[compiler-rt] r245648 - Implement __aeabi_c{d, f}{cmpeq, cmple, rcmple}.

Josh Gao via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 17:25:37 PDT 2015


Author: jmgao
Date: Thu Aug 20 19:25:37 2015
New Revision: 245648

URL: http://llvm.org/viewvc/llvm-project?rev=245648&view=rev
Log:
Implement __aeabi_c{d,f}{cmpeq,cmple,rcmple}.

Summary: Implement more missing ARM EABI runtime functions.

Reviewers: rengolin, compnerd

Subscribers: pirama, srhines, danalbert, aemerson, llvm-commits

Differential Revision: http://reviews.llvm.org/D12089

Added:
    compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmp.S
    compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c
    compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmp.S
    compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c
    compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c
    compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmple_test.c
    compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c
    compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmple_test.c
    compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.S
    compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.h
Modified:
    compiler-rt/trunk/lib/builtins/CMakeLists.txt
    compiler-rt/trunk/lib/builtins/assembly.h

Modified: compiler-rt/trunk/lib/builtins/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/CMakeLists.txt?rev=245648&r1=245647&r2=245648&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/builtins/CMakeLists.txt Thu Aug 20 19:25:37 2015
@@ -189,6 +189,10 @@ set(i686_SOURCES
 set(arm_SOURCES
   arm/adddf3vfp.S
   arm/addsf3vfp.S
+  arm/aeabi_cdcmp.S
+  arm/aeabi_cdcmpeq_check_nan.c
+  arm/aeabi_cfcmp.S
+  arm/aeabi_cfcmpeq_check_nan.c
   arm/aeabi_dcmp.S
   arm/aeabi_div0.c
   arm/aeabi_drsub.c

Added: compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmp.S
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmp.S?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmp.S (added)
+++ compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmp.S Thu Aug 20 19:25:37 2015
@@ -0,0 +1,96 @@
+//===-- aeabi_cdcmp.S - EABI cdcmp* 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_cdcmpeq(double a, double b) {
+//   if (isnan(a) || isnan(b)) {
+//     Z = 0; C = 1;
+//   } else {
+//     __aeabi_cdcmple(a, b);
+//   }
+// }
+
+        .syntax unified
+        .p2align 2
+DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
+        push {r0-r3, lr}
+        bl __aeabi_cdcmpeq_check_nan
+        cmp r0, #1
+        pop {r0-r3, lr}
+
+        // NaN has been ruled out, so __aeabi_cdcmple can't trap
+        bne __aeabi_cdcmple
+
+        msr CPSR_f, #APSR_C
+        JMP(lr)
+END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
+
+
+// void __aeabi_cdcmple(double a, double b) {
+//   if (__aeabi_dcmplt(a, b)) {
+//     Z = 0; C = 0;
+//   } else if (__aeabi_dcmpeq(a, b)) {
+//     Z = 1; C = 1;
+//   } else {
+//     Z = 0; C = 1;
+//   }
+// }
+
+        .syntax unified
+        .p2align 2
+DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple)
+        // Per the RTABI, this function must preserve r0-r11.
+        // Save lr in the same instruction for compactness
+        push {r0-r3, lr}
+
+        bl __aeabi_dcmplt
+        cmp r0, #1
+        moveq ip, #0
+        beq 1f
+
+        ldm sp, {r0-r3}
+        bl __aeabi_dcmpeq
+        cmp r0, #1
+        moveq ip, #(APSR_C | APSR_Z)
+        movne ip, #(APSR_C)
+
+1:
+        msr CPSR_f, ip
+        pop {r0-r3}
+        POP_PC()
+END_COMPILERRT_FUNCTION(__aeabi_cdcmple)
+
+// int __aeabi_cdrcmple(double a, double b) {
+//   return __aeabi_cdcmple(b, a);
+// }
+
+        .syntax unified
+        .p2align 2
+DEFINE_COMPILERRT_FUNCTION(__aeabi_cdrcmple)
+        // Swap r0 and r2
+        mov ip, r0
+        mov r0, r2
+        mov r2, ip
+
+        // Swap r1 and r3
+        mov ip, r1
+        mov r1, r3
+        mov r3, ip
+
+        b __aeabi_cdcmple
+END_COMPILERRT_FUNCTION(__aeabi_cdrcmple)
+

Added: compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c (added)
+++ compiler-rt/trunk/lib/builtins/arm/aeabi_cdcmpeq_check_nan.c Thu Aug 20 19:25:37 2015
@@ -0,0 +1,16 @@
+//===-- lib/arm/aeabi_cdcmpeq_helper.c - Helper for cdcmpeq ---------------===//
+//
+//                     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 <stdint.h>
+
+__attribute__((pcs("aapcs")))
+__attribute__((visibility("hidden")))
+int __aeabi_cdcmpeq_check_nan(double a, double b) {
+    return __builtin_isnan(a) || __builtin_isnan(b);
+}

Added: compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmp.S
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmp.S?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmp.S (added)
+++ compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmp.S Thu Aug 20 19:25:37 2015
@@ -0,0 +1,91 @@
+//===-- 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
+        pop {r0-r3, lr}
+
+        // NaN has been ruled out, so __aeabi_cfcmple can't trap
+        bne __aeabi_cfcmple
+
+        msr CPSR_f, #APSR_C
+        JMP(lr)
+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
+        moveq ip, #0
+        beq 1f
+
+        ldm sp, {r0-r3}
+        bl __aeabi_fcmpeq
+        cmp r0, #1
+        moveq ip, #(APSR_C | APSR_Z)
+        movne ip, #(APSR_C)
+
+1:
+        msr CPSR_f, ip
+        pop {r0-r3}
+        POP_PC()
+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)
+

Added: compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c (added)
+++ compiler-rt/trunk/lib/builtins/arm/aeabi_cfcmpeq_check_nan.c Thu Aug 20 19:25:37 2015
@@ -0,0 +1,16 @@
+//===-- lib/arm/aeabi_cfcmpeq_helper.c - Helper for cdcmpeq ---------------===//
+//
+//                     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 <stdint.h>
+
+__attribute__((pcs("aapcs")))
+__attribute__((visibility("hidden")))
+int __aeabi_cfcmpeq_check_nan(float a, float b) {
+    return __builtin_isnan(a) || __builtin_isnan(b);
+}

Modified: compiler-rt/trunk/lib/builtins/assembly.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/assembly.h?rev=245648&r1=245647&r2=245648&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/assembly.h (original)
+++ compiler-rt/trunk/lib/builtins/assembly.h Thu Aug 20 19:25:37 2015
@@ -73,6 +73,15 @@
 #define JMPc(r, c) mov##c pc, r
 #endif
 
+// pop {pc} can't switch Thumb mode on ARMv4T
+#if __ARM_ARCH >= 5
+#define POP_PC() pop {pc}
+#else
+#define POP_PC()                                                               \
+  pop {ip};                                                                    \
+  JMP(ip)
+#endif
+
 #if __ARM_ARCH_ISA_THUMB == 2
 #define IT(cond)  it cond
 #define ITT(cond) itt cond

Added: compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c (added)
+++ compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmpeq_test.c Thu Aug 20 19:25:37 2015
@@ -0,0 +1,70 @@
+//===-- aeabi_cdcmpeq.c - Test __aeabi_cdcmpeq ----------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __aeabi_cdcmpeq for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#if __arm__
+#include "call_apsr.h"
+
+extern __attribute__((pcs("aapcs"))) void __aeabi_cdcmpeq(double a, double b);
+
+int test__aeabi_cdcmpeq(double a, double b, int expected)
+{
+    uint32_t cpsr_value = call_apsr_d(a, b, __aeabi_cdcmpeq);
+    union cpsr cpsr = { .value = cpsr_value };
+    if (expected != cpsr.flags.z) {
+        printf("error in __aeabi_cdcmpeq(%f, %f) => Z = %d, expected %d\n",
+               a, b, cpsr.flags.z, expected);
+        return 1;
+    }
+    return 0;
+}
+#endif
+
+int main()
+{
+#if __arm__
+    if (test__aeabi_cdcmpeq(1.0, 1.0, 1))
+        return 1;
+    if (test__aeabi_cdcmpeq(1234.567, 765.4321, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(-123.0, -678.0, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(0.0, -0.0, 1))
+        return 1;
+    if (test__aeabi_cdcmpeq(1.0, NAN, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(NAN, 1.0, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(NAN, NAN, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(INFINITY, 1.0, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(0.0, INFINITY, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(-INFINITY, 0.0, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(0.0, -INFINITY, 0))
+        return 1;
+    if (test__aeabi_cdcmpeq(INFINITY, INFINITY, 1))
+        return 1;
+    if (test__aeabi_cdcmpeq(-INFINITY, -INFINITY, 1))
+        return 1;
+#else
+    printf("skipped\n");
+#endif
+    return 0;
+}

Added: compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmple_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmple_test.c?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmple_test.c (added)
+++ compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cdcmple_test.c Thu Aug 20 19:25:37 2015
@@ -0,0 +1,92 @@
+//===-- aeabi_cdcmple.c - Test __aeabi_cdcmple and __aeabi_cdrcmple -------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __aeabi_cdcmple and __aeabi_cdrcmple for the compiler_rt
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "call_apsr.h"
+
+#if __arm__
+
+extern __attribute__((pcs("aapcs"))) void __aeabi_cdcmple(double a, double b);
+extern __attribute__((pcs("aapcs"))) void __aeabi_cdrcmple(double a, double b);
+
+int test__aeabi_cdcmple(double a, double b, int expected)
+{
+    int32_t cpsr_value = call_apsr_d(a, b, __aeabi_cdcmple);
+    int32_t r_cpsr_value = call_apsr_d(b, a, __aeabi_cdrcmple);
+
+    if (cpsr_value != r_cpsr_value) {
+        printf("error: __aeabi_cdcmple(%f, %f) != __aeabi_cdrcmple(%f, %f)\n", a, b, b, a);
+        return 1;
+    }
+
+    int expected_z, expected_c;
+    if (expected == -1) {
+        expected_z = 0;
+        expected_c = 0;
+    } else if (expected == 0) {
+        expected_z = 1;
+        expected_c = 1;
+    } else {
+        // a or b is NaN, or a > b
+        expected_z = 0;
+        expected_c = 1;
+    }
+
+    union cpsr cpsr = { .value = cpsr_value };
+    if (expected_z != cpsr.flags.z || expected_c != cpsr.flags.c) {
+        printf("error in __aeabi_cdcmple(%f, %f) => (Z = %d, C = %d), expected (Z = %d, C = %d)\n",
+               a, b, cpsr.flags.z, cpsr.flags.c, expected_z, expected_c);
+        return 1;
+    }
+
+    cpsr.value = r_cpsr_value;
+    if (expected_z != cpsr.flags.z || expected_c != cpsr.flags.c) {
+        printf("error in __aeabi_cdrcmple(%f, %f) => (Z = %d, C = %d), expected (Z = %d, C = %d)\n",
+               a, b, cpsr.flags.z, cpsr.flags.c, expected_z, expected_c);
+        return 1;
+    }
+    return 0;
+}
+#endif
+
+int main()
+{
+#if __arm__
+    if (test__aeabi_cdcmple(1.0, 1.0, 0))
+        return 1;
+    if (test__aeabi_cdcmple(1234.567, 765.4321, 1))
+        return 1;
+    if (test__aeabi_cdcmple(765.4321, 1234.567, -1))
+        return 1;
+    if (test__aeabi_cdcmple(-123.0, -678.0, 1))
+        return 1;
+    if (test__aeabi_cdcmple(-678.0, -123.0, -1))
+        return 1;
+    if (test__aeabi_cdcmple(0.0, -0.0, 0))
+        return 1;
+    if (test__aeabi_cdcmple(1.0, NAN, 1))
+        return 1;
+    if (test__aeabi_cdcmple(NAN, 1.0, 1))
+        return 1;
+    if (test__aeabi_cdcmple(NAN, NAN, 1))
+        return 1;
+#else
+    printf("skipped\n");
+#endif
+    return 0;
+}

Added: compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c (added)
+++ compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmpeq_test.c Thu Aug 20 19:25:37 2015
@@ -0,0 +1,70 @@
+//===-- aeabi_cfcmpeq.c - Test __aeabi_cfcmpeq ----------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __aeabi_cfcmpeq for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#if __arm__
+#include "call_apsr.h"
+
+extern __attribute__((pcs("aapcs"))) void __aeabi_cfcmpeq(float a, float b);
+
+int test__aeabi_cfcmpeq(float a, float b, int expected)
+{
+    uint32_t cpsr_value = call_apsr_f(a, b, __aeabi_cfcmpeq);
+    union cpsr cpsr = { .value = cpsr_value };
+    if (expected != cpsr.flags.z) {
+        printf("error in __aeabi_cfcmpeq(%f, %f) => Z = %d, expected %d\n",
+               a, b, cpsr.flags.z, expected);
+        return 1;
+    }
+    return 0;
+}
+#endif
+
+int main()
+{
+#if __arm__
+    if (test__aeabi_cfcmpeq(1.0, 1.0, 1))
+        return 1;
+    if (test__aeabi_cfcmpeq(1234.567, 765.4321, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(-123.0, -678.0, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(0.0, -0.0, 1))
+        return 1;
+    if (test__aeabi_cfcmpeq(1.0, NAN, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(NAN, 1.0, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(NAN, NAN, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(INFINITY, 1.0, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(0.0, INFINITY, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(-INFINITY, 0.0, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(0.0, -INFINITY, 0))
+        return 1;
+    if (test__aeabi_cfcmpeq(INFINITY, INFINITY, 1))
+        return 1;
+    if (test__aeabi_cfcmpeq(-INFINITY, -INFINITY, 1))
+        return 1;
+#else
+    printf("skipped\n");
+#endif
+    return 0;
+}

Added: compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmple_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmple_test.c?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmple_test.c (added)
+++ compiler-rt/trunk/test/builtins/Unit/arm/aeabi_cfcmple_test.c Thu Aug 20 19:25:37 2015
@@ -0,0 +1,92 @@
+//===-- aeabi_cfcmple.c - Test __aeabi_cfcmple and __aeabi_cfrcmple -------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __aeabi_cfcmple and __aeabi_cfrcmple for the compiler_rt
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "call_apsr.h"
+
+#if __arm__
+
+extern __attribute__((pcs("aapcs"))) void __aeabi_cfcmple(float a, float b);
+extern __attribute__((pcs("aapcs"))) void __aeabi_cfrcmple(float a, float b);
+
+int test__aeabi_cfcmple(float a, float b, int expected)
+{
+    int32_t cpsr_value = call_apsr_f(a, b, __aeabi_cfcmple);
+    int32_t r_cpsr_value = call_apsr_f(b, a, __aeabi_cfrcmple);
+
+    if (cpsr_value != r_cpsr_value) {
+        printf("error: __aeabi_cfcmple(%f, %f) != __aeabi_cfrcmple(%f, %f)\n", a, b, b, a);
+        return 1;
+    }
+
+    int expected_z, expected_c;
+    if (expected == -1) {
+        expected_z = 0;
+        expected_c = 0;
+    } else if (expected == 0) {
+        expected_z = 1;
+        expected_c = 1;
+    } else {
+        // a or b is NaN, or a > b
+        expected_z = 0;
+        expected_c = 1;
+    }
+
+    union cpsr cpsr = { .value = cpsr_value };
+    if (expected_z != cpsr.flags.z || expected_c != cpsr.flags.c) {
+        printf("error in __aeabi_cfcmple(%f, %f) => (Z = %d, C = %d), expected (Z = %d, C = %d)\n",
+               a, b, cpsr.flags.z, cpsr.flags.c, expected_z, expected_c);
+        return 1;
+    }
+
+    cpsr.value = r_cpsr_value;
+    if (expected_z != cpsr.flags.z || expected_c != cpsr.flags.c) {
+        printf("error in __aeabi_cfrcmple(%f, %f) => (Z = %d, C = %d), expected (Z = %d, C = %d)\n",
+               a, b, cpsr.flags.z, cpsr.flags.c, expected_z, expected_c);
+        return 1;
+    }
+    return 0;
+}
+#endif
+
+int main()
+{
+#if __arm__
+    if (test__aeabi_cfcmple(1.0, 1.0, 0))
+        return 1;
+    if (test__aeabi_cfcmple(1234.567, 765.4321, 1))
+        return 1;
+    if (test__aeabi_cfcmple(765.4321, 1234.567, -1))
+        return 1;
+    if (test__aeabi_cfcmple(-123.0, -678.0, 1))
+        return 1;
+    if (test__aeabi_cfcmple(-678.0, -123.0, -1))
+        return 1;
+    if (test__aeabi_cfcmple(0.0, -0.0, 0))
+        return 1;
+    if (test__aeabi_cfcmple(1.0, NAN, 1))
+        return 1;
+    if (test__aeabi_cfcmple(NAN, 1.0, 1))
+        return 1;
+    if (test__aeabi_cfcmple(NAN, NAN, 1))
+        return 1;
+#else
+    printf("skipped\n");
+#endif
+    return 0;
+}

Added: compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.S
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.S?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.S (added)
+++ compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.S Thu Aug 20 19:25:37 2015
@@ -0,0 +1,43 @@
+//===-- call_apsr.S - Helpers for ARM EABI floating point tests -----------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements helpers for ARM EABI floating point tests for the
+// compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../../../lib/builtins/assembly.h"
+
+.syntax unified
+// __attribute__((pcs("aapcs")))
+// int32_t call_apsr_d(double a, double b, void(*fn)(double, double)) {
+//   fn(a, b);
+//   return apsr;
+// }
+
+DEFINE_COMPILERRT_PRIVATE_FUNCTION(call_apsr_d)
+    push {lr}
+    ldr ip, [sp, #4]
+    blx ip
+    mrs r0, apsr
+    pop {pc}
+END_COMPILERRT_FUNCTION(call_apsr_d)
+
+// __attribute__((pcs("aapcs")))
+// int32_t call_apsr_f(float a, float b, void(*fn)(float, float)) {
+//   fn(a, b);
+//   return apsr;
+// }
+
+DEFINE_COMPILERRT_PRIVATE_FUNCTION(call_apsr_f)
+    push {lr}
+    blx r2
+    mrs r0, apsr
+    pop {pc}
+END_COMPILERRT_FUNCTION(call_apsr_f)

Added: compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.h?rev=245648&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.h (added)
+++ compiler-rt/trunk/test/builtins/Unit/arm/call_apsr.h Thu Aug 20 19:25:37 2015
@@ -0,0 +1,39 @@
+//===-- call_apsr.h - Helpers for ARM EABI floating point tests -----------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares helpers for ARM EABI floating point tests for the
+// compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CALL_APSR_H
+#define CALL_APSR_H
+
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+#error big endian support not implemented
+#endif
+
+union cpsr {
+    struct {
+        uint32_t filler: 28;
+        uint32_t v: 1;
+        uint32_t c: 1;
+        uint32_t z: 1;
+        uint32_t n: 1;
+    } flags;
+    uint32_t value;
+};
+
+extern __attribute__((pcs("aapcs")))
+uint32_t call_apsr_f(float a, float b, __attribute__((pcs("aapcs"))) void (*fn)(float, float));
+
+extern __attribute__((pcs("aapcs")))
+uint32_t call_apsr_d(double a, double b, __attribute__((pcs("aapcs"))) void (*fn)(double, double));
+
+#endif // CALL_APSR_H




More information about the llvm-commits mailing list