[compiler-rt] [compiler-rt][ARM] Optimized FP double <-> single conversion (PR #179926)

Simon Tatham via llvm-commits llvm-commits at lists.llvm.org
Thu May 14 02:51:04 PDT 2026


https://github.com/statham-arm updated https://github.com/llvm/llvm-project/pull/179926

>From 9d6d4a5348da1ea60297e02059f93d419592d042 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 14:00:29 +0000
Subject: [PATCH 01/33] [compiler-rt][ARM] Enable strict mode in divsf3/mulsf3
 tests

Commit 5efce7392f3f6cc added optimized AArch32 assembly versions of
mulsf3 and divsf3, with more thorough tests. The new tests included
test cases specific to Arm's particular NaN handling rules, which are
disabled on most platforms, but were intended to be enabled for Arm.

Unfortunately, they were not enabled under any circumstances, because
I made a mistake in `test/builtins/CMakeLists.txt`: the command-line
`-D` option that should have enabled them was added to the cflags list
too early, before the list was reinitialized from scratch. So it never
ended up on the command line.

Also, the test file mulsf3.S only even _tried_ to enable strict mode
in Thumb1, even though the Arm/Thumb2 implementation would also have
met its requirements.

Because the strict-mode tests weren't enabled, I didn't notice that
they would also have failed absolutely everything, because they
checked the results using the wrong sense of comparison! I used `==`,
but that comparison was supposed to be a drop-in replacement for
`compareResultF`, which returns zero for equality. Changed the tests
to use `!=`.

Finally, I've also added a macro to each test so that it records the
source line number of each failing test case. That way, when a test
fails, you can find it in the test source more easily, without having
to search for the hex numbers mentioned in the failure message.
---
 compiler-rt/test/builtins/CMakeLists.txt     |  9 +++++----
 compiler-rt/test/builtins/Unit/divsf3_test.c | 10 ++++++----
 compiler-rt/test/builtins/Unit/mulsf3_test.c | 12 +++++++-----
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/compiler-rt/test/builtins/CMakeLists.txt b/compiler-rt/test/builtins/CMakeLists.txt
index 679dffe54f4ad..1d4e69602ee9f 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -45,10 +45,6 @@ if(APPLE)
   darwin_filter_host_archs(BUILTIN_SUPPORTED_ARCH BUILTIN_TEST_ARCH)
 endif()
 
-if(COMPILER_RT_ARM_OPTIMIZED_FP)
-  list(APPEND BUILTINS_TEST_TARGET_CFLAGS -DCOMPILER_RT_ARM_OPTIMIZED_FP)
-endif()
-
 foreach(arch ${BUILTIN_TEST_ARCH})
   set(BUILTINS_TEST_TARGET_ARCH ${arch})
   string(TOLOWER "-${arch}-${OS_NAME}" BUILTINS_TEST_CONFIG_SUFFIX)
@@ -77,6 +73,11 @@ foreach(arch ${BUILTIN_TEST_ARCH})
     endif()
   endif()
 
+  if(COMPILER_RT_ARM_OPTIMIZED_FP)
+    list(APPEND BUILTINS_TEST_TARGET_CFLAGS -DCOMPILER_RT_ARM_OPTIMIZED_FP)
+    string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}")
+  endif()
+
   if(COMPILER_RT_ENABLE_CET)
     if(NOT arch MATCHES "i?86|x86_64|AMD64")
       message(SEND_ERROR "${arch} does not support CET")
diff --git a/compiler-rt/test/builtins/Unit/divsf3_test.c b/compiler-rt/test/builtins/Unit/divsf3_test.c
index 12c5df5fdaae1..c335c22c77243 100644
--- a/compiler-rt/test/builtins/Unit/divsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/divsf3_test.c
@@ -24,23 +24,25 @@
 // Returns: a / b
 COMPILER_RT_ABI float __divsf3(float a, float b);
 
-int test__divsf3(uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep) {
+int test__divsf3(int line, uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
   float x = __divsf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
-  int ret = toRep32(x) == expected_rep;
+  int ret = toRep32(x) != expected_rep;
 #else
   int ret = compareResultF(x, expected_rep);
 #endif
 
   if (ret) {
-    printf("error in test__divsf3(%08" PRIx32 ", %08" PRIx32 ") = %08" PRIx32
+    printf("error at line %d: __divsf3(%08" PRIx32 ", %08" PRIx32 ") = %08" PRIx32
            ", expected %08" PRIx32 "\n",
-           a_rep, b_rep, toRep32(x), expected_rep);
+           line, a_rep, b_rep, toRep32(x), expected_rep);
   }
   return ret;
 }
 
+#define test__divsf3(a,b,x) test__divsf3(__LINE__,a,b,x)
+
 int main(void) {
   int status = 0;
 
diff --git a/compiler-rt/test/builtins/Unit/mulsf3_test.c b/compiler-rt/test/builtins/Unit/mulsf3_test.c
index 7dc7c8ad39c32..8460a8c117aa5 100644
--- a/compiler-rt/test/builtins/Unit/mulsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/mulsf3_test.c
@@ -16,7 +16,7 @@
 // 0x7fc00000. For the Arm optimized FP implementation, which commits to a more
 // detailed handling of NaNs, we tighten up the check and include some extra
 // test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if (__arm__ || __thumb__) && COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
@@ -24,23 +24,25 @@
 // Returns: a * b
 COMPILER_RT_ABI float __mulsf3(float a, float b);
 
-int test__mulsf3(uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep) {
+int test__mulsf3(int line, uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
   float x = __mulsf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
-  int ret = toRep32(x) == expected_rep;
+  int ret = toRep32(x) != expected_rep;
 #else
   int ret = compareResultF(x, expected_rep);
 #endif
 
   if (ret) {
-    printf("error in test__mulsf3(%08" PRIx32 ", %08" PRIx32 ") = %08" PRIx32
+    printf("error at line %d: __mulsf3(%08" PRIx32 ", %08" PRIx32 ") = %08" PRIx32
            ", expected %08" PRIx32 "\n",
-           a_rep, b_rep, toRep32(x), expected_rep);
+           line, a_rep, b_rep, toRep32(x), expected_rep);
   }
   return ret;
 }
 
+#define test__mulsf3(a,b,x) test__mulsf3(__LINE__,a,b,x)
+
 int main(void) {
   int status = 0;
 

>From a3aea535529ca7ac6e090f62a7453075adb7bbb8 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 14:21:23 +0000
Subject: [PATCH 02/33] [compiler-rt][ARM] cmake properties for complicated
 builtin sources

In the builtins library, most functions have a portable C
implementation (e.g. `mulsf3.c`), and platforms might provide an
optimized assembler implementation (e.g. `arm/mulsf3.S`). The cmake
script automatically excludes the C source file corresponding to each
assembly source file it includes. Additionally, each source file name
is automatically translated into a flag that lit tests can query, with
a name like `librt_has_mulsf3`, to indicate that a function is
available to be tested.

In future commits I plan to introduce cases where a single .S file
provides more than one function (so that they can share code easily),
and therefore, must supersede more than one existing source file.

I've introduced the `crt_supersedes` cmake property, which you can set
on a .S file to name a list of .c files that it should supersede.
Also, the `crt_provides` property can be set on any source file to
indicate a list of functions it makes available for testing, in
addition to the one implied by its name.
---
 compiler-rt/cmake/Modules/CompilerRTUtils.cmake | 12 ++++++++----
 compiler-rt/test/builtins/CMakeLists.txt        |  5 ++++-
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
index cbd18d26c0b93..a09a870ed8384 100644
--- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
+++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
@@ -450,10 +450,14 @@ function(filter_builtin_sources inout_var name)
       # and ensure that it is removed from the file list.
       get_filename_component(_name ${_file} NAME)
       string(REGEX REPLACE "\\.S$" ".c" _cname "${_name}")
-      if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_cname}")
-        message(STATUS "For ${name} builtins preferring ${_file} to ${_cname}")
-        list(REMOVE_ITEM intermediate ${_cname})
-      endif()
+      get_property(_cnames SOURCE ${_file} PROPERTY crt_supersedes)
+      set(_cnames ${_cname} ${_cnames})
+      foreach(_cname ${_cnames})
+        if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_cname}")
+          message(STATUS "For ${name} builtins preferring ${_file} to ${_cname}")
+          list(REMOVE_ITEM intermediate ${_cname})
+        endif()
+      endforeach()
     endif()
   endforeach()
   set(${inout_var} ${intermediate} PARENT_SCOPE)
diff --git a/compiler-rt/test/builtins/CMakeLists.txt b/compiler-rt/test/builtins/CMakeLists.txt
index 1d4e69602ee9f..9c7f404242f22 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -123,7 +123,10 @@ foreach(arch ${BUILTIN_TEST_ARCH})
     # "hexagon/udivsi3.S" => "udivsi3"
     # "udivsi3.c" => "udivsi3"
     get_filename_component(FILE_NAME_FILTERED "${file_name}" NAME_WE)
-    list(APPEND BUILTINS_LIT_SOURCE_FEATURES "librt_has_${FILE_NAME_FILTERED}")
+    get_property(_also_provided SOURCE "${COMPILER_RT_SOURCE_DIR}/lib/builtins/${file_name}" DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY crt_provides)
+    foreach(_function "${FILE_NAME_FILTERED}" ${_also_provided})
+      list(APPEND BUILTINS_LIT_SOURCE_FEATURES "librt_has_${_function}")
+    endforeach()
   endforeach()
 
   string(TOUPPER ${arch} ARCH_UPPER_CASE)

>From cdcb4cc7e66916f2b4a068d38825b1e6244b589c Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 16:06:10 +0000
Subject: [PATCH 03/33] [compiler-rt][ARM] Double-precision FP support
 functions

This commit adds C helper functions `dnan2`, `dnorm2` and `dunder` for
handling the less critical edge cases of double-precision arithmetic,
similar to `fnan2`, `fnorm2` and `funder` that were added in commit
f7e652127772e93.

It also adds a header file that defines some register aliases for
handling double-precision numbers in AArch32 software floating point
in an endianness-independent way, by providing aliases `xh` and `xl`
for the high and low words of the first double-precision function
argument, regardless of which of them is in r0 and which in r1, and
similarly `yh` and `yl` for the second argument in r2/r3.
---
 compiler-rt/lib/builtins/CMakeLists.txt |  3 +
 compiler-rt/lib/builtins/arm/dnan2.c    | 45 ++++++++++++++
 compiler-rt/lib/builtins/arm/dnorm2.c   | 59 +++++++++++++++++++
 compiler-rt/lib/builtins/arm/dunder.c   | 78 +++++++++++++++++++++++++
 compiler-rt/lib/builtins/arm/endian.h   | 37 ++++++++++++
 5 files changed, 222 insertions(+)
 create mode 100644 compiler-rt/lib/builtins/arm/dnan2.c
 create mode 100644 compiler-rt/lib/builtins/arm/dnorm2.c
 create mode 100644 compiler-rt/lib/builtins/arm/dunder.c
 create mode 100644 compiler-rt/lib/builtins/arm/endian.h

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index f43ef4743ff97..82ebfe0ccb322 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -455,6 +455,9 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm")
       arm/fnan2.c
       arm/fnorm2.c
       arm/funder.c
+      arm/dnan2.c
+      arm/dnorm2.c
+      arm/dunder.c
       )
   endif()
 endif()
diff --git a/compiler-rt/lib/builtins/arm/dnan2.c b/compiler-rt/lib/builtins/arm/dnan2.c
new file mode 100644
index 0000000000000..3b3bb50d3f587
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/dnan2.c
@@ -0,0 +1,45 @@
+//===-- dnan2.c - Handle double-precision NaN inputs to binary operation --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This helper function is available for use by double-precision float
+// arithmetic implementations to handle propagating NaNs from the input
+// operands to the output, in a way that matches Arm hardware FP.
+//
+// On input, a and b are floating-point numbers in IEEE 754 encoding, and at
+// least one of them must be a NaN. The return value is the correct output NaN.
+//
+// A signalling NaN in the input (with bit 51 clear) takes priority over any
+// quiet NaN, and is adjusted on return by setting bit 51 to make it quiet. If
+// both inputs are the same type of NaN then the first input takes priority:
+// the input a is used instead of b.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+
+uint64_t __compiler_rt_dnan2(uint64_t a, uint64_t b) {
+  // Make shifted-left copies of a and b to discard the sign bit. Then add 1 at
+  // the bit position where the quiet vs signalling bit ended up. This squashes
+  // all the signalling NaNs to the top of the range of 64-bit values, from
+  // 0xfff0000000000001 to 0xffffffffffffffff inclusive; meanwhile, all the
+  // quiet NaN values wrap round to the bottom, from 0 to 0x000fffffffffffff
+  // inclusive. So we can detect a signalling NaN by asking if it's greater
+  // than 0xfff0000000000000, and a quiet one by asking if it's less than
+  // 0x0010000000000000.
+  uint64_t aadj = (a << 1) + 0x0010000000000000;
+  uint64_t badj = (b << 1) + 0x0010000000000000;
+
+  if (aadj > 0xfff0000000000000)   // a is a signalling NaN?
+    return a | 0x0008000000000000; //   if so, return it with the quiet bit set
+  if (badj > 0xfff0000000000000)   // b is a signalling NaN?
+    return b | 0x0008000000000000; //   if so, return it with the quiet bit set
+  if (aadj < 0x0010000000000000)   // a is a quiet NaN?
+    return a;                      // if so, return it
+  else /* expect (badj < 0x0010000000000000) */
+    return b;                      // in that case b must be a quiet NaN
+}
diff --git a/compiler-rt/lib/builtins/arm/dnorm2.c b/compiler-rt/lib/builtins/arm/dnorm2.c
new file mode 100644
index 0000000000000..da605ca22aabe
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/dnorm2.c
@@ -0,0 +1,59 @@
+//===-- dnorm2.c - Handle double-precision denormal inputs to binary op ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This helper function is available for use by double-precision float
+// arithmetic implementations, to handle denormal inputs on entry by
+// renormalizing the mantissa and modifying the exponent to match.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+
+// Structure containing the function's inputs and outputs.
+//
+// On entry: a, b are two input floating-point numbers, still in IEEE 754
+// encoding. expa and expb are the 8-bit exponents of those numbers, extracted
+// and shifted down to the low 8 bits of the word, with no other change.
+// Neither value should be zero, or have the maximum exponent (indicating an
+// infinity or NaN).
+//
+// On exit: each of a and b contains the mantissa of the input value, with the
+// leading 1 bit made explicit, and shifted up to bit 52 (the same place it
+// would have been if the number was normalized already). If expa was zero
+// (indicating that a was denormal) then it is now represented as a normalized
+// number with an out-of-range exponent (zero or negative). The same applies to
+// expb and b.
+//
+// The sign bits from the input floating-point numbers are discarded
+// completely. The caller is expected to have stored those somewhere
+// safe already.
+struct dnorm2 {
+  uint64_t a, b;
+  uint32_t expa, expb;
+};
+
+void __compiler_rt_dnorm2(struct dnorm2 *values) {
+  values->a &= ~0xFFF0000000000000;
+  values->b &= ~0xFFF0000000000000;
+
+  if (values->expa == 0) {
+    unsigned shift = __builtin_clzll(values->a) - 11;
+    values->a <<= shift;
+    values->expa = 1 - shift;
+  } else {
+    values->a |= 0x0010000000000000;
+  }
+
+  if (values->expb == 0) {
+    unsigned shift = __builtin_clzll(values->b) - 11;
+    values->b <<= shift;
+    values->expb = 1 - shift;
+  } else {
+    values->b |= 0x0010000000000000;
+  }
+}
diff --git a/compiler-rt/lib/builtins/arm/dunder.c b/compiler-rt/lib/builtins/arm/dunder.c
new file mode 100644
index 0000000000000..026bf76d50261
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/dunder.c
@@ -0,0 +1,78 @@
+//===-- dunder.c - Handle double-precision floating-point underflow -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This helper function is available for use by double-precision float
+// arithmetic implementations to handle underflowed output values, if they were
+// computed in the form of a normalized mantissa and an out-of-range exponent.
+//
+// On input: x should be a complete IEEE 754 floating-point value representing
+// the desired output scaled up by 2^1536 (the same value that would have been
+// passed to an underflow trap handler in IEEE 754:1985).
+//
+// This isn't enough information to re-round to the correct output denormal
+// without also knowing whether x itself has already been rounded, and which
+// way. 'errsign' gives this information, by indicating the sign of the value
+// (true result - x). That is, if errsign > 0 it means the true value was
+// larger (x was rounded down); if errsign < 0 then x was rounded up; if
+// errsign == 0 then x represents the _exact_ desired output value.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+
+#define SIGNBIT 0x8000000000000000
+#define MANTSIZE 52
+#define BIAS 0x600
+
+uint64_t __compiler_rt_dunder(uint64_t x, uint32_t errsign) {
+  uint64_t sign = x & SIGNBIT;
+  uint64_t exponent = (x << 1) >> 53;
+
+  // Rule out exponents so small (or large!) that no denormalisation
+  // is needed.
+  if (exponent > BIAS) {
+    // Exponent 0x601 or above means a normalised number got here by
+    // mistake, so we just remove the 0x600 exponent bias and go
+    // straight home.
+    return x - ((uint64_t)BIAS << MANTSIZE);
+  }
+  uint32_t bits_lost = BIAS + 1 - exponent;
+  if (bits_lost > MANTSIZE + 1) {
+    // The implicit leading 1 of the intermediate value's mantissa is
+    // below the lowest mantissa bit of a denormal by at least 2 bits.
+    // Round down to 0 unconditionally.
+    return sign;
+  }
+
+  // Make the full mantissa (with leading bit) at the top of the word.
+  uint64_t mantissa = 0x8000000000000000 | (x << 11);
+  // Adjust by 1 depending on the sign of the error.
+  mantissa -= errsign >> 31;
+  mantissa += (-errsign) >> 31;
+
+  // Shift down to the output position, keeping the bits shifted off.
+  uint64_t outmant, shifted_off;
+  if (bits_lost == MANTSIZE + 1) {
+    // Special case for the exponent where we have to shift the whole
+    // of 'mantissa' off the bottom of the word.
+    outmant = 0;
+    shifted_off = mantissa;
+  } else {
+    outmant = mantissa >> (11 + bits_lost);
+    shifted_off = mantissa << (64 - (11 + bits_lost));
+  }
+
+  // Re-round.
+  if (shifted_off >> 63) {
+    outmant++;
+    if (!(shifted_off << 1))
+      outmant &= ~1; // halfway case: round to even
+  }
+
+  return sign | outmant;
+}
diff --git a/compiler-rt/lib/builtins/arm/endian.h b/compiler-rt/lib/builtins/arm/endian.h
new file mode 100644
index 0000000000000..f603fa9cc678f
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/endian.h
@@ -0,0 +1,37 @@
+//===-- endian.h - make double-prec software FP work in both endiannesses -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file should be included from assembly source code (not C). It
+// defines two pairs of register aliases, for handling 64-bit values passed and
+// returned from functions in the AArch32 integer registers:
+//
+//   xh, xl      the high and low words of a 64-bit value passed in {r0,r1}
+//   yh, yl      the high and low words of a 64-bit value passed in {r2,r3}
+//
+// Which alias goes with which register depends on endianness.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef COMPILER_RT_ARM_FP_ENDIAN_H
+#define COMPILER_RT_ARM_FP_ENDIAN_H
+
+#ifdef __BIG_ENDIAN__
+// Big-endian: high words are in lower-numbered registers.
+xh .req r0
+xl .req r1
+yh .req r2
+yl .req r3
+#else
+// Little-endian: low words are in lower-numbered registers.
+xl .req r0
+xh .req r1
+yl .req r2
+yh .req r3
+#endif
+
+#endif // COMPILER_RT_ARM_FP_ENDIAN_H

>From e51630b7ca2fe0798b51dbf5648705088fda4b43 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 16:06:40 +0000
Subject: [PATCH 04/33] [compiler-rt][ARM] Optimized double precision FP
 add/sub

The one new assembly source file, `arm/adddf3.S`, implements both
addition and subtraction via cross-branching after flipping signs,
since both operations must provide substantially the same logic. The
new cmake properties introduced in a prior commit are used to arrange
that including `adddf3.S` supersedes the C versions of both addition
and subtraction, and also informs the test suite that both functions
are available to test.
---
 compiler-rt/lib/builtins/CMakeLists.txt       |    3 +
 compiler-rt/lib/builtins/arm/adddf3.S         | 1138 +++++++++++++++++
 .../test/builtins/Unit/adddf3new_test.c       |  382 ++++++
 .../test/builtins/Unit/subdf3new_test.c       |  393 ++++++
 4 files changed, 1916 insertions(+)
 create mode 100644 compiler-rt/lib/builtins/arm/adddf3.S
 create mode 100644 compiler-rt/test/builtins/Unit/adddf3new_test.c
 create mode 100644 compiler-rt/test/builtins/Unit/subdf3new_test.c

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 82ebfe0ccb322..6c01c7ec9d95f 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -447,6 +447,7 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm")
     set(assembly_files
       arm/mulsf3.S
       arm/divsf3.S
+      arm/adddf3.S
       )
     set_source_files_properties(${assembly_files}
       PROPERTIES COMPILE_OPTIONS ${implicit_it_flag})
@@ -494,6 +495,8 @@ set(thumb1_base_SOURCES
   arm/addsf3.S
   ${GENERIC_SOURCES}
 )
+set_property(SOURCE arm/adddf3.S PROPERTY crt_supersedes subdf3.c)
+set_property(SOURCE arm/adddf3.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY crt_provides subdf3)
 
 if(COMPILER_RT_ARM_OPTIMIZED_FP)
   set(thumb1_base_SOURCES
diff --git a/compiler-rt/lib/builtins/arm/adddf3.S b/compiler-rt/lib/builtins/arm/adddf3.S
new file mode 100644
index 0000000000000..b2c1edfeb2fa3
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/adddf3.S
@@ -0,0 +1,1138 @@
+//===-- adddf3.S - Add/subtract double precision floating point numbers ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the __adddf3 and __subdf3 functions (double precision
+// floating point number addition and subtraction), with the IEEE-754 default
+// rounding (to nearest, ties to even), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+// General structure of this code:
+//
+// There are three actual entry points here, for addition, subtraction and
+// reversed subtraction (just taking the operands the other way round, so that
+// it returns y-x instead of x-y). But the first thing the functions do (after
+// checking for NaNs) is to sort out whether the magnitudes of the two inputs
+// are being added (x+y with like signs, or x-y with different signs), or
+// subtracted. So dadd jumps across into the middle of dsub if it sees that the
+// signs are different, and vice versa. Then the main code path in dadd handles
+// magnitude addition, and the one in dsub handles magnitude subtraction.
+//
+// NaNs are checked first, so that an input NaN can be propagated exactly,
+// including its sign bit. After ruling out that case, it's safe to flip the
+// sign of one of the inputs, so that during the cross-calls, x - y can be
+// rewritten as x + (-y) and vice versa.
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__adddf3)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  VMOV_FROM_DOUBLE(r2, r3, d1)
+  bl __aeabi_dadd
+  VMOV_TO_DOUBLE(d0, r0, r1)
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__adddf3, __aeabi_dadd)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_dadd)
+
+  push    {r4, r14}
+
+  // Test for all uncommon values at once: infinities, NaNs, denormals and
+  // zeroes. Branch out of line if any are found. We do this by incrementing
+  // the exponent of each input, so that the two extreme exponents 0x7ff,0x000
+  // map to 0x000,0x001 respectively. Then the original number had one of those
+  // exponents precisely when the modified version has the top 10 exponent bits
+  // zero.
+  //
+  // The constant we load into r14 for testing those ten exponent bits will be
+  // reused later. (We could load a constant suitable for just this initial
+  // test slightly more efficiently by writing MOVW r14,#0x3ff or similar, but
+  // having the set bits at the top of the word is useful later because we can
+  // extend them using ASR.)
+  ldr     r14, =0xFFC00000
+  add     r12, xh, #1 << 20   // r12 has the adjusted version of x's exponent
+  add     r4, yh, #1 << 20    // and r4 the adjusted version of y's
+  tst     r14, r12, lsl #1    // test the top 10 exponent bits of each
+  tstne   r14, r4, lsl #1
+  beq     LOCAL_LABEL(add_uncommon)       // and branch out of line if either is 0
+
+  // Now we have two normalised numbers. If their signs are opposite, we should
+  // be subtracting their magnitudes rather than adding, so cross-jump to dsub.
+  teq     xh, yh
+  eormi   yh, yh, #1 << 31
+  bmi     LOCAL_LABEL(sub_magnitude)
+LOCAL_LABEL(add_magnitude):
+  // If we get here, we're adding operands with equal signs (i.e. a magnitude
+  // addition). First thing to do is put the operands in magnitude order, so
+  // that x >= y.
+  subs    r4, xl, yl          // compare inputs, also keeping x-y
+  sbcs    r12, xh, yh
+  bhs     LOCAL_LABEL(add_swapped)        // if x>=y then branch round the swap
+  adds    yl, yl, r4          // otherwise turn y into x by adding (x-y)
+  adc     yh, yh, r12
+  subs    xl, xl, r4          // and turn x into y by subtracting it
+  sbc     xh, xh, r12
+LOCAL_LABEL(add_swapped):
+  // Keep the sign and exponent of the larger input, to use as the sign and
+  // exponent of the output (up to carries and overflows). Also calculate the
+  // exponent difference, which tells us how far we'll need to shift y's
+  // mantissa right to add it to x's.
+  //
+  // The shifted-right values will include the sign bits as well as the
+  // exponents, but both sign bits are the same, so they'll cancel.
+  lsr     r4, xh, #20            // r4 = initial sign+exponent of the output
+  sub     r12, r4, yh, lsr #20   // r12 = exponent difference
+
+  // Clear the exponents and signs off the numbers to prepare for the addition.
+  // (We reuse the value 0xffc00000 that we left in r14 on entry: ASRing that
+  // right by 2 gives 0xfff00000, just the bit mask we wanted.)
+  //
+  // Also OR in the leading 1 bit of y's mantissa, so that when we shift it
+  // right and add, it will be included in the addition.
+  //
+  // (It's cheaper not to bother doing the same for x, unless the addition
+  // carries into the exponent.)
+  bic     xh, xh, r14, asr #2
+  bic     yh, yh, r14, asr #2
+  orr     yh, yh, #1 << 20
+
+LOCAL_LABEL(add_doadd):
+  // Here we perform the actual addition. We either fell through from the code
+  // above, or jumped back to here after handling an input denormal.
+  //
+  // We get here with:
+  //   Operands known to be numeric rather than zero/infinity/NaN;
+  //   xh:xl = mantissa of larger operand, with low bit at the bottom of xl
+  //   yh:yl = mantissa of smaller operand, with low bit at the bottom of yl
+  //   r4 = result sign and exponent (in low 12 bits);
+  //   r12 = exponent difference.
+  //
+  // For normal inputs, the mantissa of y will have the leading bit set.
+  // Denormals will leave that bit clear, treating the number as 0.[mantissa] x
+  // 2^(fixed exponent) instead of renormalising to 1.[mantissa] x 2^(variable
+  // exponent) as a multiplication would want.
+
+  // The main addition involves shifting y right by the exponent difference in
+  // r12, and adding it to x. This must be done differently depending on how
+  // big the exponent difference is. Start by checking if it's at most 32.
+  rsbs    r14, r12, #32
+  blo     LOCAL_LABEL(add_bigshift)
+
+  // The exponent difference is 32 or less. The test above also left
+  // (32-difference) in r14, which is the amount we need to shift yh left by to
+  // recover the bits that the right shift will lose off the bottom.
+#if !__thumb__
+  // Add the right-shifted parts of yh and yl to xh and xl, keeping the carry
+  // in between if any.
+  adds    xl, xl, yl, lsr r12
+  adc     xh, xh, yh, lsr r12
+  // Now add the remainder of yh to the low word, again checking for a carry.
+  adds    xl, xl, yh, lsl r14
+  adcs    xh, xh, #0
+#else
+  // Thumb can't fold a register-controlled shift into an add, so we must use
+  // two separate instructions in each case.
+  //
+  // We don't have any more spare registers, so we'll use r14 as a temporary
+  // register to hold each shifted value before adding it to something. This
+  // clobbers the inverted shift count in r14, which we're going to need again
+  // during rounding, so we must recompute it after the additions are complete.
+  // (It would cost more cycles to avoid that awkwardness by pushing and
+  // popping an extra register around the whole function.)
+  //
+  // To avoid recomputing r14 _twice_, we do the addition of (yh shifted left)
+  // first, so we can use the value in r14 before clobbering it at all.
+  lsl     r14, yh, r14
+  adds    xl, xl, r14
+  adcs    xh, xh, #0
+  // Now do the addition of (yh shifted right) and (yl shifted right).
+  lsr     r14, yl, r12
+  adds    xl, xl, r14
+  lsr     r14, yh, r12
+  adc     xh, xh, r14
+  // And now reconstruct the inverted shift count, for use later.
+  rsb     r14, r12, #32
+#endif
+
+  // If that addition carried into bit 20 of xh, then the number has increased
+  // its exponent. Diverge into a completely separate code path for that case,
+  // because there we must check for overflow.
+  cmp     xh, #1 << 20
+  bhs     LOCAL_LABEL(add_carry)
+
+  // Here, on the non-carrying path, we don't need to check for overflow at
+  // all. If there is an overflow it can only be due to rounding up, so the
+  // overflowed mantissa will be all zeroes, so the naively generated output
+  // will look like the correct infinity anyway.
+  //
+  // Recombine the mantissa with the sign + exponent (in r4) via addition.
+  add     xh, xh, r4, lsl #20
+  // Now our number is complete apart from rounding.
+
+LOCAL_LABEL(add_nocarry):
+  // This is the general rounding path for additions that didn't carry into the
+  // next exponent. We come here with the unrounded output in xh:xl, and yl and
+  // r14 set up so that (yl << r14) consists of all the bits shifted off the
+  // bottom of y's mantissa, or at least some approximation to them good enough
+  // to make the right rounding decision.
+  //
+  // Perform that shift, which sets the N flag if we need to round.
+  lsls    yl, yl, r14
+
+  // We're done with our two extra registers, so we can pop them.
+  pop     {r4, r14}
+
+  // If N is clear, we're rounding down (or the result was exact), and we know
+  // there was no overflow either, so xh:xl contains the correct output and we
+  // can return immediately.
+  bxpl    lr
+
+  // Otherwise, we're rounding up, or rounding to even. Start by incrementing
+  // the low word of the output.
+  adds    xl, xl, #1
+
+  // The obvious thing to do next would be to ADC xh, xh, #0, propagating any
+  // carry from that ADDS, and completing the addition of 1 to the 64-bit value
+  // in xh:xl. But we can do better, by doing a combined test for that carry
+  // _and_ round-to-even, and returning as quickly as possible in the common
+  // case where neither has happened.
+  //
+  // The Z flag is set if the addition to xl carried, and clear if it didn't.
+  // So if Z is clear, we also test the bits of yl below the round bit. Then if
+  // Z is still clear, there was no carry into xh _and_ no round to even, so we
+  // can return.
+  lslsne  yl, yl, #1
+  bxne    lr
+
+  // Now we know that we've just incremented xl, and either or both of these
+  // things is true:
+  //
+  //  1. this is a halfway case that needs rounding to even
+  //  2. the increment of xl wrapped it round from 0xFFFFFFFF to 0
+  //
+  // We can reliably tell if #2 is true by checking if xl = 0. If that is so,
+  // we must increment xh. On the other hand, if xl != 0, then #1 must be true,
+  // so we clear the low bit of xl to complete the round-to-even.
+  //
+  // What if _both_ are true? Luckily, it doesn't matter, because if xl = 0
+  // then its low bit is already clear, so it makes no difference whether we
+  // clear it or not.
+  cmp     xl, #0                  // is xl 0?
+  bicne   xl, xl, #1              // if not, then round to even
+  adceq   xh, xh, #0              // if so, then increment xh
+  bx      lr
+
+LOCAL_LABEL(add_bigshift):
+  // We come here from dadd_doadd if y's mantissa must be shifted right by more
+  // than 32 bits. So all of yl is going to be shifted off the bottom, not
+  // _even_ into the bit that determines rounding up or down. Therefore we can
+  // approximate it well enough by a single bit at the bottom of yh, which is 1
+  // if any bit of yl is 1.
+  //
+  // We put the modified value in yl, which is where the rounding code (shared
+  // with the case for shift <= 32 bits) will expect to find the value it has
+  // to shift left to make the round word.
+  cmp     yl, #1                  // set C if yl >= 0
+  adc     yl, yh, yh              // shift yh left 1, putting C at the bottom
+
+  // Calculate shift counts. r12 is adjusted down by 32 so it tells us how much
+  // to shift yh right by when adding; r14 is the distance to shift yl left by
+  // to make the round word (again where the shared rounding code will expect
+  // to find it).
+  //
+  // The second instruction also has the side effect of checking whether the
+  // shift count in r12 is greater than 31, which we'll use in a moment.
+  sub     r12, r12, #32
+  rsbs    r14, r12, #31
+
+  // Double precision exponents are bigger than 8 bits, so it's possible that
+  // the exponent difference is > 255. AArch32 shift operations tolerate shifts
+  // bigger than the size of the word, but only up to 255, because they only
+  // look at the low 8 bits. So we must detect that r12 was huge, and handle it
+  // specially.
+  //
+  // In this situation we reset r14 to 0, so that the rounding code will not
+  // shift yl left at all. Since the top bit of yl is clear (we made yl by
+  // shifting the top word of a mantissa left by 1, so its highest set bit is
+  // at most bit 21), the effect is to consider _all_ of y's mantissa to be
+  // lower than the round bit.
+  movlo   r14, #0
+
+  // Do the actual addition, again conditionalised on the result of checking
+  // whether the shift count r12 was too big.
+#if !__thumb__
+  addshs  xl, xl, yh, lsr r12
+#else
+  lsrhs   yh, yh, r12
+  addshs  xl, xl, yh
+#endif
+
+  // Recombine the (unrounded) output mantissa with the output sign and
+  // exponent in r4. This also propagates any carry from xl into xh, from the
+  // addition. (Luckily the condition for skipping the addition also implies
+  // C=0, so in that situation, the ADC is still harmless.)
+  adc     xh, xh, r4, lsl #20
+
+  // Check whether the addition carried into the exponent field, by seeing if
+  // the exponent that ended up at the top of xh is the same as the one in r4
+  // that we just added. If it is the same (no carry) then we can go to
+  // dadd_nocarry to do the easy version of rounding that doesn't also need to
+  // check overflow.
+  cmp     r4, xh, lsr #20
+  beq     LOCAL_LABEL(add_nocarry)
+
+  // Otherwise, the addition has carried into the exponent. Subtract the
+  // exponent and sign off again, because dadd_carry (again shared with the
+  // small-shift code) will need those not to be in xh, because it will need to
+  // shift just the mantissa down by a bit.
+  sub     xh, xh, r4, lsl #20
+
+LOCAL_LABEL(add_carry):
+  // We get here from both shift branches if magnitude addition overflowed the
+  // input mantissa, so that the output will have an exponent one larger than
+  // the larger input.
+  //
+  // xh:xl was the larger input mantissa _without_ its leading 1, which we then
+  // added y's mantissa to. So before we shift down, we must put on the
+  // explicit leading 1.
+  add     xh, xh, #1 << 20
+  lsrs    xh, xh, #1
+  rrxs    xl, xl
+  // Now we can put the sign and exponent back on.
+  add     xh, xh, r4, lsl #20
+
+  // The right shift left the round bit in C. So if that's clear, we're not
+  // rounding up; we only have to check for overflow and then we can return.
+  bcc     LOCAL_LABEL(add_check_overflow_pop)
+
+  // Otherwise, set up for the combined dadd_roundeven_or_roundup_carry code:
+  // round up by incrementing the low word of xl, leaving the carry bit set if
+  // xh needs to be incremented too. If that addition _didn't_ carry, make the
+  // round word in r14 that's zero if we need to round to even. Then Z is set
+  // in either case, and otherwise, we only have overflow checking left to do.
+  adds    xl, xl, #1              // set Z if there's a carry
+  lslsne  r14, yl, r14            // else set Z if we need to round to even
+  pop     {r4, r14}
+  bne     LOCAL_LABEL(add_check_overflow)     // if Z not set for either reason, done
+
+LOCAL_LABEL(add_roundeven_or_roundup_carry):
+  // Just as in the dadd_nocarry case above, here we know that we've just
+  // incremented xl, and we either need to propagate a carry into xh, or we
+  // need to round to even, or both. See the comment there for explanation of
+  // these three instructions.
+  //
+  // The difference in this case is that after we've done that, we also need to
+  // check for overflow, where dadd_nocarry knew that wasn't necessary.
+  cmp     xl, #0                  // is xl 0?
+  bicne   xl, xl, #1              // if not, then round to even
+  adceq   xh, xh, #0              // if so, then increment xh
+  // We come here with a result ready to be returned, except that we have to
+  // check it for overflow first.
+LOCAL_LABEL(add_check_overflow):
+  lsl     yh, xh, #1              // move exponent into top 11 bits of yh
+  cmp     yh, #0xFFE00000         // if yh >= this, then exponent is all 1s
+  bxlo    lr                      // otherwise, no overflow
+
+  // If we haven't just returned, then we have an overflow. In addition we can
+  // only overflow by up to a factor of 2, so the sign bit in xh is still
+  // correct, and even the exponent has all its bits set. We only need to clear
+  // the mantissa.
+  mov     xl, #0                   // clear low word
+  lsrs    xh, xh, #20
+  lsls    xh, xh, #20
+  bx      lr
+
+  // Alternative entry point to dadd_check_overflow above, for use when the
+  // registers pushed at the start of the function haven't been popped yet.
+LOCAL_LABEL(add_check_overflow_pop):
+  pop     {r4, r14}
+  b       LOCAL_LABEL(add_check_overflow)
+
+LOCAL_LABEL(add_uncommon):
+  // We come here from the start of the function if we detected that either
+  // input had exponent 0x7ff or 0x000: that is, at least one operand is a NaN,
+  // infinity, denormal or zero.
+  //
+  // First detect whether there are any NaNs or infinities, by checking more
+  // specifically if either input has exponent 0x7ff. We take advantage of
+  // knowing that r14 was set to 0xFFC00000 in the function prologue, so we can
+  // make a useful constant for this test by adjusting it.
+  orr     r14, r14, #0x00200000   // now r14 = 0xFFE00000
+  bics    r4, r14, xh, lsl #1     // if x has exponent 0x7ff, this sets r4=0
+  bicsne  r4, r14, yh, lsl #1     // and similarly for y
+  beq     LOCAL_LABEL(add_naninf)             // so if either set Z, we have a NaN or inf
+
+  // Now we've ruled out NaNs and infinities. With NaNs gone, it's safe to flip
+  // the signs of the inputs (which only mattered for returning the right NaN).
+  // So check if the signs are the same, and cross-jump to dsub_zerodenorm
+  // (magnitude subtraction involving a zero or denormal) if not. Meanwhile,
+  // that will cross-jump back to here in the opposite case.
+  teq     xh, yh
+  eormi   yh, yh, #1 << 31
+  bmi     LOCAL_LABEL(sub_zerodenorm)
+LOCAL_LABEL(add_zerodenorm):
+  // Now we know we're doing a magnitude addition, involving at least one zero
+  // or denormal, and no NaNs or infinities.
+  //
+  // Sort the operands into magnitude order so that x >= y, exactly as in the
+  // main code path.
+  subs    r4, xl, yl          // compare inputs, also keeping x-y
+  sbcs    r12, xh, yh
+  bhs     LOCAL_LABEL(add_zerodenorm_swapped) // if x>=y then branch round the swap
+  adds    yl, yl, r4          // otherwise turn y into x by adding (x-y)
+  adc     yh, yh, r12
+  subs    xl, xl, r4          // and turn x into y by subtracting it
+  sbc     xh, xh, r12
+LOCAL_LABEL(add_zerodenorm_swapped):
+  // Set up the output sign+exponent, and the exponent difference, again
+  // exactly as in the main code path.
+  lsr     r4, xh, #20            // r4 = initial sign+exponent of the output
+  sub     r12, r4, yh, lsr #20   // r12 = exponent difference
+
+  // With the operands sorted so that y is smallest, and knowing there's at
+  // least one zero or denormal present, we know furthermore that if there's
+  // zero at all then it's y. And if y=0, then _whatever_ is in x is the right
+  // answer to return from the whole operation, whether it's another zero, a
+  // denormal, or normalised.
+  orrs    r14, yl, yh, lsl #1     // test all bits of y except the sign bit
+  popeq   {r4, pc}                // if they're all zero, we're done
+
+  // Otherwise, there are no zeroes, so y must be denormal, and we don't yet
+  // know if x is denormal too.
+  //
+  // If x isn't denormal, we rejoin the main code path for adding normalised
+  // numbers, with everything set up as dadd_doadd expects. It's easiest to
+  // represent the denormal y the same way the FP format does, as a mantissa
+  // without its leading bit set, shifted by the same amount as normalised
+  // numbers of the lowest exponent. (Renormalising via CLZ is more work, and
+  // not needed for addition.)
+  //
+  // To tell the main code that y's mantissa should be shifted by the same
+  // amount as a number with exponent 0x001, we must adjust the exponent
+  // difference r12 by one, because we've already made that by subtracting the
+  // _raw_ exponent values.
+
+  lsls    r14, r4, #21          // output exp = 0? If so, x is denormal too
+  bic     xh, xh, r4, lsl #20   // clear sign+exponent from top of x
+  bicne   yh, yh, #1 << 31      // if x not denormal, clear sign of y
+  subne   r12, r12, #1          //   and adjust exponent difference
+  bne     LOCAL_LABEL(add_doadd)            //   and rejoin the main path
+
+  // If we didn't take that branch, then both operands are denormal. In that
+  // situation we can simply do a 64-bit _integer_ addition of the values we
+  // have already! Both inputs represent numbers less than 2^52, with the same
+  // exponent; so adding them produces a number less than 2^53, which means
+  // it's either still a denormal, or if the addition carried into bit 52 then
+  // it's become a normalised number, with the mantissa still scaled by the
+  // same factor relative to the true value.
+  //
+  // The only tricky part is the sign bit. But we cleared that out of xh above,
+  // and haven't cleared it out of yh, so there's exactly one copy of it
+  // involved in this addition. So the sign bit will end up correct at the top
+  // of xh too.
+  adds    xl, xl, yl
+  adc     xh, xh, yh
+  pop     {r4, pc}
+
+LOCAL_LABEL(add_naninf):
+  // We come here knowing that at least one operand is either NaN or infinity.
+  // If there's a NaN, we can tailcall __dnan2 to do the right thing. Pop our
+  // stacked registers first: we won't need that much spare space any more, and
+  // it makes the tailcall easier if we've already done it.
+  pop     {r4, r14}
+
+  // A number is a NaN if its exponent is 0x7ff and at least one bit below that
+  // is set. The CMP + ADC pair here converts the two words xh:xl into a single
+  // word containing xh shifted up by one (throwing away the sign bit which
+  // makes no difference), with its low bit set if xl was nonzero. So if that
+  // is strictly greater than 0xffe00000, then x was a NaN.
+  cmp     xl, #1
+  adc     r12, xh, xh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+  // Now check y in the same way.
+  cmp     yl, #1
+  adc     r12, yh, yh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+
+LOCAL_LABEL(add_inf):
+  // Now we know there are no NaNs. Therefore there's at least one infinity. If
+  // we have two infinities of opposite sign, that's an invalid operation and
+  // we must return NaN; this happens if and only if x XOR y is all zero except
+  // for the top bit.
+  eor     r12, xh, yh
+  cmp     r12, #0x80000000
+  eorseq  r12, xl, yl
+  beq     LOCAL_LABEL(addsub_return_nan)
+
+  // Otherwise, only one sign of infinity is involved in our addition, so
+  // return whichever operand is the infinity. Since we know there are no NaNs,
+  // we can identify an infinity from just its exponent.
+  lsl     r12, xh, #1
+  cmp     r12, #0xFFE00000
+  bxeq    lr
+  movs    xh, yh
+  movs    xl, yl
+  bx      lr
+
+LOCAL_LABEL(addsub_return_nan):
+  // Return the default NaN, in the case of adding +inf to -inf.
+  movw    xh, 0x7ff8
+  lsls    xh, xh, #16        // 0x7ff80000 is the high word of the default NaN
+  mov     xl, #0             // and the low word is 0
+  bx      lr
+
+END_COMPILERRT_FUNCTION(__aeabi_dadd)
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_drsub)
+  // Reversed subtraction, that is, compute y-x, where x is in r0/r1 and y in
+  // r2/r3.
+  //
+  // We could implement this by simply swapping the register pairs. But the
+  // point of having a reversed-subtract in the first place is to avoid the
+  // caller having to do that, so if we do it ourselves, it wastes all the time
+  // they saved. So instead, on the fast path, we redo the sign check our own
+  // way and branch to dadd_magnitude or dsub_magnitude.
+
+  push    {r4, r14}
+
+  // Start by testing for uncommon operands in the same way as dadd.
+  ldr     r14, =0xFFC00000
+  add     r12, xh, #1 << 20   // r12 has the adjusted version of x's exponent
+  add     r4, yh, #1 << 20    // and r4 the adjusted version of y's
+  tst     r14, r12, lsl #1    // test the top 10 exponent bits of each
+  tstne   r14, r4, lsl #1
+  beq     LOCAL_LABEL(rsub_uncommon)      // and branch out of line if either is 0
+
+  // Check if the signs are equal, and branch to one or the other of
+  // dadd_magnitude and dsub_magnitude.
+  //
+  // If the signs are unequal, then y-x is a magnitude addition: we negate x so
+  // that we're computing y + (-x), in which both values have the same sign and
+  // go to dadd_magnitude. If the signs are equal then y-x is a magnitude
+  // subtraction, equal to (-x) - (-y), so we negate both operands and go to
+  // dsub_magnitude. Since x needs to be negated in both cases, we can do that
+  // unconditionally.
+  teq     xh, yh              // N set for a magnitude addition
+  eor     xh, xh, #1 << 31    // negate x unconditionally
+  bmi     LOCAL_LABEL(add_magnitude)      // branch away for magnitude addition
+  eor     yh, yh, #1 << 31    // otherwise, negate y too
+  b       LOCAL_LABEL(sub_magnitude)      // and do a magnitude subtraction
+
+LOCAL_LABEL(rsub_uncommon):
+  // Any uncommon operands to drsub are handled by just swapping the two
+  // operands and going to dsub's handler. We're off the main fast path now, so
+  // there's no need to try to optimise it any harder.
+  eor     xh, xh, yh
+  eor     xl, xl, yl
+  eor     yh, yh, xh
+  eor     yl, yl, xl
+  eor     xh, xh, yh
+  eor     xl, xl, yl
+  b       LOCAL_LABEL(sub_uncommon)
+
+END_COMPILERRT_FUNCTION(__aeabi_drsub)
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__subdf3)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  VMOV_FROM_DOUBLE(r2, r3, d1)
+  bl __aeabi_dsub
+  VMOV_TO_DOUBLE(d0, r0, r1)
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__subdf3, __aeabi_dsub)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_dsub)
+  // Main entry point for subtraction.
+
+  push    {r4, r14}
+
+  // Start by testing for uncommon operands in the same way as dadd.
+  ldr     r14, =0xFFC00000
+  add     r12, xh, #1 << 20   // r12 has the adjusted version of x's exponent
+  add     r4, yh, #1 << 20    // and r4 the adjusted version of y's
+  tst     r14, r12, lsl #1    // test the top 10 exponent bits of each
+  tstne   r14, r4, lsl #1
+  beq     LOCAL_LABEL(sub_uncommon)       // and branch out of line if either is 0
+
+  // Check the signs, and if they're unequal, cross-jump into dadd to do
+  // magnitude addition. (Now we've excluded NaNs, it's safe to flip the sign
+  // of y.)
+  teq     xh, yh
+  eormi   yh, yh, #1 << 31
+  bmi     LOCAL_LABEL(add_magnitude)
+LOCAL_LABEL(sub_magnitude):
+  // If we get here, we're subtracting operands with equal signs (i.e. a
+  // magnitude subtraction). First thing to do is put operands in magnitude
+  // order, so that x >= y. However, if they are swapped, we must also negate
+  // both of them, since A - B = (-B) - (-A). We do this by flipping the top
+  // bit of the value we add/subtract to each input to perform the swap
+  subs    r4, xl, yl          // compare inputs, also keeping x-y
+  sbcs    r12, xh, yh
+  bhs     LOCAL_LABEL(sub_swapped)        // if x>=y then branch round the swap
+  eor     r12, r12, #1 << 31  // flip the top bit of x-y
+  adds    yl, yl, r4          // so that this addition turns y into x+TOPBIT
+  adc     yh, yh, r12
+  subs    xl, xl, r4          // and this subtraction turns x into y-TOPBIT
+  sbc     xh, xh, r12
+LOCAL_LABEL(sub_swapped):
+  // Keep the sign and exponent of the larger input, to use as the sign and
+  // exponent of the output (up to carries and overflows). Also calculate the
+  // exponent difference, which tells us how far we'll need to shift y's
+  // mantissa right to add it to x's.
+  //
+  // As in dadd, the values being subtracted both include the sign bit, but
+  // we've already ensured the sign bits are the same (if we came here from
+  // dadd then we flipped the sign of y), so as in dadd, they cancel.
+  lsr     r4, xh, #20
+  sub     r12, r4, yh, lsr #20
+
+  // Isolate the two mantissas.
+  bic     xh, xh, r4, lsl #20
+  bic     yh, yh, r14, asr #2     // 0xffc00000 ASR 2 = 0xfff00000
+
+  // Negate the mantissa of y, so that we can compute the difference using
+  // ADD/ADC. As a side effect we also add in the leading bit of y's mantissa,
+  // by subtracting y from 0xfff0000000000000 instead of from 0.
+  rsbs    yl, yl, #0
+#if !__thumb__
+  rsc     yh, yh, r14, asr #2     // 0xffc00000 ASR 2 = 0xfff00000
+#else
+  // Thumb has no RSC, so simulate it by bitwise inversion and then ADC
+  mvn     yh, yh
+  adc     yh, yh, r14, asr #2     // 0xffc00000 ASR 2 = 0xfff00000
+#endif
+
+LOCAL_LABEL(sub_dosub):
+  // Here we perform the actual subtraction. We either fell through from the
+  // code above, or jumped back to here after handling an input denormal.
+  //
+  // We get here with:
+  //   Operands known to be numeric rather than zero/infinity/NaN;
+  //   xh:xl = mantissa of larger operand, with low bit at the bottom of xl
+  //   yh:yl = negated mantissa of smaller operand, similarly
+  //   r4 = result sign and exponent (in low 12 bits);
+  //   r12 = exponent difference.
+  //
+  // For normal inputs, the value in yh:yl will be as if the mantissa of y had
+  // the leading bit set before negating it. For denormal y, the mantissa will
+  // have been negated without setting that bit, similarly to dadd.
+
+  // As in dadd, we start by separating off the case where we're shifting the
+  // mantissa of y right by more than 32 bits.
+  rsbs    r14, r12, #32
+  blo     LOCAL_LABEL(sub_bigshift)
+
+  // The exponent difference is 32 or less. The test above also left
+  // (32-difference) in r14, which is the amount we need to shift yh left by to
+  // recover the bits that the right shift will lose off the bottom.
+#if !__thumb__
+  // Add the right-shifted parts of yh and yl to xh and xl, keeping the carry
+  // in between if any.
+  adds    xl, xl, yl, lsr r12
+  adc     xh, xh, yh, asr r12
+  // Now add the remainder of yh to the low word, again checking for a carry.
+  adds    xl, xl, yh, lsl r14
+  adcs    xh, xh, #0
+#else
+  // The Thumb version of the addition, which must do each register-controlled
+  // shift in a separate instruction from the addition. This works the same as
+  // the dadd version, except that we use ASR to shift yh right, because yh:yl
+  // contains a negative signed integer.
+
+  // As in dadd, start by adding (yh shifted left), so as not to waste the
+  // value we've already set up in r14.
+  lsl     r14, yh, r14
+  adds    xl, xl, r14
+  adcs    xh, xh, #0
+  // Then add (yh shifted right) and (yl shifted right).
+  lsr     r14, yl, r12
+  adds    xl, xl, r14
+  asr     r14, yh, r12
+  adcs    xh, xh, r14
+  // And now reconstruct the inverted shift count, for use later.
+  rsb     r14, r12, #32
+#endif
+
+  // We know we had x >= y before the subtraction. So x-y is still a number of
+  // the same sign, but its exponent might have reduced. If we'd set the
+  // leading bit on x's mantissa before subtracting, we'd be able to tell this
+  // by testing if it was still set. But in fact we didn't, so the question is
+  // whether x's mantissa without the leading bit is still even positive.
+  //
+  // The last ADCS (in either of the Arm and Thumb code sequences above) will
+  // have set the N flag if x < 0, which is the case where the exponent has
+  // reduced. Branch out of line for that case.
+  bmi     LOCAL_LABEL(sub_borrow)
+
+LOCAL_LABEL(sub_noborrow):
+  // This is the easy case: the exponent of x has stayed the same, so there's
+  // no possibility of underflow. All we have to do is put the pieces of the
+  // result back together, round, and return.
+
+  // Recombine x's mantissa with the output sign and exponent.
+  add     xh, xh, r4, lsl #20
+
+  // Make the word of bits shifted off the bottom of y's mantissa, with the
+  // topmost bit indicating whether we round up or down, and the rest used to
+  // determine whether to round to even.
+  lsls    yl, yl, r14
+
+  // If the top bit of the round word is clear, then we're rounding down, so
+  // the value in xh:xl is already correct and we can return.
+  poppl   {r4, pc}
+
+  // Otherwise, start by rounding up. As in dadd, we make the Z flag do double
+  // duty: it's initially set by the ADDS to indicate a carry into the high
+  // word, and then if that doesn't happen then we have another chance to set
+  // it if the round word indicates an exact halfway case. So we can return
+  // early in the common case where neither of those things happened.
+  adds    xl, xl, #1
+  cmpne   yl, #0x80000000
+  popne   {r4, pc}
+
+  // Now if xl=0 then we must increment xh (the addition from rounding carried
+  // into the high word). Otherwise we must round to even, by clearing the low
+  // bit of xl. As in dadd, it's possible that _both_ conditions are true at
+  // once, but in that situation, the fact that xl=0 means if makes no
+  // difference whether we clear its low bit or not.
+  cmp     xl, #0              // do we need to increment xh?
+  addeq   xh, xh, #1          // if so, do it
+  bicne   xl, xl, #1          // otherwise, round to even
+  pop     {r4, pc}
+
+LOCAL_LABEL(sub_bigshift):
+  // We come here from dsub_dosub if y's mantissa must be shifted right by more
+  // than 32 bits.
+  //
+  // In dadd_bigshift we concluded that all of yl could be condensed into a
+  // single bit at the bottom of the round word, because it could only affect
+  // round-to-even. However, in subtraction, that's not true, because we might
+  // renormalise: if the input exponents differ by exactly 33, and the
+  // subtraction reduces the exponent by 1, then the top bit of yl might become
+  // the round bit again. So we must make our round word by shifting two extra
+  // bits on to the bottom of yh: first the topmost bit of yl, then a single
+  // bit indicating whether any of the rest is nonzero.
+  //
+  // As in dadd_bigshift, we make this new round word in yl, leaving yh
+  // unmodified so that we can use it for the actual shift-and-add.
+  //
+  // (For these purposes, we only have to worry about renormalisation by _one_
+  // bit. If the output exponent reduces by 2 or more, it must be because the
+  // input exponents were so close that the output is exact anyway, so a round
+  // word isn't needed at all.)
+  adds    r14, yl, yl         // put the top bit of yl into C
+  adc     yl, yh, yh          // and shift it in to the bottom of yh
+  cmp     r14, #1             // set C if anything below that bit was nonzero
+  adc     yl, yl, yl          // shift that in to yl as well
+
+  // Calculate shift counts. r12 is how far to shift yh right when adding; r14
+  // is how far to shift yl left to make the round word (subtracted from 30
+  // instead of 32 to account for the two bits we just shifted in at the bottom
+  // of yl).
+  //
+  // If the latter shift count goes negative, then we can't use it. Branch to
+  // another handler for _really_ big exponent differences.
+  sub     r12, r12, #32
+  rsbs    r14, r12, #30
+  blo     LOCAL_LABEL(sub_hugeshift)
+
+  // Shift yh right and add it to x, to produce the unrounded output mantissa.
+#if !__thumb__
+  adds    xl, xl, yh, asr r12
+#else
+  // In Thumb we must do the register-controlled shift and addition separately
+  asr     r12, yh, r12
+  adds    xl, xl, r12
+#endif
+  // The top half of the addition, propagating a carry from xl into xh. Since
+  // yh was a negative number and we arithmetically shifted it right, the value
+  // we add to xh is 0xFFFFFFFF rather than 0, as if we'd sign-extended that
+  // negative number to 64 bits.
+  adcs    xh, xh, #-1
+
+  // As in the small-shift case above, if this has left a positive value in
+  // xh:xl, it means the exponent hasn't changed, so we can go to the easy
+  // epilogue code in dsub_noborrow.
+  bpl     LOCAL_LABEL(sub_noborrow)
+
+LOCAL_LABEL(sub_borrow):
+  // We come here from either of the small-shift or large-shift versions of the
+  // subtraction step, if the subtraction caused xh:xl to go negative. This
+  // means that the result of the subtraction is less than the smallest
+  // possible value with x's exponent. In other words, the output will have a
+  // smaller exponent, and we must shift the mantissa left and put some bits
+  // back in from yl (which contains the bits of y shifted off the bottom).
+  //
+  // The most important question in this situation is: do we have to shift the
+  // mantissa left by only one bit, or by more than one? It's important because
+  // in the case where we shift left by more than one bit, no rounding can
+  // possibly be needed: if x >= 2^k but x-y < 2^{k-1}, then y > 2^{k-1}, so
+  // the exponents of x and y differ by at most 1. Therefore the lowest set bit
+  // in the true difference x-y (before rounding) can't possibly be any lower
+  // than the bit just off the bottom of x's mantissa, and we're shifting left
+  // by at least 1, so that will be part of the output mantissa. So in this
+  // case the result must be exact.
+  //
+  // (This is not normally considered a good thing from the point of view of
+  // the user! Subtracting two very close values and getting a result that has
+  // a lot of mantissa bits zero at the bottom is called 'significance loss'
+  // and can be a cause of numerical instability. But whether the client code
+  // _likes_ it or not, the IEEE standard is very clear that we must return the
+  // value with lots of trailing 0 bits, which can't need any rounding.)
+  //
+  // On the other hand, if we shift left by only one bit, then the value we
+  // subtracted from x could have been almost arbitrarily small, so there's
+  // lots of scope for bits of y to have been shifted off the bottom to cause
+  // rounding.
+  //
+  // Conclusion: we either shift left 1 and have to figure out rounding, or we
+  // shift left more than 1 and have to figure out the right shift count, but
+  // never both.
+
+  // On entry to here, (yl << r14) gives the bits shifted off the bottom of
+  // xh:xl. Shift xh:xl up by one, bringing the high bit of that back in.
+  //
+  // If we're shifting left by only one bit, then the mantissa is now at its
+  // correct position and yl is the round word. On the other hand, if we're
+  // shifting by more, then all the output mantissa bits we need are now in
+  // xh:xl, and there aren't any in yl that still need to be salvaged.
+  add     r14, r14, #1            // we want to shift yl one extra bit left
+  lsls    r14, yl, r14            // do the shift, leaving the top bit in C
+  adcs    xl, xl, xl              // shift that in to the bottom of xl
+  adc     xh, xh, xh              // and propagate into xh
+
+  // Our next task is to find out which case we're in: shift by one bit and
+  // round, or figure out how many more bits to shift by? We can determine this
+  // by looking at bit 20 of xh: if that's 0 then we need to shift further.
+  //
+  // But to save instructions, we fold that test together with a test for
+  // another awkward case: was the input exponent in r4 equal to 1? If so, then
+  // it's been decremented to 0, which means the result of the subtraction is a
+  // denormal. (Separately from that, we might _also_ get a denormal if
+  // significance loss has occurred, even if the exponent in r4 was larger.)
+  //
+  // To do both of these tests at once, we add the original output exponent in
+  // r4 back in to xh, _shifted left by an extra bit_, as if we'd added it
+  // before doing the shift above. This loses the sign bit off the top, and
+  // since the top 11 bits of xh are all 1, has the same result as decrementing
+  // r4. So bit 20 of xh is unaffected (it's still 0 if we need to shift
+  // further), and bits 21 and upwards are all zero if the output might be
+  // denormal.
+  //
+  // The Arm condition code LS (unsigned lower-or-same) is implemented by
+  // testing if C=0 or Z=1. That's just what we need! Having made our modified
+  // version of xh, shift it right so that bit 20 goes off the bottom into the
+  // carry flag. Then C=0 means bit 20 of xh was clear and we need to shift
+  // further; Z=1 means the exponent has decremented from 1 to 0 and we're
+  // returning a denormal; if _either_ is true, then the BLS will send us out
+  // of line.
+
+  add     r12, xh, r4, lsl #21    // make test value (keeping the original xh)
+  lsrs    r12, r12, #21           // set C and Z to the values we want to test
+  bls     LOCAL_LABEL(sub_renorm_or_denorm)   // branch out of line if C=0 or Z=1
+
+  // If we haven't taken that branch, then we now have our mantissa in the
+  // correct position _and_ we're confident that the output is a normalised
+  // number. So we only have rounding left to do.
+  //
+  // Put the sign and exponent back on the output. Because the bits in xh's
+  // exponent field are still all 1s, this decrements the exponent in r4 by
+  // one, which is just what we want.
+  add     xh, xh, r4, lsl #20
+
+  // The round bit is at the top of r14, so we can add it to the bottom of xl
+  // by a right shift.
+  //
+  // If this addition carries off the top of xl, then C and Z will both be set.
+  // If C is not set, then Z might still be set because xl was already zero.
+  adds    xl, xl, r14, lsr #31
+  // We only need to check for round-to-even if there wasn't a carry, because
+  // if there was a carry, xl = 0 and so clearing its low bit won't make a
+  // difference anyway. So in the C=0 case, we now clobber the potentially
+  // misleading value left in Z by the previous instruction, and replace it
+  // with the result of checking r14 against the exact halfway value of the
+  // round word.
+  cmpcc   r14, #0x80000000
+  // Now if Z is clear, we don't have to round to even _or_ propagate a carry
+  // into xh, so we're done.
+  popne   {r4, pc}
+
+  // Otherwise, we have to either round to even, or increment xh. We increment
+  // xh exactly if xl = 0, because the case where xl=0 without rounding up
+  // would have taken the early return: the ADDS would have left C clear, so
+  // the CMPCC would have checked r14 against 0x80000000, and would have
+  // compared unequal because the top bit of r14 would have been claer.
+  cmp     xl, #0                  // is xl zero?
+  addeq   xh, xh, #1              // if so, increment xh to propagate carry
+  bicne   xl, xl, #1              // otherwise, clear xl bit 0 to round to even
+  pop     {r4, pc}
+
+LOCAL_LABEL(sub_renorm_or_denorm):
+  // We come here from the tricky combined test above, where we set C=0 if the
+  // output mantissa still doesn't have its leading bit set, and Z=1 if the
+  // exponent has already decreased to 0 so that the output will be denormal.
+  //
+  // In the latter case, we don't want to shift the mantissa any further up,
+  // because we'd only have to shift it back down again. So branch again to
+  // deal with that, or fall through to multiple-bit renormalisation.
+  beq     LOCAL_LABEL(sub_already_denormal)
+
+  // We'll want to adjust the exponent by the amount we shift. So split up the
+  // sign and exponent, so that we can do arithmetic on the exponent without
+  // the sign getting in the way.
+  lsr     r12, r4, #11            // sign is now in r12 bit 0
+  bic     r4, r4, #1 << 11        // exponent is in r4 all by itself
+
+  // Add the leading bit of x's mantissa back in (at bit 21 rather than 20
+  // because we already shifted left by one), to recover the full output
+  // mantissa.
+  //
+  // As a side effect, this sets Z to indicate that the top word xh is all
+  // zero, so now we know which of xh and xl we need to CLZ. It's easier to
+  // separate the two cases than to try to deal with them in a combined code
+  // path. We branch out of line for the xh=0 case, on the theory that the
+  // larger the renormalization, the less likely it is, so the common case
+  // stays in line.
+  adds    xh, xh, #1 << 21
+  beq     LOCAL_LABEL(sub_renorm_clz_xl)
+
+  // There's a set bit somewhere in xh. Find it, and shift it up to bit 20.
+  clz     yl, xh                  // distance from leading bit to bit 31
+  subs    yl, yl, #11             // distance to bit 20, where we want it
+  rsbs    yh, yl, #32             // work out the associated right shift
+  lsls    xh, xh, yl              // shift xh upwards
+#if !__thumb__
+  orr     xh, xh, xl, lsr yh      // combine with the high bits of xl
+#else
+  // As usual, in Thumb we must do the register-controlled right shift and the
+  // ORR separately.
+  lsrs    yh, xl, yh
+  orrs    xh, xh, yh
+#endif
+  lsls    xl, xl, yl              // finally, shift xl left
+
+  // Adjust the exponent downward, to match the distance we just shifted the
+  // mantissa upward.
+  //
+  // We adjust downward by an extra 2: one because we already shifted xh left
+  // by one bit, and another because the leading bit of the renormalized
+  // mantissa will increment it again.
+  subs    r4, r4, yl
+  subs    r4, r4, #2
+
+LOCAL_LABEL(sub_renormed):
+  // Here the two renormalization branches reconverge. The output mantissa in
+  // xh:xl has been shifted up to the correct position, with its leading bit
+  // present and in bit 20 of xh. r4 is the adjusted exponent, and the low bit
+  // of r12 is the output sign.
+  //
+  // Recombine all the pieces. Since no rounding is needed on this path, the
+  // output is correct and ready to return unless the exponent is too small.
+  // The smallest valid exponent is 0, because it will be adjusted upwards by 1
+  // by the leading mantissa bit. Since the last thing both branches did before
+  // coming here was to update r4 using a flag-setting instruction, we can
+  // therefore detect underflow by the N flag.
+  add     xh, xh, r12, lsl #31
+  add     xh, xh, r4, lsl #20
+  poppl   {r4, pc}
+
+  // Renormalisation made the exponent negative. We're well off the fast path
+  // by now, so the simplest way to sort this out is to use the helper routine
+  // __dunder.
+  add     xh, xh, #3 << 29        // rebias exponent as __dunder will expect
+  mov     r2, #0                  // rounding direction = 0 for an exact answer
+  pop     {r4, lr}
+  b       SYMBOL_NAME(__compiler_rt_dunder)
+
+LOCAL_LABEL(sub_renorm_clz_xl):
+  // This is the alternative renormalization code for the case where xh=0, so
+  // that the highest remaining set bit in the mantissa is somewhere in xl.
+  // Again we want to shift that all the way up to bit 20 of xh. The easiest
+  // way is to shift it to the top of xl, and then shift that in turn by a
+  // fixed distance to split it across xh[20..0] and xl[31..21], saving a
+  // conditional decision about whether to shift up or down.
+  //
+  // However, there's another special case: on this branch, we might find out
+  // that we've subtracted two _exactly_ equal values, not just nearly equal,
+  // so the result is zero! To handle this quickly, we put the shifted-up
+  // version of xl into xh instead of shifting it in place. Then, if it's zero,
+  // we've just filled xh _and_ xl with zero bits, so we can return
+  // immediately. (Since this function always uses round-to-nearest mode, an
+  // output zero from subtracting like-signed inputs is unconditionally +0.)
+  clz     yh, xl
+  lsls    xh, xl, yh              // now xl has leading bit in bit 31
+  popeq   {r4, pc}                // and if the answer is 0, just return it
+  lsls    xl, xh, #21             // now set xl to the low bits of the mantissa
+  lsrs    xh, xh, #11             // and xh to the high bits
+
+  // Adjust the exponent down by the amount we shifted up, which is the CLZ
+  // output (in yh), plus another 21 bits to get from the top bit of xl to bit
+  // 20 of xh, plus 1 bit for the shift already performed before we did the
+  // CLZ, plus 1 which the leading mantissa bit will undo when we add it to the
+  // exponent. Then go back to dsub_renormed for the shared epilogue code.
+  subs    r4, r4, yh
+  subs    r4, r4, #23
+  b       LOCAL_LABEL(sub_renormed)
+
+LOCAL_LABEL(sub_hugeshift):
+  // We came here in the case where the whole of y's mantissa was shifted down
+  // so far that dsub_bigshift couldn't cope with it. In this situation the
+  // result of the subtraction differs from the input x by under half a ULP, so
+  // we just return the original x, which we recover by putting the sign and
+  // exponent in r4 back together with the mantissa.
+  add     xh, xh, r4, lsl #20
+  pop     {r4, pc}
+
+LOCAL_LABEL(sub_already_denormal):
+  // We come here if the initial renormalization by one bit reduced the
+  // exponent of x from 1 to 0, so that the output is denormal. In this
+  // situation we don't need to call __dunder to figure out how far to shift
+  // the result, because the answer is a constant: the mantissa was already in
+  // the right place _before_ our one-bit left shift (denormals have the same
+  // mantissa shift as normalised numbers with the smallest exponent), so all
+  // we have to do is undo that left shift, and put the sign bit back on.
+  movs    xh, xh, asr #1
+  rrx     xl, xl
+  add     xh, xh, r4, lsl #20
+
+LOCAL_LABEL(sub_check_zero):
+  // Here we have a denormal result in xh:xl, with its sign bit already in
+  // place ... except that the mantissa might be all zeroes, in which case we
+  // must clear the sign bit so as to return +0.
+  pop     {r4, r14}
+  orrs    r12, xl, xh, lsl #1     // EQ if all non-sign bits of x are zero
+  bxne    lr                      // if that's not true, return our denormal
+  movs    xh, #0                  // otherwise, clear xh completely
+  bx      lr
+
+LOCAL_LABEL(sub_uncommon):
+  // We come here from the start of the function if we detected that either
+  // input had exponent 0x7ff or 0x000: that is, at least one operand is a NaN,
+  // infinity, denormal or zero.
+  //
+  // First detect whether there are any NaNs or infinities, by checking more
+  // specifically if either input has exponent 0x7ff. We take advantage of
+  // knowing that r14 was set to 0xFFC00000 in the function prologue, so we can
+  // make a useful constant for this test by adjusting it.
+  orr     r14, r14, #0x00200000   // now r14 = 0xFFE00000
+  bics    r4, r14, xh, lsl #1     // if x has exponent 0x7ff, this sets r4=0
+  bicsne  r4, r14, yh, lsl #1     // and similarly for y
+  beq     LOCAL_LABEL(sub_naninf)             // so if either set Z, we have a NaN or inf
+
+  // Now we've ruled out NaNs and infinities. With NaNs gone, it's safe to flip
+  // the signs of the inputs (which only mattered for returning the right NaN).
+  // So check if the signs are the same, and cross-jump to dadd_zerodenorm
+  // (magnitude subtraction involving a zero or denormal) if not. Meanwhile,
+  // that will cross-jump back to here in the opposite case.
+  teq     xh, yh
+  eormi   yh, yh, #1 << 31
+  bmi     LOCAL_LABEL(add_zerodenorm)
+LOCAL_LABEL(sub_zerodenorm):
+  // Now we know we're doing a magnitude addition, involving at least one zero
+  // or denormal, and no NaNs or infinities.
+  //
+  // Sort the operands into magnitude order so that x >= y, exactly as in the
+  // main code path, including the EOR that negates both operands in the course
+  // of swapping them.
+  subs    r4, xl, yl          // compare inputs, also keeping x-y
+  sbcs    r12, xh, yh
+  bhs     LOCAL_LABEL(sub_zerodenorm_swapped) // if x>=y then branch round the swap
+  eor     r12, r12, #1 << 31  // flip the top bit of x-y
+  adds    yl, yl, r4          // so that this addition turns y into x+TOPBIT
+  adc     yh, yh, r12
+  subs    xl, xl, r4          // and this subtraction turns x into y-TOPBIT
+  sbc     xh, xh, r12
+LOCAL_LABEL(sub_zerodenorm_swapped):
+  // Set up the output sign+exponent, and the exponent difference, again
+  // exactly as in the main code path.
+  lsr     r4, xh, #20
+  sub     r12, r4, yh, lsr #20
+
+  // With the operands sorted so that y is smallest, and knowing there's at
+  // least one zero or denormal present, we know furthermore that if there's
+  // zero at all then it's y. And if y=0, then we just return x, except that if
+  // x=0 too we must fix up the sign of zero.
+  orrs    r14, yl, yh, lsl #1     // test all bits of y except the sign bit
+  beq     LOCAL_LABEL(sub_check_zero)         // if they're all zero, return x
+
+  // Otherwise, there are no zeroes, so y must be denormal, and we don't yet
+  // know if x is denormal too.
+  //
+  // If x isn't denormal, we rejoin the main code path for adding normalised
+  // numbers, with everything set up as dadd_doadd expects. It's easiest to
+  // represent the denormal y the same way the FP format does, as a mantissa
+  // without its leading bit set, shifted by the same amount as normalised
+  // numbers of the lowest exponent. (Renormalising via CLZ is more work, and
+  // not needed for addition.)
+  //
+  // To tell the main code that y's mantissa should be shifted by the same
+  // amount as a number with exponent 0x001, we must adjust the exponent
+  // difference r12 by one, because we've already made that by subtracting the
+  // _raw_ exponent values.
+  lsls    r14, r4, #21          // output exp = 0? If so, x is denormal too
+  bic     xh, xh, r4, lsl #20   // clear sign+exponent from top of x
+  beq     LOCAL_LABEL(sub_both_denorm)      // if both inputs denormal, go elsewhere
+  bic     yh, yh, #1 << 31      // if x not denormal, clear sign of y
+  sub     r12, r12, #1          //   and adjust exponent difference
+  // Now negate the mantissa of y and then rejoin the main path.
+  rsbs    yl, yl, #0
+#if !__thumb__
+  rsc     yh, yh, #0
+#else
+  // Thumb has no RSC, so simulate it by bitwise inversion and then ADC
+  mvn     yh, yh
+  adc     yh, yh, #0
+#endif
+  b       LOCAL_LABEL(sub_dosub)
+
+LOCAL_LABEL(sub_both_denorm):
+  // If both inputs are denormal, then we can just subtract the mantissas like
+  // ordinary integers. We've cleared the sign bit from x, but not from y, so
+  // we'll get exactly one copy of the sign bit in the result. (Negating it
+  // makes no difference!)
+  subs    xl, xl, yl
+  sbc     xh, xh, yh
+  // Now go to dsub_check_zero, which will check if the answer is exactly zero,
+  // and fix the sign bit if it is.
+  b       LOCAL_LABEL(sub_check_zero)
+
+  // Handle NaNs and infinities in subtraction.
+LOCAL_LABEL(sub_naninf):
+  // Look for NaNs and hand them off to __dnan2, exactly as in dadd_naninf.
+  pop     {r4, r14}
+  cmp     xl, #1
+  adc     r12, xh, xh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+  cmp     yl, #1
+  adc     r12, yh, yh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+
+  // Now we know there aren't any NaNs, we can deal with subtractions involving
+  // an infinity by flipping the sign of y and letting dadd_inf deal with it.
+  eor     yh, yh, #0x80000000
+  b       LOCAL_LABEL(add_inf)
+
+END_COMPILERRT_FUNCTION(__aeabi_dsub)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/test/builtins/Unit/adddf3new_test.c b/compiler-rt/test/builtins/Unit/adddf3new_test.c
new file mode 100644
index 0000000000000..a3d8084b103ad
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/adddf3new_test.c
@@ -0,0 +1,382 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_adddf3
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test uses compareResultD to check the returned floats, which
+// accepts any returned NaN if the expected result is the canonical NaN value
+// 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
+// to a more detailed handling of NaNs, we tighten up the check and include
+// some extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#  define EXPECT_EXACT_RESULTS
+#  define ARM_NAN_HANDLING
+#endif
+
+// Returns: a + b
+COMPILER_RT_ABI double __adddf3(double a, double b);
+
+int test__adddf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+  double a = fromRep64(a_rep), b = fromRep64(b_rep);
+  double x = __adddf3(a, b);
+#ifdef EXPECT_EXACT_RESULTS
+  int ret = toRep64(x) != expected_rep;
+#else
+  int ret = compareResultD(x, expected_rep);
+#endif
+
+  if (ret) {
+    printf("error at line %d: __adddf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
+           ", expected %016" PRIx64 "\n",
+           line, a_rep, b_rep, toRep64(x), expected_rep);
+  }
+  return ret;
+}
+
+#define test__adddf3(a,b,x) (test__adddf3)(__LINE__,a,b,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__adddf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x0000000000000000, 0x000fffffffffffff, 0x000fffffffffffff);
+  status |= test__adddf3(0x0000000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |= test__adddf3(0x0000000000000000, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x0000000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x0000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x0000000000000000, 0x800fffffffffffff, 0x800fffffffffffff);
+  status |= test__adddf3(0x0000000000000000, 0x8010000000000000, 0x8010000000000000);
+  status |= test__adddf3(0x0000000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000002);
+  status |= test__adddf3(0x0000000000000001, 0x3fefffffffffffff, 0x3fefffffffffffff);
+  status |= test__adddf3(0x0000000000000001, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |= test__adddf3(0x0000000000000001, 0x3ffffffffffffffe, 0x3ffffffffffffffe);
+  status |= test__adddf3(0x0000000000000001, 0x3fffffffffffffff, 0x3fffffffffffffff);
+  status |= test__adddf3(0x0000000000000001, 0x7fdfffffffffffff, 0x7fdfffffffffffff);
+  status |= test__adddf3(0x0000000000000001, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x0000000000000001, 0x7feffffffffffffe, 0x7feffffffffffffe);
+  status |= test__adddf3(0x0000000000000001, 0x7fefffffffffffff, 0x7fefffffffffffff);
+  status |= test__adddf3(0x0000000000000001, 0x8000000000000001, 0x0000000000000000);
+  status |= test__adddf3(0x0000000000000002, 0x8000000000000001, 0x0000000000000001);
+  status |= test__adddf3(0x0000000000000003, 0x0000000000000000, 0x0000000000000003);
+  status |= test__adddf3(0x0000000000000003, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x0000000000000003, 0x8000000000000000, 0x0000000000000003);
+  status |= test__adddf3(0x0000000000000003, 0x8000000000000002, 0x0000000000000001);
+  status |= test__adddf3(0x0000000000000003, 0xc014000000000000, 0xc014000000000000);
+  status |= test__adddf3(0x0000000000000003, 0xffe0000000000000, 0xffe0000000000000);
+  status |= test__adddf3(0x0000000000000003, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0x0000000000000004, 0x0000000000000004, 0x0000000000000008);
+  status |= test__adddf3(0x000ffffffffffffc, 0x800ffffffffffffc, 0x0000000000000000);
+  status |= test__adddf3(0x000ffffffffffffd, 0x800ffffffffffffe, 0x8000000000000001);
+  status |= test__adddf3(0x000fffffffffffff, 0x000fffffffffffff, 0x001ffffffffffffe);
+  status |= test__adddf3(0x000fffffffffffff, 0x800ffffffffffffe, 0x0000000000000001);
+  status |= test__adddf3(0x000fffffffffffff, 0x8010000000000000, 0x8000000000000001);
+  status |= test__adddf3(0x0010000000000000, 0x0000000000000000, 0x0010000000000000);
+  status |= test__adddf3(0x0010000000000000, 0x0010000000000000, 0x0020000000000000);
+  status |= test__adddf3(0x0010000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x0010000000000001, 0x8010000000000000, 0x0000000000000001);
+  status |= test__adddf3(0x0010000000000001, 0x8010000000000002, 0x8000000000000001);
+  status |= test__adddf3(0x001fffffffffffff, 0x8020000000000000, 0x8000000000000001);
+  status |= test__adddf3(0x001fffffffffffff, 0x8020000000000002, 0x8000000000000005);
+  status |= test__adddf3(0x001fffffffffffff, 0x8020000000000004, 0x8000000000000009);
+  status |= test__adddf3(0x0020000000000000, 0x801fffffffffffff, 0x0000000000000001);
+  status |= test__adddf3(0x0020000000000001, 0x8010000000000001, 0x0010000000000001);
+  status |= test__adddf3(0x0020000000000001, 0x801fffffffffffff, 0x0000000000000003);
+  status |= test__adddf3(0x0020000000000002, 0x8010000000000001, 0x0010000000000003);
+  status |= test__adddf3(0x002fffffffffffff, 0x8030000000000000, 0x8000000000000002);
+  status |= test__adddf3(0x0030000000000000, 0x802fffffffffffff, 0x0000000000000002);
+  status |= test__adddf3(0x0030000000000001, 0x802fffffffffffff, 0x0000000000000006);
+  status |= test__adddf3(0x0030000000000002, 0x8020000000000003, 0x0020000000000001);
+  status |= test__adddf3(0x3fefffffffffffff, 0x8000000000000001, 0x3fefffffffffffff);
+  status |= test__adddf3(0x3ff0000000000000, 0x3ff0000000000000, 0x4000000000000000);
+  status |= test__adddf3(0x3ff0000000000000, 0x3ff0000000000003, 0x4000000000000002);
+  status |= test__adddf3(0x3ff0000000000000, 0x4000000000000000, 0x4008000000000000);
+  status |= test__adddf3(0x3ff0000000000000, 0x401c000000000000, 0x4020000000000000);
+  status |= test__adddf3(0x3ff0000000000000, 0x8000000000000000, 0x3ff0000000000000);
+  status |= test__adddf3(0x3ff0000000000000, 0xbff0000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x3ff0000000000001, 0x3ff0000000000000, 0x4000000000000000);
+  status |= test__adddf3(0x3ff0000000000001, 0xbff0000000000000, 0x3cb0000000000000);
+  status |= test__adddf3(0x3ff0000000000001, 0xbff0000000000002, 0xbcb0000000000000);
+  status |= test__adddf3(0x3ffffffffffffffc, 0xbffffffffffffffd, 0xbcb0000000000000);
+  status |= test__adddf3(0x3fffffffffffffff, 0xc000000000000000, 0xbcb0000000000000);
+  status |= test__adddf3(0x4000000000000000, 0x3cb0000000000000, 0x4000000000000000);
+  status |= test__adddf3(0x4000000000000000, 0x3ff0000000000000, 0x4008000000000000);
+  status |= test__adddf3(0x4000000000000000, 0x4000000000000000, 0x4010000000000000);
+  status |= test__adddf3(0x4000000000000000, 0x4000000000000001, 0x4010000000000000);
+  status |= test__adddf3(0x4000000000000000, 0xbfffffffffffffff, 0x3cb0000000000000);
+  status |= test__adddf3(0x4000000000000000, 0xc000000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x4000000000000000, 0xc000000000000001, 0xbcc0000000000000);
+  status |= test__adddf3(0x4000000000000000, 0xc014000000000000, 0xc008000000000000);
+  status |= test__adddf3(0x4000000000000001, 0x3cb0000000000000, 0x4000000000000002);
+  status |= test__adddf3(0x4000000000000001, 0x4000000000000002, 0x4010000000000002);
+  status |= test__adddf3(0x4000000000000001, 0xbff0000000000001, 0x3ff0000000000001);
+  status |= test__adddf3(0x4000000000000002, 0xbff0000000000001, 0x3ff0000000000003);
+  status |= test__adddf3(0x4000000000000002, 0xbff0000000000003, 0x3ff0000000000001);
+  status |= test__adddf3(0x4000000000000004, 0xc000000000000003, 0x3cc0000000000000);
+  status |= test__adddf3(0x4008000000000000, 0x4008000000000000, 0x4018000000000000);
+  status |= test__adddf3(0x400fffffffffffff, 0x3cafffffffffffff, 0x400fffffffffffff);
+  status |= test__adddf3(0x400fffffffffffff, 0x3cb0000000000000, 0x4010000000000000);
+  status |= test__adddf3(0x400fffffffffffff, 0xc00ffffffffffffe, 0x3cc0000000000000);
+  status |= test__adddf3(0x400fffffffffffff, 0xc010000000000002, 0xbce4000000000000);
+  status |= test__adddf3(0x4010000000000001, 0xc00fffffffffffff, 0x3cd8000000000000);
+  status |= test__adddf3(0x4014000000000000, 0x0000000000000000, 0x4014000000000000);
+  status |= test__adddf3(0x4014000000000000, 0x8000000000000000, 0x4014000000000000);
+  status |= test__adddf3(0x4014000000000000, 0xbff0000000000000, 0x4010000000000000);
+  status |= test__adddf3(0x4014000000000000, 0xc014000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x7fb0000000000001, 0xffafffffffffffff, 0x7c78000000000000);
+  status |= test__adddf3(0x7fcfffffffffffff, 0xffcffffffffffffe, 0x7c80000000000000);
+  status |= test__adddf3(0x7fcfffffffffffff, 0xffd0000000000002, 0xfca4000000000000);
+  status |= test__adddf3(0x7fd0000000000000, 0x7fd0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x7fd0000000000000, 0xffcfffffffffffff, 0x7c80000000000000);
+  status |= test__adddf3(0x7fd0000000000000, 0xffd0000000000001, 0xfc90000000000000);
+  status |= test__adddf3(0x7fd0000000000001, 0x7fd0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x7fd0000000000001, 0xffe0000000000001, 0xffd0000000000001);
+  status |= test__adddf3(0x7fd0000000000002, 0xffc0000000000003, 0x7fc0000000000001);
+  status |= test__adddf3(0x7fd0000000000004, 0xffd0000000000003, 0x7c90000000000000);
+  status |= test__adddf3(0x7fdffffffffffffe, 0x7fdffffffffffffe, 0x7feffffffffffffe);
+  status |= test__adddf3(0x7fdffffffffffffe, 0x7fdfffffffffffff, 0x7feffffffffffffe);
+  status |= test__adddf3(0x7fdfffffffffffff, 0x3ff0000000000000, 0x7fdfffffffffffff);
+  status |= test__adddf3(0x7fdfffffffffffff, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7fdfffffffffffff, 0xbff0000000000000, 0x7fdfffffffffffff);
+  status |= test__adddf3(0x7fdfffffffffffff, 0xffe0000000000000, 0xfc90000000000000);
+  status |= test__adddf3(0x7fe0000000000000, 0x3ff0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x7fe0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7fe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7fe0000000000000, 0xbff0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x7fe0000000000000, 0xffe0000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x7fe0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0x7fe0000000000001, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7fe0000000000001, 0xffe0000000000000, 0x7ca0000000000000);
+  status |= test__adddf3(0x7fe0000000000001, 0xffe0000000000002, 0xfca0000000000000);
+  status |= test__adddf3(0x7fe0000000000002, 0xffd0000000000001, 0x7fd0000000000003);
+  status |= test__adddf3(0x7feffffffffffffe, 0x3ff0000000000000, 0x7feffffffffffffe);
+  status |= test__adddf3(0x7feffffffffffffe, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |= test__adddf3(0x7feffffffffffffe, 0x7fefffffffffffff, 0x7ff0000000000000);
+  status |= test__adddf3(0x7feffffffffffffe, 0xbff0000000000000, 0x7feffffffffffffe);
+  status |= test__adddf3(0x7feffffffffffffe, 0xffefffffffffffff, 0xfca0000000000000);
+  status |= test__adddf3(0x7fefffffffffffff, 0x3ff0000000000000, 0x7fefffffffffffff);
+  status |= test__adddf3(0x7fefffffffffffff, 0x8000000000000001, 0x7fefffffffffffff);
+  status |= test__adddf3(0x7fefffffffffffff, 0xbff0000000000000, 0x7fefffffffffffff);
+  status |= test__adddf3(0x7fefffffffffffff, 0xffefffffffffffff, 0x0000000000000000);
+  status |= test__adddf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |= test__adddf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x7ff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
+  status |= test__adddf3(0x7ff0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x8000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x8000000000000000, 0x000fffffffffffff, 0x000fffffffffffff);
+  status |= test__adddf3(0x8000000000000000, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x8000000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x8000000000000000, 0x8000000000000000, 0x8000000000000000);
+  status |= test__adddf3(0x8000000000000000, 0x800fffffffffffff, 0x800fffffffffffff);
+  status |= test__adddf3(0x8000000000000000, 0x8010000000000000, 0x8010000000000000);
+  status |= test__adddf3(0x8000000000000000, 0xbff0000000000000, 0xbff0000000000000);
+  status |= test__adddf3(0x8000000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0x8000000000000001, 0x0000000000000001, 0x0000000000000000);
+  status |= test__adddf3(0x8000000000000001, 0x8000000000000001, 0x8000000000000002);
+  status |= test__adddf3(0x8000000000000001, 0xbfefffffffffffff, 0xbfefffffffffffff);
+  status |= test__adddf3(0x8000000000000001, 0xbff0000000000000, 0xbff0000000000000);
+  status |= test__adddf3(0x8000000000000001, 0xbffffffffffffffe, 0xbffffffffffffffe);
+  status |= test__adddf3(0x8000000000000001, 0xbfffffffffffffff, 0xbfffffffffffffff);
+  status |= test__adddf3(0x8000000000000001, 0xffdfffffffffffff, 0xffdfffffffffffff);
+  status |= test__adddf3(0x8000000000000001, 0xffe0000000000000, 0xffe0000000000000);
+  status |= test__adddf3(0x8000000000000001, 0xffeffffffffffffe, 0xffeffffffffffffe);
+  status |= test__adddf3(0x8000000000000001, 0xffefffffffffffff, 0xffefffffffffffff);
+  status |= test__adddf3(0x8000000000000002, 0x0000000000000001, 0x8000000000000001);
+  status |= test__adddf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000003);
+  status |= test__adddf3(0x8000000000000003, 0x0000000000000002, 0x8000000000000001);
+  status |= test__adddf3(0x8000000000000003, 0x4008000000000000, 0x4008000000000000);
+  status |= test__adddf3(0x8000000000000003, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |= test__adddf3(0x8000000000000003, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0x8000000000000003, 0x8000000000000000, 0x8000000000000003);
+  status |= test__adddf3(0x8000000000000003, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0x8000000000000004, 0x8000000000000004, 0x8000000000000008);
+  status |= test__adddf3(0x800ffffffffffffd, 0x000ffffffffffffe, 0x0000000000000001);
+  status |= test__adddf3(0x800fffffffffffff, 0x000ffffffffffffe, 0x8000000000000001);
+  status |= test__adddf3(0x800fffffffffffff, 0x000fffffffffffff, 0x0000000000000000);
+  status |= test__adddf3(0x800fffffffffffff, 0x0010000000000000, 0x0000000000000001);
+  status |= test__adddf3(0x800fffffffffffff, 0x800fffffffffffff, 0x801ffffffffffffe);
+  status |= test__adddf3(0x8010000000000000, 0x0000000000000000, 0x8010000000000000);
+  status |= test__adddf3(0x8010000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |= test__adddf3(0x8010000000000001, 0x0010000000000000, 0x8000000000000001);
+  status |= test__adddf3(0x8010000000000001, 0x0010000000000002, 0x0000000000000001);
+  status |= test__adddf3(0x801fffffffffffff, 0x0020000000000000, 0x0000000000000001);
+  status |= test__adddf3(0x801fffffffffffff, 0x0020000000000002, 0x0000000000000005);
+  status |= test__adddf3(0x801fffffffffffff, 0x0020000000000004, 0x0000000000000009);
+  status |= test__adddf3(0x8020000000000000, 0x001fffffffffffff, 0x8000000000000001);
+  status |= test__adddf3(0x8020000000000001, 0x0010000000000001, 0x8010000000000001);
+  status |= test__adddf3(0x8020000000000001, 0x001fffffffffffff, 0x8000000000000003);
+  status |= test__adddf3(0x8020000000000002, 0x0010000000000001, 0x8010000000000003);
+  status |= test__adddf3(0x802fffffffffffff, 0x0030000000000000, 0x0000000000000002);
+  status |= test__adddf3(0x8030000000000000, 0x002fffffffffffff, 0x8000000000000002);
+  status |= test__adddf3(0x8030000000000001, 0x002fffffffffffff, 0x8000000000000006);
+  status |= test__adddf3(0x8030000000000002, 0x0020000000000003, 0x8020000000000001);
+  status |= test__adddf3(0xbff0000000000000, 0x8000000000000000, 0xbff0000000000000);
+  status |= test__adddf3(0xbff0000000000000, 0xbff0000000000003, 0xc000000000000002);
+  status |= test__adddf3(0xbff0000000000001, 0x3ff0000000000000, 0xbcb0000000000000);
+  status |= test__adddf3(0xbff0000000000001, 0x3ff0000000000002, 0x3cb0000000000000);
+  status |= test__adddf3(0xbff0000000000001, 0xbff0000000000000, 0xc000000000000000);
+  status |= test__adddf3(0xbffffffffffffffc, 0x3ffffffffffffffd, 0x3cb0000000000000);
+  status |= test__adddf3(0xbfffffffffffffff, 0x0000000000000001, 0xbfffffffffffffff);
+  status |= test__adddf3(0xbfffffffffffffff, 0x4000000000000000, 0x3cb0000000000000);
+  status |= test__adddf3(0xc000000000000000, 0x3fffffffffffffff, 0xbcb0000000000000);
+  status |= test__adddf3(0xc000000000000000, 0x4000000000000001, 0x3cc0000000000000);
+  status |= test__adddf3(0xc000000000000000, 0xc000000000000001, 0xc010000000000000);
+  status |= test__adddf3(0xc000000000000001, 0x3ff0000000000001, 0xbff0000000000001);
+  status |= test__adddf3(0xc000000000000001, 0xc000000000000002, 0xc010000000000002);
+  status |= test__adddf3(0xc000000000000002, 0x3ff0000000000001, 0xbff0000000000003);
+  status |= test__adddf3(0xc000000000000002, 0x3ff0000000000003, 0xbff0000000000001);
+  status |= test__adddf3(0xc000000000000004, 0x4000000000000003, 0xbcc0000000000000);
+  status |= test__adddf3(0xc008000000000000, 0x4008000000000000, 0x0000000000000000);
+  status |= test__adddf3(0xc00fffffffffffff, 0x400ffffffffffffe, 0xbcc0000000000000);
+  status |= test__adddf3(0xc00fffffffffffff, 0x4010000000000002, 0x3ce4000000000000);
+  status |= test__adddf3(0xc00fffffffffffff, 0xbcafffffffffffff, 0xc00fffffffffffff);
+  status |= test__adddf3(0xc00fffffffffffff, 0xbcb0000000000000, 0xc010000000000000);
+  status |= test__adddf3(0xc010000000000001, 0x400fffffffffffff, 0xbcd8000000000000);
+  status |= test__adddf3(0xffb0000000000001, 0x7fafffffffffffff, 0xfc78000000000000);
+  status |= test__adddf3(0xffcfffffffffffff, 0x7fcffffffffffffe, 0xfc80000000000000);
+  status |= test__adddf3(0xffcfffffffffffff, 0x7fd0000000000002, 0x7ca4000000000000);
+  status |= test__adddf3(0xffd0000000000000, 0x7fcfffffffffffff, 0xfc80000000000000);
+  status |= test__adddf3(0xffd0000000000000, 0x7fd0000000000001, 0x7c90000000000000);
+  status |= test__adddf3(0xffd0000000000001, 0x7fe0000000000001, 0x7fd0000000000001);
+  status |= test__adddf3(0xffd0000000000001, 0xffd0000000000000, 0xffe0000000000000);
+  status |= test__adddf3(0xffd0000000000002, 0x7fc0000000000003, 0xffc0000000000001);
+  status |= test__adddf3(0xffd0000000000004, 0x7fd0000000000003, 0xfc90000000000000);
+  status |= test__adddf3(0xffdffffffffffffe, 0x7fdffffffffffffe, 0x0000000000000000);
+  status |= test__adddf3(0xffdffffffffffffe, 0xffdffffffffffffe, 0xffeffffffffffffe);
+  status |= test__adddf3(0xffdffffffffffffe, 0xffdfffffffffffff, 0xffeffffffffffffe);
+  status |= test__adddf3(0xffdfffffffffffff, 0x3ff0000000000000, 0xffdfffffffffffff);
+  status |= test__adddf3(0xffdfffffffffffff, 0x7fe0000000000000, 0x7c90000000000000);
+  status |= test__adddf3(0xffdfffffffffffff, 0xbff0000000000000, 0xffdfffffffffffff);
+  status |= test__adddf3(0xffdfffffffffffff, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xffe0000000000000, 0x0000000000000000, 0xffe0000000000000);
+  status |= test__adddf3(0xffe0000000000000, 0x3ff0000000000000, 0xffe0000000000000);
+  status |= test__adddf3(0xffe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__adddf3(0xffe0000000000000, 0x8000000000000000, 0xffe0000000000000);
+  status |= test__adddf3(0xffe0000000000000, 0xbff0000000000000, 0xffe0000000000000);
+  status |= test__adddf3(0xffe0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xffe0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xffe0000000000001, 0x7fe0000000000000, 0xfca0000000000000);
+  status |= test__adddf3(0xffe0000000000001, 0x7fe0000000000002, 0x7ca0000000000000);
+  status |= test__adddf3(0xffe0000000000001, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xffe0000000000002, 0x7fd0000000000001, 0xffd0000000000003);
+  status |= test__adddf3(0xffeffffffffffffe, 0x3ff0000000000000, 0xffeffffffffffffe);
+  status |= test__adddf3(0xffeffffffffffffe, 0x7fefffffffffffff, 0x7ca0000000000000);
+  status |= test__adddf3(0xffeffffffffffffe, 0xbff0000000000000, 0xffeffffffffffffe);
+  status |= test__adddf3(0xffeffffffffffffe, 0xffeffffffffffffe, 0xfff0000000000000);
+  status |= test__adddf3(0xffeffffffffffffe, 0xffefffffffffffff, 0xfff0000000000000);
+  status |= test__adddf3(0xffefffffffffffff, 0x0000000000000001, 0xffefffffffffffff);
+  status |= test__adddf3(0xffefffffffffffff, 0x3ff0000000000000, 0xffefffffffffffff);
+  status |= test__adddf3(0xffefffffffffffff, 0xbff0000000000000, 0xffefffffffffffff);
+  status |= test__adddf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
+  status |= test__adddf3(0xfff0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xfff0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xfff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |= test__adddf3(0xfff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0xfff0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__adddf3(0x3de3a83a83a83a83, 0xbff0000000000000, 0xbfefffffffec57c5);
+  status |= test__adddf3(0x0000000007ffffff, 0x0010000000010000, 0x001000000800ffff);
+  status |= test__adddf3(0x001effffffffffff, 0x0000000000400000, 0x001f0000003fffff);
+  status |= test__adddf3(0x80000000000003ff, 0x801ffffbffffffff, 0x801ffffc000003fe);
+  status |= test__adddf3(0x80003fffffffffff, 0x8010000000100000, 0x80104000000fffff);
+
+  // Test that the result of an operation is a NaN at all when it should be.
+  //
+  // In most configurations these tests' results are checked compared using
+  // compareResultD, so we set all the answers to the canonical NaN
+  // 0x7ff8000000000000, which causes compareResultF to accept any NaN
+  // encoding. We also use the same value as the input NaN in tests that have
+  // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
+  // because 0x7ff8000000000000 is still the exact expected NaN.
+  status |= test__adddf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |= test__adddf3(0xfff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |= test__adddf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |= test__adddf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |= test__adddf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+
+#ifdef ARM_NAN_HANDLING
+  // Tests specific to the NaN handling of Arm hardware, mimicked by
+  // arm/adddf3.S:
+  //
+  //  - a quiet NaN is distinguished by the top mantissa bit being 1
+  //
+  //  - if a signalling NaN appears in the input, the output quiet NaN is
+  //    obtained by setting its top mantissa bit and leaving everything else
+  //    unchanged
+  //
+  //  - if both operands are signalling NaNs then the output NaN is derived
+  //    from the first operand
+  //
+  //  - if both operands are quiet NaNs then the output NaN is the first
+  //    operand
+  //
+  //  - invalid operations not involving an input NaN return the quiet
+  //    NaN with fewest bits set, 0x7ff8000000000000.
+  status |= test__adddf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |= test__adddf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |= test__adddf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |= test__adddf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |= test__adddf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |= test__adddf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |= test__adddf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |= test__adddf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |= test__adddf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |= test__adddf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |= test__adddf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |= test__adddf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |= test__adddf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |= test__adddf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |= test__adddf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |= test__adddf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |= test__adddf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |= test__adddf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |= test__adddf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |= test__adddf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |= test__adddf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |= test__adddf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |= test__adddf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |= test__adddf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |= test__adddf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |= test__adddf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |= test__adddf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |= test__adddf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |= test__adddf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |= test__adddf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |= test__adddf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |= test__adddf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |= test__adddf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |= test__adddf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |= test__adddf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |= test__adddf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |= test__adddf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |= test__adddf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |= test__adddf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |= test__adddf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |= test__adddf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |= test__adddf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |= test__adddf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |= test__adddf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |= test__adddf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |= test__adddf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |= test__adddf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |= test__adddf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |= test__adddf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |= test__adddf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |= test__adddf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |= test__adddf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+
+#endif // ARM_NAN_HANDLING
+
+  return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/subdf3new_test.c b/compiler-rt/test/builtins/Unit/subdf3new_test.c
new file mode 100644
index 0000000000000..5ed19d4c85847
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/subdf3new_test.c
@@ -0,0 +1,393 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_subdf3
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test uses compareResultD to check the returned floats, which
+// accepts any returned NaN if the expected result is the canonical NaN value
+// 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
+// to a more detailed handling of NaNs, we tighten up the check and include
+// some extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#  define EXPECT_EXACT_RESULTS
+#  define ARM_NAN_HANDLING
+#endif
+
+// Returns: a - b
+COMPILER_RT_ABI double __subdf3(double a, double b);
+
+int test__subdf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+  double a = fromRep64(a_rep), b = fromRep64(b_rep);
+  double x = __subdf3(a, b);
+#ifdef EXPECT_EXACT_RESULTS
+  int ret = toRep64(x) != expected_rep;
+#else
+  int ret = compareResultD(x, expected_rep);
+#endif
+
+  if (ret) {
+    printf("error at line %d: __subdf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
+           ", expected %016" PRIx64 "\n",
+           line, a_rep, b_rep, toRep64(x), expected_rep);
+  }
+  return ret;
+}
+
+#define test__subdf3(a,b,x) test__subdf3(__LINE__,a,b,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__subdf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x0000000000000000, 0x000fffffffffffff, 0x800fffffffffffff);
+  status |= test__subdf3(0x0000000000000000, 0x0010000000000000, 0x8010000000000000);
+  status |= test__subdf3(0x0000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0x0000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x0000000000000000, 0x800fffffffffffff, 0x000fffffffffffff);
+  status |= test__subdf3(0x0000000000000000, 0xbff0000000000000, 0x3ff0000000000000);
+  status |= test__subdf3(0x0000000000000000, 0xffe0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x0000000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000000);
+  status |= test__subdf3(0x0000000000000001, 0x8000000000000001, 0x0000000000000002);
+  status |= test__subdf3(0x0000000000000001, 0xbfefffffffffffff, 0x3fefffffffffffff);
+  status |= test__subdf3(0x0000000000000001, 0xbff0000000000000, 0x3ff0000000000000);
+  status |= test__subdf3(0x0000000000000001, 0xbffffffffffffffe, 0x3ffffffffffffffe);
+  status |= test__subdf3(0x0000000000000001, 0xbfffffffffffffff, 0x3fffffffffffffff);
+  status |= test__subdf3(0x0000000000000001, 0xffdfffffffffffff, 0x7fdfffffffffffff);
+  status |= test__subdf3(0x0000000000000001, 0xffe0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x0000000000000001, 0xffeffffffffffffe, 0x7feffffffffffffe);
+  status |= test__subdf3(0x0000000000000001, 0xffefffffffffffff, 0x7fefffffffffffff);
+  status |= test__subdf3(0x0000000000000002, 0x0000000000000001, 0x0000000000000001);
+  status |= test__subdf3(0x0000000000000003, 0x0000000000000000, 0x0000000000000003);
+  status |= test__subdf3(0x0000000000000003, 0x0000000000000002, 0x0000000000000001);
+  status |= test__subdf3(0x0000000000000003, 0x4014000000000000, 0xc014000000000000);
+  status |= test__subdf3(0x0000000000000003, 0x7fe0000000000000, 0xffe0000000000000);
+  status |= test__subdf3(0x0000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0x0000000000000003, 0x8000000000000000, 0x0000000000000003);
+  status |= test__subdf3(0x0000000000000003, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x0000000000000004, 0x8000000000000004, 0x0000000000000008);
+  status |= test__subdf3(0x000ffffffffffffc, 0x000ffffffffffffc, 0x0000000000000000);
+  status |= test__subdf3(0x000ffffffffffffd, 0x000ffffffffffffe, 0x8000000000000001);
+  status |= test__subdf3(0x000fffffffffffff, 0x000ffffffffffffe, 0x0000000000000001);
+  status |= test__subdf3(0x000fffffffffffff, 0x0010000000000000, 0x8000000000000001);
+  status |= test__subdf3(0x000fffffffffffff, 0x800fffffffffffff, 0x001ffffffffffffe);
+  status |= test__subdf3(0x0010000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x0010000000000000, 0x8000000000000000, 0x0010000000000000);
+  status |= test__subdf3(0x0010000000000000, 0x8010000000000000, 0x0020000000000000);
+  status |= test__subdf3(0x0010000000000001, 0x0010000000000000, 0x0000000000000001);
+  status |= test__subdf3(0x0010000000000001, 0x0010000000000002, 0x8000000000000001);
+  status |= test__subdf3(0x001fffffffffffff, 0x0020000000000000, 0x8000000000000001);
+  status |= test__subdf3(0x001fffffffffffff, 0x0020000000000002, 0x8000000000000005);
+  status |= test__subdf3(0x001fffffffffffff, 0x0020000000000004, 0x8000000000000009);
+  status |= test__subdf3(0x0020000000000000, 0x001fffffffffffff, 0x0000000000000001);
+  status |= test__subdf3(0x0020000000000001, 0x0010000000000001, 0x0010000000000001);
+  status |= test__subdf3(0x0020000000000001, 0x001fffffffffffff, 0x0000000000000003);
+  status |= test__subdf3(0x0020000000000002, 0x0010000000000001, 0x0010000000000003);
+  status |= test__subdf3(0x002fffffffffffff, 0x0030000000000000, 0x8000000000000002);
+  status |= test__subdf3(0x0030000000000000, 0x002fffffffffffff, 0x0000000000000002);
+  status |= test__subdf3(0x0030000000000001, 0x002fffffffffffff, 0x0000000000000006);
+  status |= test__subdf3(0x0030000000000002, 0x0020000000000003, 0x0020000000000001);
+  status |= test__subdf3(0x3fefffffffffffff, 0x0000000000000001, 0x3fefffffffffffff);
+  status |= test__subdf3(0x3ff0000000000000, 0x0000000000000000, 0x3ff0000000000000);
+  status |= test__subdf3(0x3ff0000000000000, 0x3ff0000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x3ff0000000000000, 0xbff0000000000000, 0x4000000000000000);
+  status |= test__subdf3(0x3ff0000000000000, 0xbff0000000000003, 0x4000000000000002);
+  status |= test__subdf3(0x3ff0000000000000, 0xc000000000000000, 0x4008000000000000);
+  status |= test__subdf3(0x3ff0000000000000, 0xc01c000000000000, 0x4020000000000000);
+  status |= test__subdf3(0x3ff0000000000001, 0x3ff0000000000000, 0x3cb0000000000000);
+  status |= test__subdf3(0x3ff0000000000001, 0x3ff0000000000002, 0xbcb0000000000000);
+  status |= test__subdf3(0x3ff0000000000001, 0xbff0000000000000, 0x4000000000000000);
+  status |= test__subdf3(0x3ffffffffffffffc, 0x3ffffffffffffffd, 0xbcb0000000000000);
+  status |= test__subdf3(0x3fffffffffffffff, 0x4000000000000000, 0xbcb0000000000000);
+  status |= test__subdf3(0x4000000000000000, 0x3fffffffffffffff, 0x3cb0000000000000);
+  status |= test__subdf3(0x4000000000000000, 0x4000000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x4000000000000000, 0x4000000000000001, 0xbcc0000000000000);
+  status |= test__subdf3(0x4000000000000000, 0x4014000000000000, 0xc008000000000000);
+  status |= test__subdf3(0x4000000000000000, 0xbcb0000000000000, 0x4000000000000000);
+  status |= test__subdf3(0x4000000000000000, 0xbff0000000000000, 0x4008000000000000);
+  status |= test__subdf3(0x4000000000000000, 0xc000000000000000, 0x4010000000000000);
+  status |= test__subdf3(0x4000000000000000, 0xc000000000000001, 0x4010000000000000);
+  status |= test__subdf3(0x4000000000000001, 0x3ff0000000000001, 0x3ff0000000000001);
+  status |= test__subdf3(0x4000000000000001, 0xbcb0000000000000, 0x4000000000000002);
+  status |= test__subdf3(0x4000000000000001, 0xc000000000000002, 0x4010000000000002);
+  status |= test__subdf3(0x4000000000000002, 0x3ff0000000000001, 0x3ff0000000000003);
+  status |= test__subdf3(0x4000000000000002, 0x3ff0000000000003, 0x3ff0000000000001);
+  status |= test__subdf3(0x4000000000000004, 0x4000000000000003, 0x3cc0000000000000);
+  status |= test__subdf3(0x4008000000000000, 0xc008000000000000, 0x4018000000000000);
+  status |= test__subdf3(0x400fffffffffffff, 0x400ffffffffffffe, 0x3cc0000000000000);
+  status |= test__subdf3(0x400fffffffffffff, 0x4010000000000002, 0xbce4000000000000);
+  status |= test__subdf3(0x400fffffffffffff, 0xbcafffffffffffff, 0x400fffffffffffff);
+  status |= test__subdf3(0x400fffffffffffff, 0xbcb0000000000000, 0x4010000000000000);
+  status |= test__subdf3(0x4010000000000001, 0x400fffffffffffff, 0x3cd8000000000000);
+  status |= test__subdf3(0x4014000000000000, 0x0000000000000000, 0x4014000000000000);
+  status |= test__subdf3(0x4014000000000000, 0x3ff0000000000000, 0x4010000000000000);
+  status |= test__subdf3(0x4014000000000000, 0x4014000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x4014000000000000, 0x8000000000000000, 0x4014000000000000);
+  status |= test__subdf3(0x4280000000000001, 0x3ff0017fffffffff, 0x427ffffffffff001);
+  status |= test__subdf3(0x7fb0000000000001, 0x7fafffffffffffff, 0x7c78000000000000);
+  status |= test__subdf3(0x7fcfffffffffffff, 0x7fcffffffffffffe, 0x7c80000000000000);
+  status |= test__subdf3(0x7fcfffffffffffff, 0x7fd0000000000002, 0xfca4000000000000);
+  status |= test__subdf3(0x7fd0000000000000, 0x7fcfffffffffffff, 0x7c80000000000000);
+  status |= test__subdf3(0x7fd0000000000000, 0x7fd0000000000001, 0xfc90000000000000);
+  status |= test__subdf3(0x7fd0000000000000, 0xffd0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x7fd0000000000001, 0x7fe0000000000001, 0xffd0000000000001);
+  status |= test__subdf3(0x7fd0000000000001, 0xffd0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x7fd0000000000002, 0x7fc0000000000003, 0x7fc0000000000001);
+  status |= test__subdf3(0x7fd0000000000004, 0x7fd0000000000003, 0x7c90000000000000);
+  status |= test__subdf3(0x7fdffffffffffffe, 0xffdffffffffffffe, 0x7feffffffffffffe);
+  status |= test__subdf3(0x7fdffffffffffffe, 0xffdfffffffffffff, 0x7feffffffffffffe);
+  status |= test__subdf3(0x7fdfffffffffffff, 0x3ff0000000000000, 0x7fdfffffffffffff);
+  status |= test__subdf3(0x7fdfffffffffffff, 0x7fe0000000000000, 0xfc90000000000000);
+  status |= test__subdf3(0x7fdfffffffffffff, 0xbff0000000000000, 0x7fdfffffffffffff);
+  status |= test__subdf3(0x7fdfffffffffffff, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7fe0000000000000, 0x3ff0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x7fe0000000000000, 0x7fe0000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x7fe0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0x7fe0000000000000, 0xbff0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x7fe0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7fe0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7fe0000000000001, 0x7fe0000000000000, 0x7ca0000000000000);
+  status |= test__subdf3(0x7fe0000000000001, 0x7fe0000000000002, 0xfca0000000000000);
+  status |= test__subdf3(0x7fe0000000000001, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7fe0000000000002, 0x7fd0000000000001, 0x7fd0000000000003);
+  status |= test__subdf3(0x7feffffffffffffe, 0x3ff0000000000000, 0x7feffffffffffffe);
+  status |= test__subdf3(0x7feffffffffffffe, 0x7fefffffffffffff, 0xfca0000000000000);
+  status |= test__subdf3(0x7feffffffffffffe, 0xbff0000000000000, 0x7feffffffffffffe);
+  status |= test__subdf3(0x7feffffffffffffe, 0xffeffffffffffffe, 0x7ff0000000000000);
+  status |= test__subdf3(0x7feffffffffffffe, 0xffefffffffffffff, 0x7ff0000000000000);
+  status |= test__subdf3(0x7fefffffffffffff, 0x0000000000000001, 0x7fefffffffffffff);
+  status |= test__subdf3(0x7fefffffffffffff, 0x3ff0000000000000, 0x7fefffffffffffff);
+  status |= test__subdf3(0x7fefffffffffffff, 0x7fefffffffffffff, 0x0000000000000000);
+  status |= test__subdf3(0x7fefffffffffffff, 0xbff0000000000000, 0x7fefffffffffffff);
+  status |= test__subdf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |= test__subdf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7ff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
+  status |= test__subdf3(0x7ff0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x8000000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |= test__subdf3(0x8000000000000000, 0x000fffffffffffff, 0x800fffffffffffff);
+  status |= test__subdf3(0x8000000000000000, 0x0010000000000000, 0x8010000000000000);
+  status |= test__subdf3(0x8000000000000000, 0x3ff0000000000000, 0xbff0000000000000);
+  status |= test__subdf3(0x8000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0x8000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x8000000000000000, 0x800fffffffffffff, 0x000fffffffffffff);
+  status |= test__subdf3(0x8000000000000000, 0xffe0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x8000000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x8000000000000001, 0x0000000000000001, 0x8000000000000002);
+  status |= test__subdf3(0x8000000000000001, 0x3fefffffffffffff, 0xbfefffffffffffff);
+  status |= test__subdf3(0x8000000000000001, 0x3ff0000000000000, 0xbff0000000000000);
+  status |= test__subdf3(0x8000000000000001, 0x3ffffffffffffffe, 0xbffffffffffffffe);
+  status |= test__subdf3(0x8000000000000001, 0x3fffffffffffffff, 0xbfffffffffffffff);
+  status |= test__subdf3(0x8000000000000001, 0x7fdfffffffffffff, 0xffdfffffffffffff);
+  status |= test__subdf3(0x8000000000000001, 0x7fe0000000000000, 0xffe0000000000000);
+  status |= test__subdf3(0x8000000000000001, 0x7feffffffffffffe, 0xffeffffffffffffe);
+  status |= test__subdf3(0x8000000000000001, 0x7fefffffffffffff, 0xffefffffffffffff);
+  status |= test__subdf3(0x8000000000000001, 0x8000000000000001, 0x0000000000000000);
+  status |= test__subdf3(0x8000000000000002, 0x8000000000000001, 0x8000000000000001);
+  status |= test__subdf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000003);
+  status |= test__subdf3(0x8000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0x8000000000000003, 0x8000000000000000, 0x8000000000000003);
+  status |= test__subdf3(0x8000000000000003, 0x8000000000000002, 0x8000000000000001);
+  status |= test__subdf3(0x8000000000000003, 0xc008000000000000, 0x4008000000000000);
+  status |= test__subdf3(0x8000000000000003, 0xffe0000000000000, 0x7fe0000000000000);
+  status |= test__subdf3(0x8000000000000003, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0x8000000000000004, 0x0000000000000004, 0x8000000000000008);
+  status |= test__subdf3(0x800ffffffffffffd, 0x800ffffffffffffe, 0x0000000000000001);
+  status |= test__subdf3(0x800fffffffffffff, 0x000fffffffffffff, 0x801ffffffffffffe);
+  status |= test__subdf3(0x800fffffffffffff, 0x800ffffffffffffe, 0x8000000000000001);
+  status |= test__subdf3(0x800fffffffffffff, 0x800fffffffffffff, 0x0000000000000000);
+  status |= test__subdf3(0x800fffffffffffff, 0x8010000000000000, 0x0000000000000001);
+  status |= test__subdf3(0x8010000000000000, 0x8000000000000000, 0x8010000000000000);
+  status |= test__subdf3(0x8010000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |= test__subdf3(0x8010000000000001, 0x8010000000000000, 0x8000000000000001);
+  status |= test__subdf3(0x8010000000000001, 0x8010000000000002, 0x0000000000000001);
+  status |= test__subdf3(0x801fffffffffffff, 0x8020000000000000, 0x0000000000000001);
+  status |= test__subdf3(0x801fffffffffffff, 0x8020000000000002, 0x0000000000000005);
+  status |= test__subdf3(0x801fffffffffffff, 0x8020000000000004, 0x0000000000000009);
+  status |= test__subdf3(0x8020000000000000, 0x801fffffffffffff, 0x8000000000000001);
+  status |= test__subdf3(0x8020000000000001, 0x8010000000000001, 0x8010000000000001);
+  status |= test__subdf3(0x8020000000000001, 0x801fffffffffffff, 0x8000000000000003);
+  status |= test__subdf3(0x8020000000000002, 0x8010000000000001, 0x8010000000000003);
+  status |= test__subdf3(0x802fffffffffffff, 0x8030000000000000, 0x0000000000000002);
+  status |= test__subdf3(0x8030000000000000, 0x802fffffffffffff, 0x8000000000000002);
+  status |= test__subdf3(0x8030000000000001, 0x802fffffffffffff, 0x8000000000000006);
+  status |= test__subdf3(0x8030000000000002, 0x8020000000000003, 0x8020000000000001);
+  status |= test__subdf3(0xbff0000000000000, 0x0000000000000000, 0xbff0000000000000);
+  status |= test__subdf3(0xbff0000000000000, 0x3ff0000000000003, 0xc000000000000002);
+  status |= test__subdf3(0xbff0000000000001, 0x3ff0000000000000, 0xc000000000000000);
+  status |= test__subdf3(0xbff0000000000001, 0xbff0000000000000, 0xbcb0000000000000);
+  status |= test__subdf3(0xbff0000000000001, 0xbff0000000000002, 0x3cb0000000000000);
+  status |= test__subdf3(0xbffffffffffffffc, 0xbffffffffffffffd, 0x3cb0000000000000);
+  status |= test__subdf3(0xbfffffffffffffff, 0x8000000000000001, 0xbfffffffffffffff);
+  status |= test__subdf3(0xbfffffffffffffff, 0xc000000000000000, 0x3cb0000000000000);
+  status |= test__subdf3(0xc000000000000000, 0x4000000000000001, 0xc010000000000000);
+  status |= test__subdf3(0xc000000000000000, 0xbfffffffffffffff, 0xbcb0000000000000);
+  status |= test__subdf3(0xc000000000000000, 0xc000000000000001, 0x3cc0000000000000);
+  status |= test__subdf3(0xc000000000000001, 0x4000000000000002, 0xc010000000000002);
+  status |= test__subdf3(0xc000000000000001, 0xbff0000000000001, 0xbff0000000000001);
+  status |= test__subdf3(0xc000000000000002, 0xbff0000000000001, 0xbff0000000000003);
+  status |= test__subdf3(0xc000000000000002, 0xbff0000000000003, 0xbff0000000000001);
+  status |= test__subdf3(0xc000000000000004, 0xc000000000000003, 0xbcc0000000000000);
+  status |= test__subdf3(0xc008000000000000, 0xc008000000000000, 0x0000000000000000);
+  status |= test__subdf3(0xc00fffffffffffff, 0x3cafffffffffffff, 0xc00fffffffffffff);
+  status |= test__subdf3(0xc00fffffffffffff, 0x3cb0000000000000, 0xc010000000000000);
+  status |= test__subdf3(0xc00fffffffffffff, 0xc00ffffffffffffe, 0xbcc0000000000000);
+  status |= test__subdf3(0xc00fffffffffffff, 0xc010000000000002, 0x3ce4000000000000);
+  status |= test__subdf3(0xc010000000000001, 0xc00fffffffffffff, 0xbcd8000000000000);
+  status |= test__subdf3(0xffb0000000000001, 0xffafffffffffffff, 0xfc78000000000000);
+  status |= test__subdf3(0xffcfffffffffffff, 0xffcffffffffffffe, 0xfc80000000000000);
+  status |= test__subdf3(0xffcfffffffffffff, 0xffd0000000000002, 0x7ca4000000000000);
+  status |= test__subdf3(0xffd0000000000000, 0xffcfffffffffffff, 0xfc80000000000000);
+  status |= test__subdf3(0xffd0000000000000, 0xffd0000000000001, 0x7c90000000000000);
+  status |= test__subdf3(0xffd0000000000001, 0x7fd0000000000000, 0xffe0000000000000);
+  status |= test__subdf3(0xffd0000000000001, 0xffe0000000000001, 0x7fd0000000000001);
+  status |= test__subdf3(0xffd0000000000002, 0xffc0000000000003, 0xffc0000000000001);
+  status |= test__subdf3(0xffd0000000000004, 0xffd0000000000003, 0xfc90000000000000);
+  status |= test__subdf3(0xffdffffffffffffe, 0x7fdffffffffffffe, 0xffeffffffffffffe);
+  status |= test__subdf3(0xffdffffffffffffe, 0x7fdfffffffffffff, 0xffeffffffffffffe);
+  status |= test__subdf3(0xffdffffffffffffe, 0xffdffffffffffffe, 0x0000000000000000);
+  status |= test__subdf3(0xffdfffffffffffff, 0x3ff0000000000000, 0xffdfffffffffffff);
+  status |= test__subdf3(0xffdfffffffffffff, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xffdfffffffffffff, 0xbff0000000000000, 0xffdfffffffffffff);
+  status |= test__subdf3(0xffdfffffffffffff, 0xffe0000000000000, 0x7c90000000000000);
+  status |= test__subdf3(0xffe0000000000000, 0x0000000000000000, 0xffe0000000000000);
+  status |= test__subdf3(0xffe0000000000000, 0x3ff0000000000000, 0xffe0000000000000);
+  status |= test__subdf3(0xffe0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xffe0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xffe0000000000000, 0x8000000000000000, 0xffe0000000000000);
+  status |= test__subdf3(0xffe0000000000000, 0xbff0000000000000, 0xffe0000000000000);
+  status |= test__subdf3(0xffe0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__subdf3(0xffe0000000000001, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xffe0000000000001, 0xffe0000000000000, 0xfca0000000000000);
+  status |= test__subdf3(0xffe0000000000001, 0xffe0000000000002, 0x7ca0000000000000);
+  status |= test__subdf3(0xffe0000000000002, 0xffd0000000000001, 0xffd0000000000003);
+  status |= test__subdf3(0xffeffffffffffffe, 0x3ff0000000000000, 0xffeffffffffffffe);
+  status |= test__subdf3(0xffeffffffffffffe, 0x7feffffffffffffe, 0xfff0000000000000);
+  status |= test__subdf3(0xffeffffffffffffe, 0x7fefffffffffffff, 0xfff0000000000000);
+  status |= test__subdf3(0xffeffffffffffffe, 0xbff0000000000000, 0xffeffffffffffffe);
+  status |= test__subdf3(0xffeffffffffffffe, 0xffefffffffffffff, 0x7ca0000000000000);
+  status |= test__subdf3(0xffefffffffffffff, 0x3ff0000000000000, 0xffefffffffffffff);
+  status |= test__subdf3(0xffefffffffffffff, 0x8000000000000001, 0xffefffffffffffff);
+  status |= test__subdf3(0xffefffffffffffff, 0xbff0000000000000, 0xffefffffffffffff);
+  status |= test__subdf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
+  status |= test__subdf3(0xfff0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xfff0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xfff0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0xfff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |= test__subdf3(0xfff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__subdf3(0x004caed458edc883, 0x004f7fc23eeef153, 0x8016876f30094680);
+  status |= test__subdf3(0x0028000000000000, 0x0010000000000001, 0x001fffffffffffff);
+  status |= test__subdf3(0x0028000000000000, 0x0010000000000000, 0x0020000000000000);
+  status |= test__subdf3(0x001fffffffffffff, 0x0010000000000000, 0x000fffffffffffff);
+  status |= test__subdf3(0x001fffffffffffff, 0x000fffffffffffff, 0x0010000000000000);
+  status |= test__subdf3(0x0020000000000000, 0x0010000000000000, 0x0010000000000000);
+  status |= test__subdf3(0x0038000000000000, 0x0034000000000001, 0x000ffffffffffffc);
+  status |= test__subdf3(0x0038000000000000, 0x0034000000000000, 0x0010000000000000);
+  status |= test__subdf3(0x0038000000000000, 0x0030000000000001, 0x001ffffffffffffc);
+  status |= test__subdf3(0x0038000000000000, 0x0030000000000000, 0x0020000000000000);
+  status |= test__subdf3(0x000fffffffe00000, 0x801000000007ffff, 0x001fffffffe7ffff);
+  status |= test__subdf3(0x0010000000004000, 0x800effffffffffff, 0x001f000000003fff);
+  status |= test__subdf3(0x800000000fffffff, 0x001ffff000000000, 0x801ffff00fffffff);
+  status |= test__subdf3(0x800fffff80000000, 0x001000000fffffff, 0x801fffff8fffffff);
+  status |= test__subdf3(0x80100000001fffff, 0x000ffffeffffffff, 0x801fffff001ffffe);
+
+  // Test that the result of an operation is a NaN at all when it should be.
+  //
+  // In most configurations these tests' results are checked compared using
+  // compareResultD, so we set all the answers to the canonical NaN
+  // 0x7ff8000000000000, which causes compareResultF to accept any NaN
+  // encoding. We also use the same value as the input NaN in tests that have
+  // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
+  // because 0x7ff8000000000000 is still the exact expected NaN.
+  status |= test__subdf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |= test__subdf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |= test__subdf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |= test__subdf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |= test__subdf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+
+#ifdef ARM_NAN_HANDLING
+  // Tests specific to the NaN handling of Arm hardware, mimicked by
+  // the subtraction function in arm/adddf3.S:
+  //
+  //  - a quiet NaN is distinguished by the top mantissa bit being 1
+  //
+  //  - if a signalling NaN appears in the input, the output quiet NaN is
+  //    obtained by setting its top mantissa bit and leaving everything else
+  //    unchanged
+  //
+  //  - if both operands are signalling NaNs then the output NaN is derived
+  //    from the first operand
+  //
+  //  - if both operands are quiet NaNs then the output NaN is the first
+  //    operand
+  //
+  //  - invalid operations not involving an input NaN return the quiet
+  //    NaN with fewest bits set, 0x7ff8000000000000.
+  status |= test__subdf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |= test__subdf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |= test__subdf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |= test__subdf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |= test__subdf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |= test__subdf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |= test__subdf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |= test__subdf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |= test__subdf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |= test__subdf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |= test__subdf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |= test__subdf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |= test__subdf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |= test__subdf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |= test__subdf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |= test__subdf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |= test__subdf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |= test__subdf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |= test__subdf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |= test__subdf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |= test__subdf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |= test__subdf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |= test__subdf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |= test__subdf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |= test__subdf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |= test__subdf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |= test__subdf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |= test__subdf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |= test__subdf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |= test__subdf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |= test__subdf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |= test__subdf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |= test__subdf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |= test__subdf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |= test__subdf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |= test__subdf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |= test__subdf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |= test__subdf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |= test__subdf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |= test__subdf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |= test__subdf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |= test__subdf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |= test__subdf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |= test__subdf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |= test__subdf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |= test__subdf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |= test__subdf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |= test__subdf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |= test__subdf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |= test__subdf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |= test__subdf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |= test__subdf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+
+#endif // ARM_NAN_HANDLING
+
+  return status;
+}

>From 76b373d79cdc7bf245fe8ebdce77225005a18162 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 16:07:17 +0000
Subject: [PATCH 05/33] [compiler-rt][ARM] Optimized double-precision FP
 mul/div

Optimized AArch32 implementations of `muldf3` and `divdf3` are
provided. The division function is particularly tricky because its
Newton-Raphson approximation strategy requires a rigorous error bound.
In this version of the commit I've left out the full supporting
machinery that validates the error bound via Gappa and Rocq, but full
details are provided via links to the upstream version of this code in
the Arm Optimized Routines repository, and to a pair of Arm Community
blog posts.
---
 compiler-rt/lib/builtins/CMakeLists.txt       |   2 +
 compiler-rt/lib/builtins/arm/divdf3.S         | 620 ++++++++++++++++++
 compiler-rt/lib/builtins/arm/muldf3.S         | 404 ++++++++++++
 .../test/builtins/Unit/divdf3new_test.c       | 471 +++++++++++++
 .../test/builtins/Unit/muldf3new_test.c       | 456 +++++++++++++
 5 files changed, 1953 insertions(+)
 create mode 100644 compiler-rt/lib/builtins/arm/divdf3.S
 create mode 100644 compiler-rt/lib/builtins/arm/muldf3.S
 create mode 100644 compiler-rt/test/builtins/Unit/divdf3new_test.c
 create mode 100644 compiler-rt/test/builtins/Unit/muldf3new_test.c

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 6c01c7ec9d95f..b8e328f657eea 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -448,6 +448,8 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm")
       arm/mulsf3.S
       arm/divsf3.S
       arm/adddf3.S
+      arm/muldf3.S
+      arm/divdf3.S
       )
     set_source_files_properties(${assembly_files}
       PROPERTIES COMPILE_OPTIONS ${implicit_it_flag})
diff --git a/compiler-rt/lib/builtins/arm/divdf3.S b/compiler-rt/lib/builtins/arm/divdf3.S
new file mode 100644
index 0000000000000..48b0dbe8d346e
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/divdf3.S
@@ -0,0 +1,620 @@
+//===-- divdf3.S - double-precision floating point division ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the __divdf3 function (double precision floating point
+// division), with the IEEE-754 default rounding (to nearest, ties to even),
+// for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+// The basic strategy of this division code is to use Newton-Raphson iteration
+// to calculate an approximation to 1/y, then multiply it by x. This procedure
+// delivers a quotient with 10 extra bits of precision, but which isn't exact.
+// We know an upper bound on its possible error, which gives an interval of
+// possible values for the true quotient. So we can check the 10 extra bits to
+// see whether a rounding boundary lies within the interval. If not, then we
+// can round and return without worrying further; otherwise, we go to slower
+// correction code that multiplies the approximate quotient back up by y and
+// checks it against x.
+//
+// This strategy depends critically on the upper bound on the approximation
+// error. Underestimating the error introduces a bug; overestimating it costs
+// performance, by sending more cases than necessary to the slow path.
+//
+// To give high confidence of its correctness, the upper bound has been proved
+// formally by Gappa. The Gappa proof and auxiliary code are not included in
+// this version, but they can be found in the Arm Optimized Routines repository
+//
+// https://github.com/ARM-software/optimized-routines/blob/bf3e44c3784dd3e18d3d5232e13b4d81f232310b/fp/at32/ddiv.S
+// https://github.com/ARM-software/optimized-routines/blob/bf3e44c3784dd3e18d3d5232e13b4d81f232310b/fp/auxiliary/ddiv-prove.py
+// https://github.com/ARM-software/optimized-routines/blob/bf3e44c3784dd3e18d3d5232e13b4d81f232310b/fp/auxiliary/ddiv-diagnostics.c
+//
+// and a pair of blog posts describing the concepts and procedure are here:
+//
+// https://developer.arm.com/community/arm-community-blogs/b/embedded-and-microcontrollers-blog/posts/formally-verifying-a-floating-point-division-routine-with-gappa-p1
+// https://developer.arm.com/community/arm-community-blogs/b/embedded-and-microcontrollers-blog/posts/formally-verifying-a-floating-point-division-routine-with-gappa-p2
+
+  .syntax unified
+  .text
+  .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__divdf3)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  VMOV_FROM_DOUBLE(r2, r3, d1)
+  bl __aeabi_ddiv
+  VMOV_TO_DOUBLE(d0, r0, r1)
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__divdf3, __aeabi_ddiv)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_ddiv)
+
+  push    {r4,r5,r6,r7,r8,lr}
+
+  // Check if either input exponent 7FF (infinity or NaN), and if so, branch
+  // out of line.
+  ldr     r12, =0x07FF0000        // mask for exponent cold storage
+  bics    r4, r12, xh, lsr #4     // test for Infs or NaNs
+  bicsne  r4, r12, yh, lsr #4
+  beq     LOCAL_LABEL(ddiv_naninf)
+
+  // Extract the exponents of the input values x and y into bits 16..26 of r14
+  // and r5 respectively, and in the process, check if either exponent is zero
+  // (so that one or both inputs are 0 or denormal). In order to combine the
+  // two tests, the second ANDS is performed conditionally, so that if x's
+  // exponent is zero then the out-of-line code at ddiv_zerodenorm might find
+  // y's exponent hasn't been set up yet.
+  //
+  // We also calculate the sign of the result, which will be needed whether or
+  // not we branch. This is saved in the low bit of r4.
+  ands    r4, r12, xh, lsr #4     // get exponent of x, setting Z if it's 0
+  andsne  r5, r12, yh, lsr #4     // if not, extract and test exponent of y
+  eor     r6, xh, yh              // XOR the input signs to get the result sign
+  orr     r4, r4, r6, lsr #31     // save it in the low bit of r4
+  beq     LOCAL_LABEL(ddiv_zerodenorm)         // branch out of line for zeroes or denormals
+
+  // Calculate the initial exponent of the result, by subtracting the two input
+  // exponents and adjusting for the IEEE exponent bias. This value may have to
+  // be adjusted by 1 later, depending on the quotient of the mantissas.
+  //
+  // If we branched to ddiv_zerodenorm above, and it found denormals but no
+  // zeroes, it may branch back here after renormalising them. We expect the
+  // out-of-line code to have left the exponent difference in the top half of
+  // r4 (still with the output sign in the low bit), but not yet to have
+  // applied the bias. So it branches back in immediately after the SUB.
+  //
+  // The exponent bias we want is either 0x3fe or 0x3ff, depending on whether
+  // we have to shift the output mantissa by 1 below. Neither of those values
+  // fits in the immediate field of an ADD instruction, so we must use two
+  // instructions.
+  sub     r4, r4, r5
+LOCAL_LABEL(ddiv_normalised): // denormal handler will come back to here
+  add     r4, r4, #0x03FC0000     // add the 8 high bits of the bias 0x3FE
+  add     r4, r4, #0x00020000     // add the remaining bit of the bias
+
+  // Shift both mantissas up to the top of their 64-bit register pair, and OR
+  // in the leading 1 bit, which will occupy the high bit of the high word in
+  // each case.
+  mov     r5, #1<<31              // high bit for ORing in to both mantissas
+  orr     xh, r5, xh, lsl #11     // shift up xh and OR in the high bit
+  orr     yh, r5, yh, lsl #11     // same for yh
+  orr     xh, xh, xl, lsr #21     // OR in the bits shifted out of xl into xh
+  orr     yh, yh, yl, lsr #21     // same for yl and yh
+  lsl     xl, xl, #11             // shift up the rest of xl
+  lsl     yl, yl, #11             // same for yl
+
+  // Check if the two mantissas are exactly equal, so that the quotient is
+  // exactly a power of 2. If so, branch out of line to handle that case
+  // specially.
+  //
+  // This guarantees that when we examine the approximate quotient afterwards,
+  // we can't be confused about whether it needs to be renormalised, which
+  // would otherwise cost just as much effort as this check. Our reciprocal
+  // approximation is always an underestimate (that's in the nature of this
+  // particular Newton-Raphson iteration), so if x < y (meaning the mantissas
+  // rather than the whole floats) then even the true quotient will be less
+  // than 1, and the approximation even more so. On the other hand, if x > y,
+  // then the true quotient will be enough greater than 1 that even the largest
+  // possible error in the approximation can't make it look like less than 1.
+  //
+  // (Proof: regard x,y as normalised to the range [1,2). If x > y, then we
+  // have x ≥ y+ε, where ε is the machine epsilon. So x/y ≥ 1+ε/y > 1+ε/2. And
+  // the bound on the approximation error, given below, is far less than ε/2.)
+  cmp     xh, yh
+  cmpeq   xl, yl
+  beq     LOCAL_LABEL(ddiv_result_is_power_of_2)
+
+  // Now we begin the actual calculation of the reciprocal approximation.
+  //
+  // We begin with our two input mantissas stored in xh:xl and yh:yl, each with
+  // its leading 1 explicit and shifted up to the top of the word. So they can
+  // be regarded as 64-bit integers with the high bit set and the bottom 11
+  // bits clear.
+
+  // Obtain an 8-bit reciprocal approximation by using the topmost 8 bits of y
+  // as a lookup table. The top bit of y is always set, so there are only 128
+  // lookup table entries, not 256. The 8-bit value we load also has its top
+  // bit set.
+  lsr     r5, yh, #24           // r5 is the table index plus 0x80
+  adr     r6, LOCAL_LABEL(reciptbl)-128      // so subtract 0x80 from the table address
+  ldrb    r6, [r6, r5]          // and load the approximation into r6
+
+  // First Newton-Raphson iteration, which expands that 8-bit approximation to
+  // a 17-bit one, again with its top bit set. We use the top 16 bits of y for
+  // this, so that we can fit the multiplications into ordinary MUL rather than
+  // UMULL.
+  //
+  // The Newton-Raphson formula to turn an approximation r ≈ 1/y into a better
+  // one is r → r(2-yr). In this case we're scaling up to integers (informal
+  // fixed point), so the 2 becomes 2^24.
+  lsr     r5, yh, #16           // get top halfword of y
+  mul     r7, r6, r5            // multiply it by the input value r
+  rsb     r7, r7, #1<<24        // subtract from 2 (scaled up appropriately)
+  mul     r7, r6, r7            // multiply again to make r(2-yr)
+  lsr     r7, r7, #14           // shift down to keep only 17 bits of it
+
+  // Second iteration, expanding into a 32-bit reciprocal, using the top 31
+  // bits of y (i.e. yh shifted by 1). The first multiplication (making yr) is
+  // 32x32 → 64 bits, so we use a single UMULL; the second one making r(2-yr)
+  // is 32x64, which we do with a UMULL by the bottom half of yr and then MLA
+  // by the top half, so we only keep the low 64 bits of the full answer.
+  //
+  // The subtraction from 2 (again scaled up, this time to 2^48) is done by
+  // RSBS+RSC, interleaved with the multiplications so as to use a delay slot
+  // on CPUs that have one.
+  lsr     r12, yh, #1
+  umull   r6, r8, r7, r12       // r8:r6 = yr
+  rsbs    r6, r6, #0            // low half of subtraction from 2
+  umull   r12, lr, r7, r6       // multiply r by the low half of 2-yr
+#if !__thumb__
+  rsc     r8, r8, #1<<16        // high half of subtraction from 2
+#else
+  // Thumb has no RSC, so simulate it by bitwise inversion and then ADC
+  mvn     r8, r8
+  adc     r8, r8, #1<<16
+#endif
+  mla     r6, r7, r8, lr        // multiply r by the high half of 2-yr
+
+  // Third iteration, expanding into a 64-bit reciprocal, with the leading bit
+  // expected to end up in bit 60. Now the first multiplication to make yr is
+  // 32x64 → 96 bits, so we put the product in three registers lr:r12:r8.
+  // However, we're going to discard the low word r8 completely, because it
+  // makes negligible difference. So we'll treat the output yr as 64-bit.
+  umull   r8, r12, r6, yl       // multiply r by bottom half of y
+  mov     lr, #0                // initialize high word to 0
+  umlal   r12, lr, r6, yh       // multiply r by top half of y
+  // Subtract from a power of 2, as usual. But in this case the power of 2
+  // we're subtracting from is 2^64, which is just off the top of the 64-bit
+  // value in lr:r12. So in fact we're just negating the whole thing!
+  //
+  // To preserve the invariant that the approximation error is always negative,
+  // we negate via one's complement rather than two's. (This would only make a
+  // difference if r8 had happened to be exactly 0. That in turn can occur when
+  // yl=0, so one of the test cases in ddiv-diagnostics.c deliberately uses
+  // such a value, so that the intermediate results can be checked against the
+  // reference Python.)
+  mvn     r12, r12
+  mvn     lr, lr
+  // Now lr:r12:r8 contains 2-yr. We discard the low word r8 to reduce that to
+  // 64 bits, and do another 32x64 → 96 bit multiplication.
+  umull   r5, r8, r6, r12      // multiply r by bottom half of 2-yr
+  mov     r7, #0               // initialize high word to 0
+  umlal   r8, r7, r6, lr       // multiply r by top half of 2-yr
+
+  // That's the Newton-Raphson iteration done: we have a 64-bit approximation
+  // to 1/y. Multiply it by x to get the full approximate quotient.
+  //
+  // In principle, this would be a 64x64 → 128 bit multiplication, involving
+  // four long multiply instructions. But we only need the top 64 bits, and
+  // we're already prepared to tolerate some error in the calculations, so we
+  // cut corners: don't multiply the two low words together at all, and we
+  // discard the bottom half of each of the (low * high) partial products
+  // without bothering to propagate carries out of it.
+  //
+  // (All of these shortcuts are faithfully mimicked in the Python reference
+  // implementation which generates Gappa input, so they're all accounted for
+  // in the error analysis.)
+#if __ARM_FEATURE_DSP
+  umull   r12, r6, xh, r8      // r6 = high word of x * low word of 1/y
+  umull   r12, r5, xl, r7      // r5 = low word of x * high word of 1/y
+  umaal   r6, r5, xh, r7       // add those to the product of both high words
+#else
+  // Alternative instruction sequence using UMLAL, if UMAAL isn't available
+  umull   r12, r6, xh, r8      // r6 = high word of x * low word of 1/y
+  umull   r12, lr, xl, r7      // lr = low word of x * high word of 1/y
+  adds    r6, r6, lr           // add those together
+  mov     r5, #0               // set r5 to the carry out of that addition
+  adc     r5, r5, #0
+  umlal   r6, r5, xh, r7       // add that to the product of both high words
+#endif
+  // Now r5:r6 is the completed approximate quotient, with its leading bit at
+  // position either 61 or 62.
+
+  // Normalize so that the leading bit is always in bit 60, by shifting left if
+  // it isn't there already, and adjusting the output exponent by 1 to
+  // compensate.
+  //
+  // We do the test in a slightly tricky way, by arranging to set the V flag if
+  // the leading bit is in bit 60. This allows us to do the left shift under
+  // the VC condition, which is convenient because the LSLS instruction that
+  // shifts the low word left moves the top bit into the C flag without
+  // affecting V.
+  //
+  // We also save the value written into lr by the initial ADDS instruction,
+  // because that contains enough information to tell us whether we
+  // renormalised here. The correction path for quotients too close to a
+  // rounding boundary will need to recover that information.
+  adds    lr, r5, #0x40000000  // set V flag if bit 62 of high word set
+  subvc   r4, r4, #1<<16       // if not, correct the exponent by 1,
+  lslsvc  r6, r6, #1           // shift the low word of the quotient left
+  adcvc   r5, r5, r5           // and shift its top bit into the high word
+
+  // Now r5:r6 is the _normalised_ approximate quotient, with its leading bit
+  // reliably in bit 60. This is the final output of the calculation that the
+  // Gappa error-analysis proof applies to.
+
+  // That 64-bit output has bit 63 clear; the leading 1 bit of the output
+  // mantissa in bit 62, followed by 52 more mantissa bits; then 10 bits at the
+  // bottom which are used for determining rounding.
+  //
+  // Compute the _approximately_ rounded-to-nearest output mantissa, by adding
+  // half a ULP and shifting down. If we don't go to the slow path, this is the
+  // correct output mantissa. (See fdiv.S for the proof that the round-to-even
+  // tiebreaking case can't occur in floating-point division.)
+  //
+  // We keep the original version of r6, containing the ten rounding bits, so
+  // that we can test it to see if we need the slow path.
+  adds    r7, r6, #1<<9        // add half a ULP, copying low word into r7
+  adc     r5, r5, #0           // propagate carry into high word
+  lsr     r7, r7, #10          // shift low word right
+  orr     r7, r7, r5, lsl #22  // combine with bits shifted out of high word
+  lsr     r5, r5, #10          // shift high word right
+
+  // Now test r6 to see whether this output mantissa can be relied on, or
+  // whether the approximation landed too close to a rounding boundary.
+  //
+  // The maximum possible error in the approximation, taking into account the
+  // initial error in each lookup table entry, the remaining mathematical error
+  // introduced by stopping after this many Newton-Raphson iterations, and
+  // every shortcut, right shift, truncation and discarding of a partial
+  // product in the algorithm above, is always negative, and less than 64 units
+  // in the last place of the 64-bit approximate quotient. That is, the true
+  // quotient lies somewhere between the 64-bit integer described as "final
+  // output of the calculation" above, and that plus 64.
+  //
+  // So if the bottom 10 bits of r6 have the value 2^9 or greater, we're safe,
+  // because the true value is _larger_ than the approximation, so if the
+  // approximation is already above the rounding boundary then so is the true
+  // value. And if those 10 bits are (2^9-64) or less then we're also safe,
+  // because even if the true value is greater by 63, it's still on the same
+  // side of the rounding boundary.
+  //
+  // We check the error by subtracting (2^9-64), so that the dangerous values
+  // of the bottom 10 bits are those in the range 0,...,63, i.e. precisely
+  // those with none of bits 6,7,8,9 set.
+  //
+  // We also combine this test with a check for underflow, because that also
+  // needs more careful handling (the mantissa must be re-rounded to a
+  // different bit position, which involves knowing whether it's exact).
+  // Underflow has happened if the exponent in the top half of r4 is negative
+  // (it's off by 1 so that the leading mantissa bit will increment it), so we
+  // test by an ASR#31 (copying the top bit of r4 into all of it) and negating.
+  // That way, the output value is zero on underflow, matching the flags from
+  // the other check.
+  sub     r6, r6, #(1<<9)-64
+  tst     r6, #0x3C0              // now EQ means we must go to the slow path
+  mvnsne  r12, r4, asr #31        // also set EQ if underflow has happened
+  beq     LOCAL_LABEL(ddiv_correction)         // branch out of line to do the hard bit
+
+  // If we do go to ddiv_correction, it branches back here after the correction
+  // code has finished. Either way, we expect that r5:r7 is the result
+  // mantissa, with the top bit set, already in the correct position in the
+  // word, and already rounded to nearest.
+LOCAL_LABEL(ddiv_corrected):
+  // Recombine the output mantissa with the sign and exponent.
+  add     xh, r5, r4, lsl #31     // add sign bit to top word of mantissa
+  bic     r12, r4, #1             // isolate exponent in top half of r4
+  add     xh, xh, r12, lsl #4     // add exponent to make the final high word
+  mov     xl, r7                  // move low word into the right register
+
+  // If there's no overflow or underflow, we're done.
+  //
+  // We _identified_ underflow above when we went to the slow path, but having
+  // done that, the slow path came back here, so we must check for it again.
+  // (The only purpose of the detour was to obtain accurate information about
+  // whether the quotient is exact, or needed rounding.)
+  //
+  // The output exponent, offset downwards by 1, is in the top half of r4. If
+  // it's negative, there's an underflow; if it's too large, there's an
+  // overflow. We do an approximate test for both at once via an unsigned
+  // comparison against 0x7f0, using r12 (the register in which we already
+  // cleared the sign bit stored at the bottom). This identifies _most_ normal
+  // outputs as quickly as possible.
+  //
+  // 0x7f0 isn't the maximum possible known-safe exponent, but it's the largest
+  // one that fits in the immediate field of CMP. We deal with the remaining
+  // cases in the next few instructions.
+  cmp     r12, #0x7f0 << 16
+  popls   {r4,r5,r6,r7,r8,pc}
+
+  // Now check the remaining cases more carefully.
+  //
+  // If r12 < 0 then we definitely have underflow. We detect overflow precisely
+  // by seeing if the _final_ output exponent (in the output register xh) is
+  // 0x7ff or more, by incrementing it and seeing if the sign is opposite from
+  // the intended output sign.
+  add     lr, xh, #1<<20          // increment the output exponent field
+  teq     lr, r4, lsl #31         // set N if the sign now doesn't match r4[0]
+  tstpl   r12, r12                // otherwise, set N if underflow
+  poppl   {r4,r5,r6,r7,r8,pc}     // if neither, we've finished
+
+  // If we still haven't returned, we really do have overflow or underflow, and
+  // the sign of r12 tells us which.
+  tst     r12, r12
+  bmi     LOCAL_LABEL(ddiv_underflow)
+  // For overflow, correct the sign by biasing the exponent downward, and go to
+  // code that constructs an infinite return value (shared with the
+  // division-by-zero handler).
+  sub     xh, xh, #0x60000000
+  pop     {r4,r5,r6,r7,r8,lr}     // ddiv_retinf expects no regs on the stack
+  b       LOCAL_LABEL(ddiv_retinf)
+
+LOCAL_LABEL(ddiv_correction):
+  // The slow path, entered if the approximate quotient was too close to a
+  // rounding boundary to trust, and also if there's a chance of underflow (so
+  // that we can reliably determine the rounding direction, including whether
+  // the quotient was exact).
+  //
+  // Regarding the input mantissas x,y and our approximate quotient q as
+  // integers in [2^52,2^53), the quotient is an approximation to either
+  // x*2^52/y or x*2^53/y, depending on which of x,y was larger. We know that q
+  // is less than the true value of that quotient by at most a small fraction
+  // of a ULP. So the correct rounded quotient is either equal to q or to q+1,
+  // and we can decide which by multiplying back up by y: we want q - x*2^k/y
+  // to be in the range (-1/2,+1/2) (where k = 52 or 53), which is equivalent
+  // to asking if qy - x*2^k is in the range (-y/2,+y/2).
+  //
+  // That's a calculation we can do in integers using only addition and
+  // multiplication. And we know that if q itself doesn't have that property
+  // then q+1 will.
+
+  // The mantissa of y is currently right at the top of the word, which means
+  // that if the result of our check is greater than it, it will overflow. So
+  // we must start by shifting y downward. We'll put it back at the bottom of
+  // the word, where it was in the input float.
+  lsr     yl, yl, #11             // shift yl right
+  orr     yl, yl, yh, lsl #21     // OR in the bits shifted out of yh
+  lsr     yh, yh, #11             // shift yh right
+
+  // Compute the integer qy-x. Because q is already very close to the right
+  // quotient, we expect this to be an integer at most twice the size of y,
+  // which easily fits in 64 bits. So we don't need to compute the full 128-bit
+  // product: the low 64 bits are enough.
+  umull   r8, r6, r7, yl          // 64-bit product of the low words
+  mla     r6, r7, yh, r6          //   + (high word of y) * (low word of q)
+  mla     r6, r5, yl, r6          //   + (high word of q) * (low word of y)
+
+  // Now we must subtract either x << 53 or x << 52. This will only affect the
+  // high word of the product we've just computed. Also the mantissa of x is
+  // already shifted left by 11. So we shift xl left by either (52-32-11) or
+  // (53-32-11), i.e. by 9 or by 10, and subtract from the high word of the
+  // product.
+  //
+  // To decide which, we consult the value left in lr by the original test for
+  // renormalization, which added 0x40000000 to the high word of the initial
+  // approximate quotient 'quot'. If that had bit 62 set (so no renormalization
+  // needed) then the addition carried into the sign bit; otherwise it didn't.
+  // So lr is positive if and only if we need to shift xl left by an extra bit.
+  tst     lr, lr                  // did we renormalize?
+  subpl   r6, r6, xl, lsl #10     // if so, subtract x<<53 from q*y
+  submi   r6, r6, xl, lsl #9      // if not, subtract x<<52
+
+  // Now r6:r8 contains the residual value r = qy - x*2^k as described above.
+  // If this is between -y/2 and +y/2 then q is already the correctly rounded
+  // quotient. Otherwise, the correct quotient is q+1, so the value in r6:r8
+  // will be too small (incrementing q would add y to it). So we need to check
+  // whether r < -y/2, or equivalently whether 2r < -y (avoiding having to
+  // worry about what happens when we halve y if it's odd).
+  //
+  // As mentioned above, division can't give an exact halfway case, so we don't
+  // need to worry about the case r = y/2.
+  adds    r8, r8, r8              // multiply the residual by 2
+  adc     r6, r6, r6
+  adds    lr, r8, yl              // add y to it, discarding the result
+  adcs    lr, r6, yh
+  bpl     LOCAL_LABEL(ddiv_corrected)          // if the answer is positive, we're OK
+
+  // If we didn't take that branch, then the approximate quotient is too small
+  // by 1, so we must increment it. But also, we adjust the residual in r6:r8
+  // to match. That residual is unused by the main epilogue code, but we also
+  // came here for any underflowing value, and the underflow handler will need
+  // the exact residual to determine the rounding direction.
+  //
+  // (We could re-test whether underflow had happened and use that to skip the
+  // update of r6:r8, but the test would cost as much effort as it saved!)
+  adds    r7, r7, #1              // increment the output quotient
+  adcs    r5, r5, #0
+  adds    r8, r8, yl              // repeat the addition of y to the residual,
+  adcs    r6, r6, yh              //   this time keeping the result in r6:r8
+  b       LOCAL_LABEL(ddiv_corrected)          // finally we can rejoin the main code
+
+LOCAL_LABEL(ddiv_result_is_power_of_2):
+  // The special-case handler for the two input mantissas being equal, so that
+  // the result is an exact power of two. We set up all the output registers to
+  // the way the main code would have done it, and jump straight to
+  // ddiv_corrected. This includes setting r6:r8 to the 'residual' value
+  // computed by the slow path, in case this power-of-2 output is also an
+  // underflow, which will depend on those registers.
+  mov     r5, #0x00100000         // high word of quotient mantissa = 1<<20
+  mov     r7, #0                  // low word of quotient mantissa = 0
+  mov     r6, #0                  // high word of residual = 0
+  mov     r8, #0                  // low word of residual = 0
+  b       LOCAL_LABEL(ddiv_corrected)
+
+LOCAL_LABEL(ddiv_underflow):
+  // We come here to handle underflow. The output double, constructed naïvely
+  // from the out-of-range exponent, is in xh:xl. We expect in this situation
+  // that we've _always_ come via either the ddiv_correction slow path or the
+  // ddiv_result_is_power_of_2 special case, both of which will have set up a
+  // residual value in r6:r8 equal to q*y - x*2^k (for appropriate k). This
+  // value is positive if the quotient is slightly above the true value (i.e.
+  // was rounded up), or negative if the quotient was rounded down. But we must
+  // also distinguish the third case of the residual being exactly zero.
+  add     xh, xh, #0x60000000     // apply IEEE 754 exponent bias for __dunder
+  orrs    r12, r6, r8             // set r12=0 and Z=1 if quotient was exact
+  movne   r12, #1                 // otherwise, set r12 = +1
+  orrne   r12, r12, r6, asr #31   // and change to -1 if residual is negative
+  pop     {r4,r5,r6,r7,r8,lr}     // pop all locally saved registers
+  b       SYMBOL_NAME(__compiler_rt_dunder)                // and tailcall __dunder to finish
+
+LOCAL_LABEL(ddiv_zerodenorm):
+  // We come here if either input had exponent 0, so there's at least one zero
+  // or denormal. However, we know there are no infinities or NaNs, because
+  // those were checked first and will have gone to ddiv_naninf below.
+  //
+  // First we must repeat the instruction which extracted the exponent of y
+  // into r5, this time unconditionally, in case the setup code didn't do it.
+  and     r5, r12, yh, lsr #4
+
+  // If either or both input is actually zero, the answer is easy.
+  orrs    lr, xl, xh, lsl #1    // is x zero?
+  beq     LOCAL_LABEL(ddiv_xzero)
+  orrs    lr, yl, yh, lsl #1    // is y zero?
+  beq     LOCAL_LABEL(ddiv_divbyzero)
+
+  // Otherwise, delegate to __dnorm2 to handle denormals, converting them into
+  // a normalised mantissa and an out-of-range exponent. __dnorm2 expects the
+  // exponents at the bottom of their words instead of half way up, so shift
+  // down first.
+  lsr     r4, r4, #16
+  lsr     r5, r5, #16
+  push    {r0, r1, r2, r3, r4, r5} // create a 'struct dnorm2' on the stack
+  mov     r0, sp                   // pass it by address
+  bl      SYMBOL_NAME(__compiler_rt_dnorm2)
+  pop     {r0, r1, r2, r3, r4, r5}
+
+  // Rejoin the main code, with the exponent difference in the top half of r4,
+  // and the output sign in the low bit of r4. (The original setup code did the
+  // latter, but we clobbered it while setting up for __dnorm2.)
+  subs    r4, r4, r5               // exponent difference, at the bottom of r4
+  lsls    r4, r4, #16              // move it up to the right place
+  orr     r4, r4, r6, lsr #31      // recover output sign from top bit of r6
+  b       LOCAL_LABEL(ddiv_normalised)          // rejoin the main code
+
+LOCAL_LABEL(ddiv_xzero):
+  // We come here if x=0. We return 0 (of the right sign) if y is not 0, and
+  // the default quiet NaN if both inputs are zero.
+  orrs    lr, yl, yh, lsl #1       // is y zero?
+  beq     LOCAL_LABEL(ddiv_ivo_pop)             // if so, pop registers and return a NaN
+  // We know xl=0 already, so we only need to reset xh to contain the right
+  // output sign. The setup code left that in the high bit of r6.
+  and     xh, r6, #0x80000000
+  pop     {r4,r5,r6,r7,r8,pc}
+
+LOCAL_LABEL(ddiv_divbyzero):
+  // We come here if y=0, but x is not 0 (or we'd have gone to ddiv_xzero above
+  // instead). So we're dividing a nonzero number by zero, and must return
+  // infinity.
+  pop     {r4,r5,r6,r7,r8,lr}
+  eor     xh, xh, yh               // combine signs to get result sign
+  b       LOCAL_LABEL(ddiv_retinf)
+
+LOCAL_LABEL(ddiv_naninf):
+  // We come here knowing that at least one operand is either NaN or infinity.
+  // If there's a NaN, we can tailcall __dnan2 to do the right thing. Pop our
+  // stacked registers first: we won't need that much spare space any more, and
+  // it makes the tailcall easier if we've already done it.
+  pop     {r4,r5,r6,r7,r8,lr}
+
+  // A number is a NaN if its exponent is 0x7ff and at least one bit below that
+  // is set. The CMP + ADC pair here converts the two words xh:xl into a single
+  // word containing xh shifted up by one (throwing away the sign bit which
+  // makes no difference), with its low bit set if xl was nonzero. So if that
+  // is strictly greater than 0xffe00000, then x was a NaN.
+  cmp     xl, #1
+  adc     r12, xh, xh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+  // Now check y in the same way.
+  cmp     yl, #1
+  adc     r12, yh, yh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+
+  // Now we know there are no NaNs. Therefore there's at least one infinity. If
+  // both operands are infinity then we have inf / inf = invalid operation and
+  // must return a NaN. We detect this by XORing the inputs' exponent fields:
+  // knowing one of them is 7FF, they XOR to zero iff the other one is too.
+  eors    r12, xh, yh              // XOR entire top words of the inputs
+  lsl     r12, r12, #1             // shift left to discard the sign bit
+  lsrs    r12, r12, #21            // shift right again to discard mantissas
+  beq     LOCAL_LABEL(ddiv_ivo)                 // if what's left is 0, we have inf / inf
+
+  // Otherwise, there's exactly one infinity, so our answers are easy, but
+  // depend on which operand it is:
+  //   infinity / anything = infinity
+  //   anything / infinity = 0
+  //
+  // Determine if x is the infinity, by bitwise inverting the whole word and
+  // then shifting left and right to isolate its exponent bits.
+  mvn     r12, xh, lsl #1          // invert x, shift left to discard sign
+  lsrs    r12, r12, #21            //   and shift right to discard mantissa
+  eor     xh, xh, yh               // calculate the output sign bit
+  beq     LOCAL_LABEL(ddiv_retinf)              // if x = inf, return infinity of that sign
+  mov     xl, #0                   // otherwise clear all bits of x
+  and     xh, xh, #0x80000000      //   other than the sign bit
+  bx      lr                       //   and return zero of the same sign
+LOCAL_LABEL(ddiv_retinf):
+  // Construct and return an infinity in xh:xl, with whatever sign bit is
+  // already in the top bit of xh.
+  mov     xl, #0                   // clear low word
+  mvn     xh, xh, lsr #31          // shift xh[31] down to bit 0, inverted
+  mvn     xh, xh, lsl #11          // uninvert, and put exponent 0x7ff below it
+  lsl     xh, xh, #20              // shift back up to the top
+  bx      lr
+
+  // Code to construct and return the default quiet NaN, for the cases inf/inf
+  // and 0/0. We provide two entry labels, one for callers who still need to
+  // pop all the registers this function pushed, and one for callers who have
+  // done that already.
+LOCAL_LABEL(ddiv_ivo_pop):
+  pop     {r4,r5,r6,r7,r8,lr}
+LOCAL_LABEL(ddiv_ivo):
+  movw    xh, 0x7ff8
+  lsls    xh, xh, #16
+  mov     xl, #0
+  bx      lr
+
+  // Table of approximate reciprocals.
+LOCAL_LABEL(reciptbl):
+  .byte 0xFF,0xFD,0xFB,0xF9,0xF7,0xF5,0xF4,0xF2
+  .byte 0xF0,0xEE,0xED,0xEB,0xE9,0xE8,0xE6,0xE4
+  .byte 0xE3,0xE1,0xE0,0xDE,0xDD,0xDB,0xDA,0xD8
+  .byte 0xD7,0xD5,0xD4,0xD3,0xD1,0xD0,0xCF,0xCD
+  .byte 0xCC,0xCB,0xCA,0xC8,0xC7,0xC6,0xC5,0xC4
+  .byte 0xC2,0xC1,0xC0,0xBF,0xBE,0xBD,0xBC,0xBB
+  .byte 0xBA,0xB9,0xB8,0xB7,0xB6,0xB5,0xB4,0xB3
+  .byte 0xB2,0xB1,0xB0,0xAF,0xAE,0xAD,0xAC,0xAB
+  .byte 0xAA,0xA9,0xA8,0xA8,0xA7,0xA6,0xA5,0xA4
+  .byte 0xA3,0xA3,0xA2,0xA1,0xA0,0x9F,0x9F,0x9E
+  .byte 0x9D,0x9C,0x9C,0x9B,0x9A,0x99,0x99,0x98
+  .byte 0x97,0x97,0x96,0x95,0x95,0x94,0x93,0x93
+  .byte 0x92,0x91,0x91,0x90,0x8F,0x8F,0x8E,0x8E
+  .byte 0x8D,0x8C,0x8C,0x8B,0x8B,0x8A,0x89,0x89
+  .byte 0x88,0x88,0x87,0x87,0x86,0x85,0x85,0x84
+  .byte 0x84,0x83,0x83,0x82,0x82,0x81,0x81,0x80
+
+END_COMPILERRT_FUNCTION(__aeabi_ddiv)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/muldf3.S b/compiler-rt/lib/builtins/arm/muldf3.S
new file mode 100644
index 0000000000000..47b04cdb8272e
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/muldf3.S
@@ -0,0 +1,404 @@
+//===-- muldf3.S - double-precision floating point multiplication ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the __muldf3 function (double precision floating point
+// multiplication), with the IEEE-754 default rounding (to nearest, ties to
+// even), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__muldf3)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  VMOV_FROM_DOUBLE(r2, r3, d1)
+  bl __aeabi_dmul
+  VMOV_TO_DOUBLE(d0, r0, r1)
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__muldf3, __aeabi_dmul)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_dmul)
+
+  push    {r4,r5,r6,lr}
+
+  // Check if either input exponent is 000 or 7FF (i.e. not a normalized
+  // number), and if so, branch out of line. If we don't branch out of line,
+  // then we've also extracted the exponents of the input values x and y into
+  // bits 16..26 of r14 and r5 respectively. But if we do, then that hasn't
+  // necessarily been done (because the second AND might have been skipped).
+  ldr     r12, =0x07FF0000
+  ands    r14, r12, xh, lsr #4 // sets Z if exponent of x is 0
+  andsne  r5, r12, yh, lsr #4  // otherwise, sets Z if exponent of y is 0
+  teqne   r14, r12             // otherwise, sets Z if exponent of x is 7FF
+  teqne   r5, r12              // otherwise, sets Z if exponent of y is 7FF
+  beq     LOCAL_LABEL(uncommon)        // branch out of line to handle inf/NaN/0/denorm
+
+  // Calculate the sign of the result, and put it in an unused bit of r14.
+  eor     r4, xh, yh           // XOR the input signs to get the result sign
+  orr     r14, r14, r4, lsr #31 // save it in the low bit of r14
+
+  // Clear the exponent and sign bits from the top word of each mantissa, and
+  // set the leading mantissa bit in each one, so that they're in the right
+  // form to be multiplied.
+  bic     xh, xh, r12, lsl #5     // r12 = 0x07FF0000, so r12 << 5 = 0xFF800000
+  bic     yh, yh, r12, lsl #5
+  orr     xh, xh, #1<<20
+  orr     yh, yh, #1<<20
+
+  // Now we're ready to multiply mantissas. This is also the place we'll come
+  // back to after decoding denormal inputs. The denormal decoding will also
+  // have to set up the same register contents:
+  //  - fractions in xh/xl and yh/yl, with leading bits at bit 20 of xh/yh
+  //  - exponents in r14 and r5, starting at bit 16
+  //  - output sign in r14 bit 0
+LOCAL_LABEL(mul):
+
+  // Multiply the two mantissas as if they were full 64-bit words, delivering a
+  // 128-bit output in four registers. We provide three different ways to do
+  // this, using different instructions.
+  //
+  // Interleaved with the multiplication code, we also compute the output
+  // exponent by adding the input exponents and rebiasing. This takes two
+  // instructions. We schedule each one after a multiplication, to use a delay
+  // slot from the multiplication on CPUs where there is one.
+  //
+  // We add r5 to r14, so that the output exponent is in the top half of r14,
+  // and r5 is freed up to be used in the multiplication.
+  //
+  // We rebias the exponent by subtracting 0x400, which is correct for one of
+  // the two places where the leading bit of the product could end up, and will
+  // need correcting by one in the other case.
+  //
+  // Exit conditions from the three-way #if:
+  //
+  // r4:r5:r6 are the top 96 bits of the 128-bit product, with the leading bit
+  // at either bit 8 or bit 9 of r4. The low bit of r6 is forced to 1 if any of
+  // the low 32 bits of the 128-bit product were set.
+  //
+  // The output sign is still in the low bit of r14; the top half contains the
+  // preliminary output exponent (yet to be adjusted depending on where the
+  // high bit of the product ended up).
+
+#if __ARM_FEATURE_DSP
+  // The UMAAL instruction, which computes a 64-bit product and adds two
+  // separate 32-bit values to it, makes this easy.
+  umull   r6, r4, xh, yl
+  add     r14, r14, r5             // add exponents, freeing up r5
+  umull   r12, r5, xl, yl
+  sub     r14, r14, #0x4000000     // initial rebiasing of exponent
+  umaal   r6, r5, xl, yh
+  umaal   r5, r4, xh, yh
+#elif ARM_FP_DMUL_USE_UMLAL
+  // The UMLAL instruction computes a 64-bit product and adds a 64-bit value to
+  // it. But it doesn't write to the carry flag, so you can't tell if the
+  // addition wrapped. Therefore you have to use it in a way that means the
+  // addition never wraps. Here we do three of the four multiplications (xl*yl,
+  // xl*yh, xh*yh) in a chain, using UMLAL for the top two, in each case with
+  // the 64-bit accumulator consisting of the top half of the previous
+  // multiplication, and a high word set to zero before the UMLAL instruction.
+  //
+  // On Cortex-M3, this is not a win over just using UMULL and doing the
+  // additions by hand, because UMLAL takes two cycles longer than UMULL, and
+  // it also costs a cycle to initialise each of the two high accumulator words
+  // to zero. If the high word of the addend were not zero then those two
+  // cycles would be doing something useful, but as it is, they're wasted time.
+  //
+  // CPUs later than Cortex-M3 - in particular, Cortex-M4 - will do both UMLAL
+  // and UMULL much faster, so that this code is a win over the plain UMULL
+  // code below. But those CPUs typically have UMAAL anyway and will use the
+  // even faster version of the code above. So this code is provided in case
+  // it's useful, but won't be enabled unless you manually #define
+  // ARM_FP_DMUL_USE_UMLAL.
+  umull   r12, r6, xl, yl
+  add     r14, r14, r5             // add exponents, freeing up r5
+  movs    r5, #0
+  umlal   r6, r5, xl, yh
+  movs    r4, #0
+  umlal   r5, r4, xh, yh
+  sub     r14, r14, #0x4000000     // initial rebiasing of exponent
+  umull   xl, yh, xh, yl
+  adds    r6, r6, xl
+  adcs    r5, r5, yh
+  adc     r4, r4, #0
+#else
+  // Simplest approach, using plain UMULL to compute each 64-bit product, and
+  // separate ADD and ADC instructions to do the additions. On Cortex-M3 this
+  // wins over the UMLAL approach: it's one instruction longer, but three
+  // cycles quicker, since each use of UMLAL in the above version costs 2
+  // cycles.
+  umull   r4, r12, xh, yl
+  add     r14, r14, r5             // add exponents, freeing up r5
+  umull   r6, r5, xl, yh
+  sub     r14, r14, #0x4000000     // initial rebiasing of exponent
+  adds    r6, r6, r4
+  adcs    r5, r5, r12              // carry from here is used below
+
+  umull   r4, r12, xh, yh          // r12:r4 is top part
+  adc     yh, r12, #0              // get carry from above addition
+  umull   r12, xh, xl, yl          // xh:r12 is bottom part
+
+  adds    r6, r6, xh
+  adcs    r5, r5, r4
+  adcs    r4, yh, #0
+#endif
+
+  // Now the full 128-bit product of the two mantissas occupies the four
+  // registers r4,r5,r6,r12 (in order from MSW to LSW). Since each input
+  // mantissa was in the range [2^52,2^53), the product is in the range
+  // [2^104,2^106), which means that the lowest-order word r12 is a long way
+  // below the round bit, so that it can only affect cases so close to a
+  // rounding boundary that you need to know if it's nonzero to tell whether
+  // you're rounding to even. Start by freeing up that register, ensuring the
+  // low bit of r6 is set if anything in r12 was nonzero.
+  tst     r12, r12
+  orrne   r6, r6, #1
+
+  // Now we can regard the result as a 96-bit value in r4,r5,r6, with its
+  // leading bit in either bit 8 or 9 of r4. To move that bit up to its final
+  // position in bit 20, we must shift the whole thing left by either 11 or 12
+  // bits. Find out which.
+  tst     r4, #0x200               // is bit 9 set?
+  bne     LOCAL_LABEL(shift11)             // if so, only shift by 11 bits
+
+  // In this branch, we're shifting left by 12 bits. Put the shifted result
+  // back into the output registers xh,xl, and the bits lower than the bottom
+  // mantissa bit into r4.
+  lsls    xh, r4, #12              // shift each input reg left 12
+  lsls    xl, r5, #12
+  lsls    r4, r6, #12
+  orr     xh, xh, r5, lsr #20      // and the top two right by 32-12
+  orr     xl, xl, r6, lsr #20
+
+  b       LOCAL_LABEL(shifted)
+
+LOCAL_LABEL(shift11):
+  // In this branch, we're shifting left by 11 bits instead of 12, and we must
+  // adjust the exponent by 1 to compensate.
+  lsls    xh, r4, #11              // shift each input reg left 11
+  lsls    xl, r5, #11
+  lsls    r4, r6, #11
+  orr     xh, xh, r5, lsr #21      // and the top two right by 32-11
+  orr     xl, xl, r6, lsr #21
+  add     r14, r14, #0x10000       // adjust the exponent
+
+LOCAL_LABEL(shifted):
+  // We've reconverged after shifting the mantissa, so that now the leading 1
+  // bit of the mantissa is in bit 20 of xh, and r4 contains the bits lower
+  // than the bottom of xl.
+
+  // Recombine the sign and exponent into the high bits of xh. If the exponent
+  // is over- or underflowed, this may not give a valid FP result, but because
+  // everything is put on by addition, it will be right "mod 2^64" so that we
+  // can bias the exponent back into range for underflow handling and that will
+  // recover the right sign.
+  //
+  // r14 still has the output sign in its low bit. To extract just the exponent
+  // for adding to xh, we could use BIC to clear that bit, or shift the value
+  // right. We do the latter, which saves a copy of the pre-rounding exponent
+  // in yl, to use later for overflow detection. The shift is ASR, so that if
+  // the exponent is negative due to underflow, it stays negative.
+  asr     yl, r14, #16             // isolate the exponent
+  add     xh, xh, yl, lsl #20      // shift it back up to add to xh
+  add     xh, xh, r14, lsl #31     // then add the sign
+
+  // If we have to handle an underflow, we'll need enough information to
+  // reconstruct the rounding direction. Our strategy is
+  //
+  //  - save the LSW of the output before rounding: if that differs from the
+  //    LSW after rounding then we rounded up
+  //  - save the round word r4: if that is zero then we didn't round at all.
+  //
+  // We're going to branch past the rounding code for a quicker exit in the
+  // case where we're exact. In that case we don't need to save the output LSW
+  // at all, because the zero round word will override whatever it would have
+  // been anyway.
+  movs    r6, r4                   // unconditionally save round word
+  beq     LOCAL_LABEL(rounded)             // branch past rounding code if exact
+  mov     r5, xl                   // and if not, save output LSW too
+
+  // Rounding: we shift r4 left to put the round bit into the carry flag so
+  // that ADCS+ADC will conditionally increment the mantissa. But before we do
+  // the additions, we also check the Z flag, which tells us whether the
+  // remaining 31 bits are all zero. If so, we're either in the round-to-even
+  // (RTE) halfway case, or the exact case - but the exact case never came
+  // through this code at all, so it must be RTE.
+  //
+  // If those 31 bits _aren't_ all zero, we clear the top bit of r4, leaving it
+  // set only in the round-to-even case. Then (r4 >> 31) can be used to clear
+  // the low bit to perform RTE.
+  lsls    r12, r4, #1              // test round word
+  bicne   r4, r4, #0x80000000      // make top bit of r4 into the RTE bit
+  adcs    xl, xl, #0               // conditionally increment the mantissa
+  adc     xh, xh, #0               // ... and carry into its high word
+  bic     xl, xl, r4, lsr #31      // round to even if r4[31] != 0
+
+LOCAL_LABEL(rounded):
+  // Now we've rounded the output. The last thing we must do is check for
+  // overflow and underflow: if neither has happened, we can return.
+  //
+  // yl contains the pre-rounding output exponent minus 1 (so that the leading
+  // mantissa bit incremented it to the right output value). If this is in the
+  // range [0,0x7fd] then the leading bit would have incremented it to
+  // [1,0x7fe], which are non-overflowed output exponents. So an unsigned check
+  // if yl >= 0x7fe detects both overflow and underflow at once.
+  movw    r12, #0x7FE
+  cmp     yl, r12
+  poplo   {r4,r5,r6,pc}
+
+  // We have either an underflow or an overflow. We can tell which it is by
+  // doing a _signed_ comparison of yl with the same value again - and since we
+  // only just did the CMP instruction, we can reuse the same flags.
+  bge     LOCAL_LABEL(overflow)
+
+  // Now we're dealing with an underflow. Set r2 to the rounding direction, by
+  // first checking xl against r5 (where we saved its pre-rounding value) to
+  // see if we rounded up or down, and then overriding that by checking r6
+  // (where we saved the round word) to see if we didn't round at all. In the
+  // latter case the comparison against r5 will deliver nonsense, but then we
+  // overwrite it, so it doesn't matter.
+  cmp     xl, r5                   // did we modify the LSW, i.e. round up?
+  movne   r2, #-1                  // if so, the true value is a bit smaller
+  moveq   r2, #+1                  // else it's a bit bigger
+  cmp     r6, #0                   // except maybe we didn't round at all
+  moveq   r2, #0                   // in which case the true value is exact.
+
+  // Add the IEEE 754 exponent bias, and tail-call __dunder to handle the rest
+  // of the job.
+  add     xh, xh, #0x60000000
+  pop     {r4,r5,r6,lr}
+  b       SYMBOL_NAME(__compiler_rt_dunder)
+
+LOCAL_LABEL(overflow):
+  // Here, we overflowed, so we must return an infinity of the correct sign.
+  // Rebias the exponent, which corrects the sign bit.
+  sub     xh, xh, #0x60000000
+
+  // And pop our scratch registers before falling through into dmul_retinf.
+  pop     {r4,r5,r6,lr}
+
+LOCAL_LABEL(retinf):
+  // This is entered from the overflow handler and also from cases with
+  // infinite inputs. It constructs an infinity, with sign bit equal to the
+  // high bit of xh.
+  //
+  // On entry to here, we expect not to have a stack frame any more, because
+  // one of our callers will have popped it already in order to conditionally
+  // tailcall __dnan2.
+  mov     xl, #0                   // clear low word
+  mvn     xh, xh, lsr #31          // shift xh[31] down to bit 0, inverted
+  mvn     xh, xh, lsl #11          // uninvert, and put exponent 0x7ff below it
+  lsl     xh, xh, #20              // shift back up to the top
+  bx      lr
+
+LOCAL_LABEL(uncommon):
+  // We come here from the entry point, if any input had exponent 0 or 0x7ff.
+  // First we must repeat the instruction from the entry point that sets up r5
+  // with the exponent of y, this time unconditionally, so we know we have both
+  // exponents in the top halves of r14 and r5.
+  and     r5, r12, yh, lsr #4
+
+  // Check if either exponent is 0x7ff, by comparing against the value left in
+  // r12 by the entry point. If so, branch away to handle NaNs and infinities.
+  teq     r14, r12
+  teqne   r5, r12
+  beq     LOCAL_LABEL(naninf)
+
+  // If we didn't branch, we're dealing with finite numbers, including a zero
+  // or a denormal or both.
+  //
+  // First save the output sign.
+  eor     r6, xh, yh
+
+  // Handle zeroes first, because if there's a zero we don't have to worry
+  // about denormals at all.
+  orrs    r4, xl, xh, lsl #1      // is x zero?
+  orrsne  r4, yl, yh, lsl #1      // or is y zero?
+  beq     LOCAL_LABEL(retzero)            // Return zero if so
+
+  // Otherwise, delegate to __dnorm2 to handle denormals, converting them into
+  // a normalised mantissa and an out-of-range exponent. __dnorm2 expects the
+  // exponents at the bottom of their words instead of half way up, so shift
+  // down first, and back up again afterwards.
+  //
+  // This call clobbers r12, because we didn't bother to save it on the stack.
+  // That's fine, because we don't need the constant in it any more. When we go
+  // back to dmul_mul, that will use it as a scratch register.
+  lsr     r4, r14, #16
+  lsr     r5, r5, #16
+  push    {r0, r1, r2, r3, r4, r5} // create a 'struct dnorm2' on the stack
+  mov     r0, sp                   // pass it by address
+  bl      SYMBOL_NAME(__compiler_rt_dnorm2)
+  pop     {r0, r1, r2, r3, r4, r5}
+  lsl     r14, r4, #16
+  lsls    r5, r5, #16
+
+  // Put the output sign at the bottom of r14, the same place the fast path
+  // would have left it. Then rejoin the fast path.
+  orr     r14, r14, r6, lsr #31
+  b       LOCAL_LABEL(mul)
+
+LOCAL_LABEL(retzero):
+  // Return an exact zero, with sign bit from the high bit of r6.
+  mov     xl, #0                  // low word is 0
+  ands    xh, r6, #0x80000000     // high word is 0 except for the sign
+  pop     {r4,r5,r6,pc}
+
+LOCAL_LABEL(naninf):
+  // We come here knowing that at least one operand is either NaN or infinity.
+  // If there's a NaN, we can tailcall __dnan2 to do the right thing. Pop our
+  // stacked registers first: we won't need that much spare space any more, and
+  // it makes the tailcall easier if we've already done it.
+  pop     {r4,r5,r6,lr}
+
+  // A number is a NaN if its exponent is 0x7ff and at least one bit below that
+  // is set. The CMP + ADC pair here converts the two words xh:xl into a single
+  // word containing xh shifted up by one (throwing away the sign bit which
+  // makes no difference), with its low bit set if xl was nonzero. So if that
+  // is strictly greater than 0xffe00000, then x was a NaN.
+  cmp     xl, #1
+  adc     r12, xh, xh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+  // Now check y in the same way.
+  cmp     yl, #1
+  adc     r12, yh, yh
+  cmp     r12, #0xFFE00000
+  bhi     SYMBOL_NAME(__compiler_rt_dnan2)
+
+  // Now we know there are no NaNs. Therefore there's at least one infinity. If
+  // either operand is zero then we have inf * 0 = invalid operation and must
+  // return a NaN.
+  orrs    r12, xl, xh, lsl #1     // are all bits of x zero except the sign?
+  beq     LOCAL_LABEL(retnan)             // if so, x == 0, so y == inf
+  orrs    r12, yl, yh, lsl #1     // same check the other way round
+  beq     LOCAL_LABEL(retnan)
+
+  // If we have an infinity and no NaN, then we just return an infinity of the
+  // correct sign.
+  eor     xh, xh, yh
+  b       LOCAL_LABEL(retinf)
+
+LOCAL_LABEL(retnan):
+  // Return the default NaN, in the case where the inputs were 0 and infinity.
+  movw    xh, 0x7ff8
+  lsls    xh, xh, #16
+  mov     xl, #0
+  bx      lr
+
+END_COMPILERRT_FUNCTION(__aeabi_dmul)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/test/builtins/Unit/divdf3new_test.c b/compiler-rt/test/builtins/Unit/divdf3new_test.c
new file mode 100644
index 0000000000000..b756acf2dfeb0
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/divdf3new_test.c
@@ -0,0 +1,471 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_divdf3
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test uses compareResultD to check the returned floats, which
+// accepts any returned NaN if the expected result is the canonical NaN value
+// 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
+// to a more detailed handling of NaNs, we tighten up the check and include
+// some extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#  define EXPECT_EXACT_RESULTS
+#  define ARM_NAN_HANDLING
+#endif
+
+// Returns: a / b
+COMPILER_RT_ABI double __divdf3(double a, double b);
+
+int test__divdf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+  double a = fromRep64(a_rep), b = fromRep64(b_rep);
+  double x = __divdf3(a, b);
+#ifdef EXPECT_EXACT_RESULTS
+  int ret = toRep64(x) != expected_rep;
+#else
+  int ret = compareResultD(x, expected_rep);
+#endif
+
+  if (ret) {
+    printf("error at line %d: __divdf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
+           ", expected %016" PRIx64 "\n",
+           line, a_rep, b_rep, toRep64(x), expected_rep);
+  }
+  return ret;
+}
+
+#define test__divdf3(a,b,x) test__divdf3(__LINE__,a,b,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__divdf3(0x0000000000000000, 0x0000000000000001, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x000fffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x001fffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x3ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x4014000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x7fdfffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x7fe0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x8000000000000002, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x800fffffffffffff, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x8010000000000001, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x8020000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0xc008000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0xc01c000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0xffcfffffffffffff, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0xffe0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000001, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x0000000000000001, 0x3fc0000000000000, 0x0000000000000008);
+  status |= test__divdf3(0x0000000000000001, 0x3fe0000000000000, 0x0000000000000002);
+  status |= test__divdf3(0x0000000000000001, 0x4000000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000001, 0x7fefffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000001, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0000000000000001, 0xc000000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000001, 0xffefffffffffffff, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000002, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x0000000000000002, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0000000000000009, 0x4022000000000000, 0x0000000000000001);
+  status |= test__divdf3(0x0000000000000009, 0xc022000000000000, 0x8000000000000001);
+  status |= test__divdf3(0x000ffffffffffff7, 0x3feffffffffffffe, 0x000ffffffffffff8);
+  status |= test__divdf3(0x000ffffffffffffe, 0x3feffffffffffffe, 0x000fffffffffffff);
+  status |= test__divdf3(0x000fffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x000fffffffffffff, 0x3f60000000000000, 0x009ffffffffffffe);
+  status |= test__divdf3(0x000fffffffffffff, 0x3fe0000000000000, 0x001ffffffffffffe);
+  status |= test__divdf3(0x000fffffffffffff, 0x3ff0000000000000, 0x000fffffffffffff);
+  status |= test__divdf3(0x000fffffffffffff, 0x3ff0000000000002, 0x000ffffffffffffd);
+  status |= test__divdf3(0x000fffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x000fffffffffffff, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x000fffffffffffff, 0xbff0000000000000, 0x800fffffffffffff);
+  status |= test__divdf3(0x000fffffffffffff, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0010000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x0010000000000000, 0x3ff0000000000001, 0x000fffffffffffff);
+  status |= test__divdf3(0x0010000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0010000000000001, 0x3ff0000000000002, 0x000fffffffffffff);
+  status |= test__divdf3(0x0010000000000001, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x0010000000000001, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0010000000000002, 0x3ff0000000000006, 0x000ffffffffffffc);
+  status |= test__divdf3(0x001ffffffffffffe, 0x4000000000000000, 0x000fffffffffffff);
+  status |= test__divdf3(0x001fffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x001fffffffffffff, 0x4000000000000000, 0x0010000000000000);
+  status |= test__divdf3(0x001fffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x0020000000000000, 0x0010000000000000, 0x4000000000000000);
+  status |= test__divdf3(0x0020000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x0020000000000000, 0xc000000000000000, 0x8010000000000000);
+  status |= test__divdf3(0x0020000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x0020000000000001, 0x0010000000000001, 0x4000000000000000);
+  status |= test__divdf3(0x0020000000000001, 0xc000000000000000, 0x8010000000000001);
+  status |= test__divdf3(0x0020000000000003, 0x8010000000000003, 0xc000000000000000);
+  status |= test__divdf3(0x0020000000000003, 0xc000000000000000, 0x8010000000000003);
+  status |= test__divdf3(0x3feffffffffffff7, 0x3feffffffffffffb, 0x3feffffffffffffc);
+  status |= test__divdf3(0x3feffffffffffff7, 0x3feffffffffffffe, 0x3feffffffffffff9);
+  status |= test__divdf3(0x3feffffffffffff8, 0x3feffffffffffffc, 0x3feffffffffffffc);
+  status |= test__divdf3(0x3feffffffffffff8, 0x3feffffffffffffd, 0x3feffffffffffffb);
+  status |= test__divdf3(0x3feffffffffffffa, 0x3feffffffffffff9, 0x3ff0000000000001);
+  status |= test__divdf3(0x3feffffffffffffb, 0x3feffffffffffff9, 0x3ff0000000000001);
+  status |= test__divdf3(0x3feffffffffffffc, 0x3feffffffffffff9, 0x3ff0000000000002);
+  status |= test__divdf3(0x3feffffffffffffc, 0x3feffffffffffffd, 0x3fefffffffffffff);
+  status |= test__divdf3(0x3feffffffffffffc, 0x3feffffffffffffe, 0x3feffffffffffffe);
+  status |= test__divdf3(0x3feffffffffffffc, 0x3fefffffffffffff, 0x3feffffffffffffd);
+  status |= test__divdf3(0x3feffffffffffffc, 0x3ff0000000000001, 0x3feffffffffffffa);
+  status |= test__divdf3(0x3feffffffffffffd, 0x3feffffffffffff9, 0x3ff0000000000002);
+  status |= test__divdf3(0x3feffffffffffffd, 0x3feffffffffffffc, 0x3ff0000000000001);
+  status |= test__divdf3(0x3feffffffffffffd, 0x3feffffffffffffe, 0x3fefffffffffffff);
+  status |= test__divdf3(0x3feffffffffffffd, 0x3fefffffffffffff, 0x3feffffffffffffe);
+  status |= test__divdf3(0x3feffffffffffffd, 0x3ff0000000000001, 0x3feffffffffffffb);
+  status |= test__divdf3(0x3feffffffffffffd, 0x3ff0000000000002, 0x3feffffffffffff9);
+  status |= test__divdf3(0x3feffffffffffffe, 0x3feffffffffffff9, 0x3ff0000000000003);
+  status |= test__divdf3(0x3feffffffffffffe, 0x3feffffffffffffc, 0x3ff0000000000001);
+  status |= test__divdf3(0x3feffffffffffffe, 0x3feffffffffffffd, 0x3ff0000000000001);
+  status |= test__divdf3(0x3feffffffffffffe, 0x3fefffffffffffff, 0x3fefffffffffffff);
+  status |= test__divdf3(0x3feffffffffffffe, 0x3ff0000000000001, 0x3feffffffffffffc);
+  status |= test__divdf3(0x3feffffffffffffe, 0x3ff0000000000002, 0x3feffffffffffffa);
+  status |= test__divdf3(0x3feffffffffffffe, 0x3ff0000000000003, 0x3feffffffffffff8);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffff9, 0x3ff0000000000003);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffc, 0x3ff0000000000002);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffd, 0x3ff0000000000001);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffe, 0x3ff0000000000001);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000001, 0x3feffffffffffffd);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000002, 0x3feffffffffffffb);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000003, 0x3feffffffffffff9);
+  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000004, 0x3feffffffffffff7);
+  status |= test__divdf3(0x3ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffff7, 0x3ff0000000000005);
+  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffff8, 0x3ff0000000000004);
+  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffb, 0x3ff0000000000003);
+  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffc, 0x3ff0000000000002);
+  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffd, 0x3ff0000000000002);
+  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffe, 0x3ff0000000000001);
+  status |= test__divdf3(0x3ff0000000000000, 0x3fefffffffffffff, 0x3ff0000000000001);
+  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000001, 0x3feffffffffffffe);
+  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000002, 0x3feffffffffffffc);
+  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000003, 0x3feffffffffffffa);
+  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000004, 0x3feffffffffffff8);
+  status |= test__divdf3(0x3ff0000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x3ff0000000000001, 0x3feffffffffffffb, 0x3ff0000000000004);
+  status |= test__divdf3(0x3ff0000000000001, 0x3feffffffffffffd, 0x3ff0000000000003);
+  status |= test__divdf3(0x3ff0000000000001, 0x3feffffffffffffe, 0x3ff0000000000002);
+  status |= test__divdf3(0x3ff0000000000001, 0x3fefffffffffffff, 0x3ff0000000000002);
+  status |= test__divdf3(0x3ff0000000000001, 0x3ff0000000000002, 0x3feffffffffffffe);
+  status |= test__divdf3(0x3ff0000000000001, 0x3ff0000000000003, 0x3feffffffffffffc);
+  status |= test__divdf3(0x3ff0000000000002, 0x3feffffffffffffc, 0x3ff0000000000004);
+  status |= test__divdf3(0x3ff0000000000002, 0x3feffffffffffffd, 0x3ff0000000000004);
+  status |= test__divdf3(0x3ff0000000000002, 0x3feffffffffffffe, 0x3ff0000000000003);
+  status |= test__divdf3(0x3ff0000000000002, 0x3fefffffffffffff, 0x3ff0000000000003);
+  status |= test__divdf3(0x3ff0000000000002, 0x3ff0000000000001, 0x3ff0000000000001);
+  status |= test__divdf3(0x3ff0000000000002, 0x3ff0000000000003, 0x3feffffffffffffe);
+  status |= test__divdf3(0x3ff0000000000003, 0x3feffffffffffffd, 0x3ff0000000000005);
+  status |= test__divdf3(0x3ff0000000000003, 0x3feffffffffffffe, 0x3ff0000000000004);
+  status |= test__divdf3(0x3ff0000000000003, 0x3fefffffffffffff, 0x3ff0000000000004);
+  status |= test__divdf3(0x3ff0000000000003, 0x3ff0000000000001, 0x3ff0000000000002);
+  status |= test__divdf3(0x3ff0000000000004, 0x3feffffffffffffe, 0x3ff0000000000005);
+  status |= test__divdf3(0x3ff0000000000004, 0x3ff0000000000001, 0x3ff0000000000003);
+  status |= test__divdf3(0x3ff0000000000004, 0x3ff0000000000007, 0x3feffffffffffffa);
+  status |= test__divdf3(0x3ff0000000000005, 0x3fefffffffffffff, 0x3ff0000000000006);
+  status |= test__divdf3(0x3ff0000000000006, 0x3ff0000000000008, 0x3feffffffffffffc);
+  status |= test__divdf3(0x3ff0000000000007, 0x3ff0000000000002, 0x3ff0000000000005);
+  status |= test__divdf3(0x3ff0000000000009, 0x3ff0000000000008, 0x3ff0000000000001);
+  status |= test__divdf3(0x3ff199999999999a, 0x3ff3333333333333, 0x3fed555555555556);
+  status |= test__divdf3(0x4000000000000000, 0x3ff0000000000000, 0x4000000000000000);
+  status |= test__divdf3(0x4000000000000000, 0xbff0000000000000, 0xc000000000000000);
+  status |= test__divdf3(0x4008000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x4008000000000000, 0xc008000000000000, 0xbff0000000000000);
+  status |= test__divdf3(0x4008000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x4014000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x4014000000000000, 0x4014000000000000, 0x3ff0000000000000);
+  status |= test__divdf3(0x4014000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x401c000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x401c000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x4020000000000000, 0x4000000000000000, 0x4010000000000000);
+  status |= test__divdf3(0x4022000000000000, 0x4008000000000000, 0x4008000000000000);
+  status |= test__divdf3(0x7f60000000000000, 0x00a0000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7fcfffffffffffff, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7fdffffffffffffd, 0xc000000000000000, 0xffcffffffffffffd);
+  status |= test__divdf3(0x7fdfffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7fdfffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0x3fe0000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0x4000000000000000, 0x7fd0000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0xbfe0000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0xc000000000000000, 0xffd0000000000000);
+  status |= test__divdf3(0x7fe0000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x7fe0000000000003, 0xffd0000000000003, 0xc000000000000000);
+  status |= test__divdf3(0x7feffffffffffffd, 0x4010000000000000, 0x7fcffffffffffffd);
+  status |= test__divdf3(0x7feffffffffffffd, 0xc010000000000000, 0xffcffffffffffffd);
+  status |= test__divdf3(0x7fefffffffffffff, 0x0000000000000001, 0x7ff0000000000000);
+  status |= test__divdf3(0x7fefffffffffffff, 0x3fefffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0x7fefffffffffffff, 0x7fcfffffffffffff, 0x4010000000000000);
+  status |= test__divdf3(0x7fefffffffffffff, 0x7fdfffffffffffff, 0x4000000000000000);
+  status |= test__divdf3(0x7fefffffffffffff, 0xc000000000000000, 0xffdfffffffffffff);
+  status |= test__divdf3(0x7fefffffffffffff, 0xffcfffffffffffff, 0xc010000000000000);
+  status |= test__divdf3(0x7fefffffffffffff, 0xfff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x0000000000000001, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x0010000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x001fffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x4014000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x7fdfffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x8000000000000002, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x8010000000000001, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x8020000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0xc008000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0xc01c000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0xffcfffffffffffff, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0xffefffffffffffff, 0xfff0000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x0000000000000003, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x000fffffffffffff, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x0010000000000001, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x0020000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x4000000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x4018000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x7fcfffffffffffff, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x7fd0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x8000000000000004, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x800fffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x801fffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0xc010000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0xc020000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0xffd0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0xffdfffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000001, 0x3fe0000000000000, 0x8000000000000002);
+  status |= test__divdf3(0x8000000000000001, 0x4000000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000001, 0x7fefffffffffffff, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000001, 0xc000000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000001, 0xffefffffffffffff, 0x0000000000000000);
+  status |= test__divdf3(0x8000000000000003, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x8000000000000003, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8000000000000004, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x8000000000000004, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x800ffffffffffff8, 0x3feffffffffffffe, 0x800ffffffffffff9);
+  status |= test__divdf3(0x800fffffffffffff, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x800fffffffffffff, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x800fffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x800fffffffffffff, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8010000000000000, 0x3ff0000000000001, 0x800fffffffffffff);
+  status |= test__divdf3(0x8010000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x8010000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8010000000000001, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x8010000000000001, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x801fffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0x801fffffffffffff, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0x8020000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0x8020000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0x8020000000000001, 0x0010000000000001, 0xc000000000000000);
+  status |= test__divdf3(0x8020000000000005, 0x0010000000000005, 0xc000000000000000);
+  status |= test__divdf3(0xbff0000000000000, 0x3ff0000000000000, 0xbff0000000000000);
+  status |= test__divdf3(0xbff0000000000000, 0xbff0000000000000, 0x3ff0000000000000);
+  status |= test__divdf3(0xc000000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xc000000000000000, 0x3ff0000000000000, 0xc000000000000000);
+  status |= test__divdf3(0xc000000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0xc000000000000000, 0xbff0000000000000, 0x4000000000000000);
+  status |= test__divdf3(0xc010000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xc010000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0xc018000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xc018000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0xc018000000000000, 0xc008000000000000, 0x4000000000000000);
+  status |= test__divdf3(0xc01c000000000000, 0x401c000000000000, 0xbff0000000000000);
+  status |= test__divdf3(0xc020000000000000, 0x4000000000000000, 0xc010000000000000);
+  status |= test__divdf3(0xc020000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xc020000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0xc022000000000000, 0xc008000000000000, 0x4008000000000000);
+  status |= test__divdf3(0xffcfffffffffffff, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xffcfffffffffffff, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0xffd0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xffd0000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |= test__divdf3(0xffd0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xffd0000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0xffdfffffffffffff, 0x4000000000000000, 0xffcfffffffffffff);
+  status |= test__divdf3(0xffdfffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xffe0000000000000, 0x3fe0000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xffe0000000000000, 0xbfe0000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xffe0000000000001, 0x7fd0000000000001, 0xc000000000000000);
+  status |= test__divdf3(0xffeffffffffffffd, 0x4010000000000000, 0xffcffffffffffffd);
+  status |= test__divdf3(0xffeffffffffffffd, 0xc010000000000000, 0x7fcffffffffffffd);
+  status |= test__divdf3(0xffefffffffffffff, 0x7fcfffffffffffff, 0xc010000000000000);
+  status |= test__divdf3(0xffefffffffffffff, 0xffcfffffffffffff, 0x4010000000000000);
+  status |= test__divdf3(0xffefffffffffffff, 0xfff0000000000000, 0x0000000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x0000000000000003, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x0010000000000001, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x0020000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x4000000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x4018000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x7fd0000000000000, 0xfff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x8000000000000004, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x8010000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x801fffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0xc010000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0xc020000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0xffd0000000000000, 0x7ff0000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0xffefffffffffffff, 0x7ff0000000000000);
+  status |= test__divdf3(0x800ffffffdffffff, 0xc00fff8000000000, 0x0004000fffbfff00);
+  status |= test__divdf3(0xb7fbffffffffffff, 0xffe0000000000007, 0x0000000000000000);
+  status |= test__divdf3(0x3ff660beb3029ffd, 0x3ff52e22fb7ace43, 0x3ff0e79e59ccb735);
+  status |= test__divdf3(0x3ff73ddbc621eb00, 0x3ffb8224c030d747, 0x3feb095d4073d13b);
+  status |= test__divdf3(0x3ff9a3b1ff2bf973, 0x3ff42fdf35d2d3bd, 0x3ff452508f203fca);
+  status |= test__divdf3(0x3ffa2f42f2a01655, 0x3ff01310ba9f33d1, 0x3ffa103474220298);
+  status |= test__divdf3(0x3ffa6b3e65d68478, 0x3ff773ca580800a9, 0x3ff206204bf651cc);
+  status |= test__divdf3(0x3ffae840ed05aaad, 0x3ff374c8afa6bd73, 0x3ff620a0b38357dd);
+  status |= test__divdf3(0x3ffc9bff90e124f7, 0x3ff19678d03f31b9, 0x3ffa06ce5731c244);
+  status |= test__divdf3(0x3ff716518068f63e, 0x3ffea080001fffff, 0x3fe81f4927e2f813);
+  status |= test__divdf3(0x3ff30b70c9e177b3, 0x3ffdc1dbcddeaaf7, 0x3fe47ae453d79b63);
+  status |= test__divdf3(0x3ff690a0c1cf289e, 0x3ffdd0e4ec596ead, 0x3fe837c35c721292);
+  status |= test__divdf3(0x3ff9a9f18698d1c5, 0x3ffdcf214b672807, 0x3feb8cd196d1e2db);
+  status |= test__divdf3(0x3ffc412def95e9f2, 0x3ffe09fd73e44afb, 0x3fee195e4c411819);
+  status |= test__divdf3(0x3ffab674f26df917, 0x3ffe55a80dfd623d, 0x3fec2de561fb628a);
+  status |= test__divdf3(0x3ff15bb10851a33b, 0x3ffe770229894d4f, 0x3fe23b9bdf3ad4d7);
+  status |= test__divdf3(0x3ff6ce035de00c24, 0x3fff04076d288c95, 0x3fe7874738e5ef5e);
+  status |= test__divdf3(0x3ffb0e73f83fd2b4, 0x3fff01150ca4f6e3, 0x3febece97e64ff65);
+  status |= test__divdf3(0x3ff53fff6c6d7043, 0x3fffb55c0bf15be1, 0x3fe57204f8441410);
+  status |= test__divdf3(0x3ffa8aa3bbff7c4b, 0x3fffd530fa74cc5f, 0x3feaae55281a47cf);
+  status |= test__divdf3(0x3ff3004b0d901379, 0x3ffe470662686931, 0x3fe41508eef9d818);
+  status |= test__divdf3(0x3ffac10f29e80b25, 0x3ffe2fba9d423c9d, 0x3fec5c8a8148eb26);
+  status |= test__divdf3(0x3ff8a3e14fe0651f, 0x3ffdeeae50e07679, 0x3fea579ce7a3f61c);
+  status |= test__divdf3(0x3ff168321760dd0d, 0x3ffd382a2b3c2c27, 0x3fe31042c5fcbe35);
+  status |= test__divdf3(0x3ff208350f930e99, 0x3ffc80beeab6d9ed, 0x3fe43e9486314a0e);
+  status |= test__divdf3(0x3ff46a9470b46af6, 0x3ffc2e13c9335b3f, 0x3fe72f150e86f5a1);
+  status |= test__divdf3(0x3ffaf26f45d21562, 0x3ffbe6d631b290e7, 0x3feee7b30b353e95);
+  status |= test__divdf3(0x3ff5cda6f52381df, 0x3ffbe2a5bce4483f, 0x3fe90542a0e62c21);
+  status |= test__divdf3(0x3ff92aeb8209bb69, 0x3ffb57a0bdf7af6f, 0x3fed74754022b839);
+  status |= test__divdf3(0x3ff627c9c1a1903d, 0x3ffb3c161457a7e1, 0x3fea082feee891f0);
+  status |= test__divdf3(0x3ffa5fef91208fd5, 0x3ff68928392cf5e7, 0x3ff2b9c16cd0a6eb);
+  status |= test__divdf3(0x3ffdc6825d6a2ad2, 0x3ff69bb9ca89cd3f, 0x3ff5127c1399515f);
+  status |= test__divdf3(0x3ffd62dbb1150699, 0x3ff6e12d3daf7823, 0x3ff48cd52e787bc5);
+  status |= test__divdf3(0x3ffb9f0e3f946dd2, 0x3ff75a51f01f688b, 0x3ff2ecadebdfdf91);
+  status |= test__divdf3(0x3ffdf21fc13ef609, 0x3ff77a80c8098ae1, 0x3ff46843217c9c90);
+  status |= test__divdf3(0x3ff83f6d28924d31, 0x3ff7cb607bcc758f, 0x3ff04e08e26c84b7);
+  status |= test__divdf3(0x3ffef8774307cea5, 0x3ff849124d13461d, 0x3ff467851369d61a);
+  status |= test__divdf3(0x3ffd7c2259068fa2, 0x3ffa9e9faf8d6845, 0x3ff1b8e24ddeb546);
+  status |= test__divdf3(0x3fffb10b35d3977b, 0x3ffb57a0bdf7af6f, 0x3ff28b8abfdd47c7);
+  status |= test__divdf3(0x3ffdcfa4097387f1, 0x3ffbe6d631b290e7, 0x3ff1184cf4cac16b);
+  status |= test__divdf3(0x3ffcb6231a615d02, 0x3ffb98faef6f9417, 0x3ff0a552a67a8e2d);
+  status |= test__divdf3(0x3ffba5443a5d0a42, 0x3ffb3a5c10922a9d, 0x3ff03ed2622d2a26);
+  status |= test__divdf3(0x3fff3144ae86b33e, 0x3ffa58948417f235, 0x3ff2f17912d557f2);
+  status |= test__divdf3(0x3ffd68635bf6605a, 0x3ff945fce3a79f3f, 0x3ff29e0c7d6617a1);
+  status |= test__divdf3(0x3ff97e6030354676, 0x3ff906f78f460697, 0x3ff04c56a5f3136d);
+  status |= test__divdf3(0x3ffe86f743594e95, 0x3ff8444d7946422d, 0x3ff420b1e63f512e);
+  status |= test__divdf3(0x3fff12a6c5539a9a, 0x3ff7cad48079af09, 0x3ff4e564f736b864);
+  status |= test__divdf3(0x3ffa5371fe989251, 0x3ff6fc5272dc36d1, 0x3ff2533d7a4d0ee8);
+  status |= test__divdf3(0x3ffe18c0547f65d2, 0x3ff6fc9e8dd915ed, 0x3ff4f2e7f917b80e);
+  status |= test__divdf3(0x3ffd7aea8a297055, 0x3ff64eb95d608cd9, 0x3ff52500dc28664c);
+
+  // Test that the result of an operation is a NaN at all when it should be.
+  //
+  // In most configurations these tests' results are checked compared using
+  // compareResultD, so we set all the answers to the canonical NaN
+  // 0x7ff8000000000000, which causes compareResultF to accept any NaN
+  // encoding. We also use the same value as the input NaN in tests that have
+  // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
+  // because 0x7ff8000000000000 is still the exact expected NaN.
+  status |= test__divdf3(0x0000000000000000, 0x0000000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x0000000000000000, 0x8000000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x0000000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x8000000000000000, 0x8000000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |= test__divdf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+
+#ifdef ARM_NAN_HANDLING
+  // Tests specific to the NaN handling of Arm hardware, mimicked by
+  // arm/divdf3.S:
+  //
+  //  - a quiet NaN is distinguished by the top mantissa bit being 1
+  //
+  //  - if a signalling NaN appears in the input, the output quiet NaN is
+  //    obtained by setting its top mantissa bit and leaving everything else
+  //    unchanged
+  //
+  //  - if both operands are signalling NaNs then the output NaN is derived
+  //    from the first operand
+  //
+  //  - if both operands are quiet NaNs then the output NaN is the first
+  //    operand
+  //
+  //  - invalid operations not involving an input NaN return the quiet
+  //    NaN with fewest bits set, 0x7ff8000000000000.
+  status |= test__divdf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |= test__divdf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |= test__divdf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |= test__divdf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |= test__divdf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |= test__divdf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |= test__divdf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |= test__divdf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |= test__divdf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |= test__divdf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |= test__divdf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |= test__divdf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |= test__divdf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |= test__divdf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |= test__divdf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |= test__divdf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |= test__divdf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |= test__divdf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |= test__divdf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |= test__divdf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |= test__divdf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |= test__divdf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |= test__divdf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |= test__divdf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |= test__divdf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |= test__divdf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |= test__divdf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |= test__divdf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |= test__divdf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |= test__divdf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |= test__divdf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |= test__divdf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |= test__divdf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |= test__divdf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |= test__divdf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |= test__divdf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |= test__divdf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |= test__divdf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |= test__divdf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |= test__divdf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |= test__divdf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |= test__divdf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |= test__divdf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |= test__divdf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |= test__divdf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |= test__divdf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |= test__divdf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |= test__divdf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |= test__divdf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |= test__divdf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |= test__divdf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |= test__divdf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+
+#endif // ARM_NAN_HANDLING
+
+  return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/muldf3new_test.c b/compiler-rt/test/builtins/Unit/muldf3new_test.c
new file mode 100644
index 0000000000000..809f40a95b95a
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/muldf3new_test.c
@@ -0,0 +1,456 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_muldf3
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test uses compareResultD to check the returned floats, which
+// accepts any returned NaN if the expected result is the canonical NaN value
+// 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
+// to a more detailed handling of NaNs, we tighten up the check and include
+// some extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#  define EXPECT_EXACT_RESULTS
+#  define ARM_NAN_HANDLING
+#endif
+
+// Returns: a * b
+COMPILER_RT_ABI double __muldf3(double a, double b);
+
+int test__muldf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+  double a = fromRep64(a_rep), b = fromRep64(b_rep);
+  double x = __muldf3(a, b);
+#ifdef EXPECT_EXACT_RESULTS
+  int ret = toRep64(x) != expected_rep;
+#else
+  int ret = compareResultD(x, expected_rep);
+#endif
+
+  if (ret) {
+    printf("error at line %d: __muldf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
+           ", expected %016" PRIx64 "\n",
+           line, a_rep, b_rep, toRep64(x), expected_rep);
+  }
+  return ret;
+}
+
+#define test__muldf3(a,b,x) test__muldf3(__LINE__,a,b,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__muldf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x000fffffffffffff, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x001fffffffffffff, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x3ff0000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x7fdfffffffffffff, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x8000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x8000000000000002, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x800fffffffffffff, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x8010000000000001, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0x8020000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0xc008000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0xffcfffffffffffff, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0xffe0000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000000, 0xffefffffffffffff, 0x8000000000000000);
+  status |= test__muldf3(0x0000000000000001, 0x0000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000001, 0x3fe0000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x0000000000000001, 0x3fefffffffffffff, 0x0000000000000001);
+  status |= test__muldf3(0x0000000000000001, 0x3ff0000000000000, 0x0000000000000001);
+  status |= test__muldf3(0x0000000000000001, 0x4000000000000000, 0x0000000000000002);
+  status |= test__muldf3(0x0000000000000001, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x0000000000000001, 0xbfefffffffffffff, 0x8000000000000001);
+  status |= test__muldf3(0x0000000000000006, 0x3fe0000000000000, 0x0000000000000003);
+  status |= test__muldf3(0x0000000000000006, 0xbfe0000000000000, 0x8000000000000003);
+  status |= test__muldf3(0x0000000000000008, 0x3fc0000000000000, 0x0000000000000001);
+  status |= test__muldf3(0x000ffffffffffff7, 0x8020000000000003, 0x8000000000000000);
+  status |= test__muldf3(0x000ffffffffffff8, 0x3ff0000000000001, 0x000ffffffffffff9);
+  status |= test__muldf3(0x000ffffffffffff8, 0x3ff0000000000008, 0x0010000000000000);
+  status |= test__muldf3(0x000ffffffffffff8, 0xbff0000000000001, 0x800ffffffffffff9);
+  status |= test__muldf3(0x000ffffffffffff8, 0xbff0000000000008, 0x8010000000000000);
+  status |= test__muldf3(0x000ffffffffffffc, 0x4000000000000000, 0x001ffffffffffff8);
+  status |= test__muldf3(0x000ffffffffffffe, 0x3feffffffffffffc, 0x000ffffffffffffc);
+  status |= test__muldf3(0x000ffffffffffffe, 0x3ff0000000000001, 0x000fffffffffffff);
+  status |= test__muldf3(0x000ffffffffffffe, 0xbff0000000000001, 0x800fffffffffffff);
+  status |= test__muldf3(0x000fffffffffffff, 0x000ffffffffffffe, 0x0000000000000000);
+  status |= test__muldf3(0x000fffffffffffff, 0x3cb0000000000001, 0x0000000000000001);
+  status |= test__muldf3(0x000fffffffffffff, 0x3fe0000000000001, 0x0008000000000000);
+  status |= test__muldf3(0x000fffffffffffff, 0x3ff0000000000001, 0x0010000000000000);
+  status |= test__muldf3(0x000fffffffffffff, 0x4000000000000000, 0x001ffffffffffffe);
+  status |= test__muldf3(0x0010000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x0010000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x0010000000000000, 0x3feffffffffffffe, 0x000fffffffffffff);
+  status |= test__muldf3(0x0010000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x0010000000000000, 0x8010000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x0010000000000000, 0xc000000000000000, 0x8020000000000000);
+  status |= test__muldf3(0x0010000000000001, 0x3feffffffffffffa, 0x000ffffffffffffe);
+  status |= test__muldf3(0x0010000000000001, 0x3feffffffffffffe, 0x0010000000000000);
+  status |= test__muldf3(0x0010000000000001, 0xc000000000000000, 0x8020000000000001);
+  status |= test__muldf3(0x0010000000000002, 0x3feffffffffffffc, 0x0010000000000000);
+  status |= test__muldf3(0x001ffffffffffff8, 0x3fe0000000000000, 0x000ffffffffffffc);
+  status |= test__muldf3(0x001ffffffffffffe, 0x3fe0000000000000, 0x000fffffffffffff);
+  status |= test__muldf3(0x001ffffffffffffe, 0xbfe0000000000000, 0x800fffffffffffff);
+  status |= test__muldf3(0x001fffffffffffff, 0x3fe0000000000000, 0x0010000000000000);
+  status |= test__muldf3(0x001fffffffffffff, 0xbfe0000000000000, 0x8010000000000000);
+  status |= test__muldf3(0x3fe0000000000000, 0x8000000000000001, 0x8000000000000000);
+  status |= test__muldf3(0x3ff0000000000000, 0x000ffffffffffffd, 0x000ffffffffffffd);
+  status |= test__muldf3(0x3ff0000000000000, 0x0020000000000003, 0x0020000000000003);
+  status |= test__muldf3(0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |= test__muldf3(0x3ff0000000000000, 0x4000000000000000, 0x4000000000000000);
+  status |= test__muldf3(0x3ff0000000000000, 0x8000000000000001, 0x8000000000000001);
+  status |= test__muldf3(0x3ff0000000000000, 0x8000000000000009, 0x8000000000000009);
+  status |= test__muldf3(0x3ff0000000000001, 0x3ff0000000000001, 0x3ff0000000000002);
+  status |= test__muldf3(0x3ff0000000000001, 0xbff0000000000001, 0xbff0000000000002);
+  status |= test__muldf3(0x3ff0000000000001, 0xbff0000000000002, 0xbff0000000000003);
+  status |= test__muldf3(0x3ff0000000000002, 0x3ff0000000000001, 0x3ff0000000000003);
+  status |= test__muldf3(0x3ff0000000000002, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |= test__muldf3(0x3ff0000000000001, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |= test__muldf3(0x4000000000000000, 0x0010000000000000, 0x0020000000000000);
+  status |= test__muldf3(0x4000000000000000, 0x0010000000000001, 0x0020000000000001);
+  status |= test__muldf3(0x4000000000000000, 0x3ff0000000000000, 0x4000000000000000);
+  status |= test__muldf3(0x4000000000000000, 0x4008000000000000, 0x4018000000000000);
+  status |= test__muldf3(0x4000000000000000, 0x7fd0000000000000, 0x7fe0000000000000);
+  status |= test__muldf3(0x4000000000000000, 0x7fdfffffffffffff, 0x7fefffffffffffff);
+  status |= test__muldf3(0x4000000000000000, 0x800ffffffffffffd, 0x801ffffffffffffa);
+  status |= test__muldf3(0x4000000000000000, 0x8010000000000003, 0x8020000000000003);
+  status |= test__muldf3(0x4000000000000000, 0x8010000000000005, 0x8020000000000005);
+  status |= test__muldf3(0x4000000000000000, 0xbff0000000000000, 0xc000000000000000);
+  status |= test__muldf3(0x4000000000000000, 0xffcffffffffffffd, 0xffdffffffffffffd);
+  status |= test__muldf3(0x4000000000000000, 0xffd0000000000003, 0xffe0000000000003);
+  status |= test__muldf3(0x4007ffffffffffff, 0x3feffffffffffffd, 0x4007fffffffffffd);
+  status |= test__muldf3(0x4007ffffffffffff, 0x3feffffffffffffe, 0x4007fffffffffffe);
+  status |= test__muldf3(0x4007ffffffffffff, 0x3fefffffffffffff, 0x4007fffffffffffe);
+  status |= test__muldf3(0x4007ffffffffffff, 0xbfeffffffffffffd, 0xc007fffffffffffd);
+  status |= test__muldf3(0x4008000000000000, 0x0000000000000002, 0x0000000000000006);
+  status |= test__muldf3(0x4008000000000000, 0x4000000000000000, 0x4018000000000000);
+  status |= test__muldf3(0x4008000000000000, 0x4008000000000000, 0x4022000000000000);
+  status |= test__muldf3(0x4008000000000000, 0xc000000000000000, 0xc018000000000000);
+  status |= test__muldf3(0x4008000000000001, 0x3ff0000000000001, 0x4008000000000003);
+  status |= test__muldf3(0x4008000000000001, 0x3ff0000000000003, 0x4008000000000006);
+  status |= test__muldf3(0x4008000000000001, 0xbff0000000000003, 0xc008000000000006);
+  status |= test__muldf3(0x4010000000000000, 0x0000000000000002, 0x0000000000000008);
+  status |= test__muldf3(0x4010000000000000, 0x7fcfffffffffffff, 0x7fefffffffffffff);
+  status |= test__muldf3(0x4010000000000000, 0xffcfffffffffffff, 0xffefffffffffffff);
+  status |= test__muldf3(0x4013ffffffffffff, 0x3fefffffffffffff, 0x4013fffffffffffe);
+  status |= test__muldf3(0x4014000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x4014000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x4014000000000001, 0x3ff0000000000001, 0x4014000000000002);
+  status |= test__muldf3(0x401bffffffffffff, 0x3feffffffffffffc, 0x401bfffffffffffc);
+  status |= test__muldf3(0x401bffffffffffff, 0x3fefffffffffffff, 0x401bfffffffffffe);
+  status |= test__muldf3(0x401c000000000000, 0x8000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x401c000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x401c000000000001, 0x3ff0000000000001, 0x401c000000000003);
+  status |= test__muldf3(0x7fcffffffffffffd, 0x4010000000000000, 0x7feffffffffffffd);
+  status |= test__muldf3(0x7fcffffffffffffd, 0xc010000000000000, 0xffeffffffffffffd);
+  status |= test__muldf3(0x7fd0000000000000, 0xc000000000000000, 0xffe0000000000000);
+  status |= test__muldf3(0x7fdffffffffffffd, 0xc000000000000008, 0xfff0000000000000);
+  status |= test__muldf3(0x7fdfffffffffffff, 0xc000000000000000, 0xffefffffffffffff);
+  status |= test__muldf3(0x7fe0000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x7fe0000000000000, 0x4000000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x7fe0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x7fe0000000000000, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |= test__muldf3(0x7fe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x7fe0000000000000, 0xffd0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x7fe0000000000000, 0xffd0000000000004, 0xfff0000000000000);
+  status |= test__muldf3(0x7fe0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x7fe0000000000009, 0x7feffffffffffffa, 0x7ff0000000000000);
+  status |= test__muldf3(0x7fe0000000000009, 0xc018000000000002, 0xfff0000000000000);
+  status |= test__muldf3(0x7fefffffffffffff, 0x0000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x001fffffffffffff, 0x7ff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x7fdfffffffffffff, 0x7ff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x8000000000000002, 0xfff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x8010000000000001, 0xfff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x8020000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0xc008000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0xffefffffffffffff, 0xfff0000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x8000000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x8000000000000000, 0x4018000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x8000000000000000, 0x7fefffffffffffff, 0x8000000000000000);
+  status |= test__muldf3(0x8000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x8000000000000000, 0x8000000000000004, 0x0000000000000000);
+  status |= test__muldf3(0x8000000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x8000000000000000, 0xc020000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x8000000000000000, 0xffd0000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x8000000000000001, 0x0000000000000001, 0x8000000000000000);
+  status |= test__muldf3(0x8000000000000001, 0x4014000000000000, 0x8000000000000005);
+  status |= test__muldf3(0x8000000000000002, 0x3ff0000000000000, 0x8000000000000002);
+  status |= test__muldf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x8000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x8000000000000004, 0xbff0000000000000, 0x0000000000000004);
+  status |= test__muldf3(0x8000000000000008, 0x3fc0000000000000, 0x8000000000000001);
+  status |= test__muldf3(0x800ffffffffffff7, 0x0020000000000003, 0x8000000000000000);
+  status |= test__muldf3(0x800ffffffffffff7, 0x3ff0000000000001, 0x800ffffffffffff8);
+  status |= test__muldf3(0x800ffffffffffffd, 0xc000000000000000, 0x001ffffffffffffa);
+  status |= test__muldf3(0x800fffffffffffff, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x800fffffffffffff, 0x3ff0000000000001, 0x8010000000000000);
+  status |= test__muldf3(0x800fffffffffffff, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x800fffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x800fffffffffffff, 0x800ffffffffffffe, 0x0000000000000000);
+  status |= test__muldf3(0x800fffffffffffff, 0xbff0000000000000, 0x000fffffffffffff);
+  status |= test__muldf3(0x800fffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x8010000000000000, 0x0010000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x8010000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x8010000000000001, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x8010000000000001, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0x8010000000000001, 0xbff0000000000000, 0x0010000000000001);
+  status |= test__muldf3(0x801ffffffffffffc, 0x3fe0000000000000, 0x800ffffffffffffe);
+  status |= test__muldf3(0x801ffffffffffffc, 0xbfe0000000000000, 0x000ffffffffffffe);
+  status |= test__muldf3(0x801ffffffffffffe, 0x3ff0000000000000, 0x801ffffffffffffe);
+  status |= test__muldf3(0x801fffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0x801fffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x8020000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0x8020000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xbfefffffffffffff, 0xffefffffffffffff, 0x7feffffffffffffe);
+  status |= test__muldf3(0xbff0000000000000, 0x0000000000000009, 0x8000000000000009);
+  status |= test__muldf3(0xbff0000000000000, 0x0010000000000009, 0x8010000000000009);
+  status |= test__muldf3(0xbff0000000000000, 0x3ff0000000000000, 0xbff0000000000000);
+  status |= test__muldf3(0xbff0000000000000, 0x4000000000000000, 0xc000000000000000);
+  status |= test__muldf3(0xbff0000000000000, 0xbff0000000000000, 0x3ff0000000000000);
+  status |= test__muldf3(0xbff0000000000000, 0xc000000000000000, 0x4000000000000000);
+  status |= test__muldf3(0xbff0000000000001, 0x3ff0000000000001, 0xbff0000000000002);
+  status |= test__muldf3(0xbff0000000000001, 0xbff0000000000001, 0x3ff0000000000002);
+  status |= test__muldf3(0xbff0000000000001, 0xbff0000000000002, 0x3ff0000000000003);
+  status |= test__muldf3(0xbff0000000000002, 0x3ff0000000000001, 0xbff0000000000003);
+  status |= test__muldf3(0xbff0000000000002, 0xbff0000000000001, 0x3ff0000000000003);
+  status |= test__muldf3(0xc000000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0xc000000000000000, 0x000ffffffffffffd, 0x801ffffffffffffa);
+  status |= test__muldf3(0xc000000000000000, 0x0010000000000001, 0x8020000000000001);
+  status |= test__muldf3(0xc000000000000000, 0x0010000000000005, 0x8020000000000005);
+  status |= test__muldf3(0xc000000000000000, 0x0010000000000009, 0x8020000000000009);
+  status |= test__muldf3(0xc000000000000000, 0x4008000000000000, 0xc018000000000000);
+  status |= test__muldf3(0xc000000000000000, 0x7fcfffffffffffff, 0xffdfffffffffffff);
+  status |= test__muldf3(0xc000000000000000, 0x7fd0000000000001, 0xffe0000000000001);
+  status |= test__muldf3(0xc000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xc000000000000000, 0xbff0000000000000, 0x4000000000000000);
+  status |= test__muldf3(0xc000000000000000, 0xc008000000000000, 0x4018000000000000);
+  status |= test__muldf3(0xc007fffffffffffe, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xc007ffffffffffff, 0x3fefffffffffffff, 0xc007fffffffffffe);
+  status |= test__muldf3(0xc008000000000000, 0x4008000000000000, 0xc022000000000000);
+  status |= test__muldf3(0xc008000000000000, 0xc000000000000000, 0x4018000000000000);
+  status |= test__muldf3(0xc008000000000000, 0xc008000000000000, 0x4022000000000000);
+  status |= test__muldf3(0xc008000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xc008000000000001, 0x3ff0000000000001, 0xc008000000000003);
+  status |= test__muldf3(0xc010000000000000, 0x7fcfffffffffffff, 0xffefffffffffffff);
+  status |= test__muldf3(0xc010000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0xc010000000000000, 0xffcfffffffffffff, 0x7fefffffffffffff);
+  status |= test__muldf3(0xc010000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xc013fffffffffffe, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xc013ffffffffffff, 0xbfefffffffffffff, 0x4013fffffffffffe);
+  status |= test__muldf3(0xc014000000000001, 0xbff0000000000001, 0x4014000000000002);
+  status |= test__muldf3(0xc01bfffffffffff9, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xc022000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xc022000000000001, 0xffe0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xffcffffffffffff9, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xffcffffffffffff9, 0xc00fffffffffffff, 0x7feffffffffffff8);
+  status |= test__muldf3(0xffcffffffffffffd, 0x4010000000000000, 0xffeffffffffffffd);
+  status |= test__muldf3(0xffcffffffffffffd, 0xc010000000000000, 0x7feffffffffffffd);
+  status |= test__muldf3(0xffcfffffffffffff, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0xffcfffffffffffff, 0x4000000000000001, 0xffe0000000000000);
+  status |= test__muldf3(0xffcfffffffffffff, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xffd0000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |= test__muldf3(0xffd0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xffdffffffffffff7, 0x7fd0000000000001, 0xfff0000000000000);
+  status |= test__muldf3(0xffdfffffffffffff, 0x3ff0000000000001, 0xffe0000000000000);
+  status |= test__muldf3(0xffdfffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0xffe0000000000005, 0xffe0000000000001, 0x7ff0000000000000);
+  status |= test__muldf3(0xffeffffffffffffd, 0x7fe0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xffeffffffffffffd, 0xc008000000000001, 0x7ff0000000000000);
+  status |= test__muldf3(0xffeffffffffffffd, 0xffe0000000000001, 0x7ff0000000000000);
+  status |= test__muldf3(0xffefffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |= test__muldf3(0xffefffffffffffff, 0xffefffffffffffff, 0x7ff0000000000000);
+  status |= test__muldf3(0xffefffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xfff0000000000000, 0x4018000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xfff0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |= test__muldf3(0xfff0000000000000, 0x8000000000000004, 0x7ff0000000000000);
+  status |= test__muldf3(0xfff0000000000000, 0x8010000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xfff0000000000000, 0xc020000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xfff0000000000000, 0xffd0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x002ffffffe000000, 0x3fcffffffffffffd, 0x000ffffffeffffff);
+  status |= test__muldf3(0xbfeffeffffffffff, 0x8010000000000100, 0x000fff80000000ff);
+  status |= test__muldf3(0x802ffffffe000000, 0x3fcffffffffffffd, 0x800ffffffeffffff);
+  status |= test__muldf3(0xbfeffeffffffffff, 0x0010000000000100, 0x800fff80000000ff);
+  status |= test__muldf3(0xbf9e8325a5aa6c8d, 0xbf9e8325a5aa6c8d, 0x3f4d180013083955);
+  status |= test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fe4000000000000, 0x3ff237a6f271c5c4);
+  status |= test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fe4000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x201d25d7ea4fa2d4, 0x1fd4000000000000, 0x00091bd37938e2e2);
+  status |= test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fe8000000000000, 0x3ff5dc61efbbba1f);
+  status |= test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fe8000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x201d25d7ea4fa2d4, 0x1fd8000000000000, 0x000aee30f7dddd10);
+  status |= test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fec000000000000, 0x3ff9811ced05ae7a);
+  status |= test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fec000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x201d25d7ea4fa2d4, 0x1fdc000000000000, 0x000cc08e7682d73d);
+  status |= test__muldf3(0x3ff265f139b6c87c, 0x3ff7000000000000, 0x3ffa728ac2f6c032);
+  status |= test__muldf3(0x6ff265f139b6c87c, 0x4ff7000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x201265f139b6c87c, 0x1fe7000000000000, 0x000d3945617b6019);
+  status |= test__muldf3(0x3ff265f139b6c87c, 0x3ff5000000000000, 0x3ff825cc9bbfe723);
+  status |= test__muldf3(0x6ff265f139b6c87c, 0x4ff5000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x201265f139b6c87c, 0x1fe5000000000000, 0x000c12e64ddff391);
+  status |= test__muldf3(0x3ffe5ab1dc9f12f9, 0x3ff0c1a10c80f0b7, 0x3fffca09666ab16e);
+  status |= test__muldf3(0x6ffe5ab1dc9f12f9, 0x4ff0c1a10c80f0b7, 0x7ff0000000000000);
+  status |= test__muldf3(0x201e5ab1dc9f12f9, 0x1fe0c1a10c80f0b7, 0x000fe504b33558b7);
+  status |= test__muldf3(0x3ffe5ab1dc9f12f9, 0x3fe73e5ef37f0f49, 0x3ff60c59a0917f00);
+  status |= test__muldf3(0x6ffe5ab1dc9f12f9, 0x4fe73e5ef37f0f49, 0x7ff0000000000000);
+  status |= test__muldf3(0x201e5ab1dc9f12f9, 0x1fd73e5ef37f0f49, 0x000b062cd048bf80);
+  status |= test__muldf3(0x3ffe5ab1dc9f12f9, 0x3fe8c1a10c80f0b7, 0x3ff77bb12a5d1d75);
+  status |= test__muldf3(0x6ffe5ab1dc9f12f9, 0x4fe8c1a10c80f0b7, 0x7ff0000000000000);
+  status |= test__muldf3(0x201e5ab1dc9f12f9, 0x1fd8c1a10c80f0b7, 0x000bbdd8952e8ebb);
+  status |= test__muldf3(0x3ffc6be665de3b1d, 0x3fe52d156619a0cb, 0x3ff2ced9f056fba8);
+  status |= test__muldf3(0x6ffc6be665de3b1d, 0x4fe52d156619a0cb, 0x7ff0000000000000);
+  status |= test__muldf3(0x201c6be665de3b1d, 0x1fd52d156619a0cb, 0x0009676cf82b7dd4);
+  status |= test__muldf3(0x3ffc6be665de3b1d, 0x3fead2ea99e65f35, 0x3ff7d2ffa8765d03);
+  status |= test__muldf3(0x6ffc6be665de3b1d, 0x4fead2ea99e65f35, 0x7ff0000000000000);
+  status |= test__muldf3(0x201c6be665de3b1d, 0x1fdad2ea99e65f35, 0x000be97fd43b2e82);
+  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ff5c9b956d0b54b, 0x3ff82c50eb71ac34);
+  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ff5c9b956d0b54b, 0x7ff0000000000000);
+  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fe5c9b956d0b54b, 0x000c162875b8d61a);
+  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ff23646a92f4ab5, 0x3ff434a77da664d4);
+  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ff23646a92f4ab5, 0x7ff0000000000000);
+  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fe23646a92f4ab5, 0x000a1a53bed3326a);
+  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ffa3646a92f4ab5, 0x3ffd14d92c44cea3);
+  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ffa3646a92f4ab5, 0x7ff0000000000000);
+  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fea3646a92f4ab5, 0x000e8a6c96226751);
+  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ff1c9b956d0b54b, 0x3ff3bc381422774d);
+  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ff1c9b956d0b54b, 0x7ff0000000000000);
+  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fe1c9b956d0b54b, 0x0009de1c0a113ba6);
+  status |= test__muldf3(0x3ff907065fd11389, 0x3fe46bad37af52b9, 0x3feff135e5756ec7);
+  status |= test__muldf3(0x6ff907065fd11389, 0x4fe46bad37af52b9, 0x7feff135e5756ec7);
+  status |= test__muldf3(0x201907065fd11389, 0x1fd46bad37af52b9, 0x0007fc4d795d5bb2);
+  status |= test__muldf3(0x3ff907065fd11389, 0x3feb9452c850ad47, 0x3ff591ee9cfee5ea);
+  status |= test__muldf3(0x6ff907065fd11389, 0x4feb9452c850ad47, 0x7ff0000000000000);
+  status |= test__muldf3(0x201907065fd11389, 0x1fdb9452c850ad47, 0x000ac8f74e7f72f5);
+  status |= test__muldf3(0x3ff761c03e198df7, 0x3fe7f47c731d43c7, 0x3ff180e675617e83);
+  status |= test__muldf3(0x6ff761c03e198df7, 0x4fe7f47c731d43c7, 0x7ff0000000000000);
+  status |= test__muldf3(0x201761c03e198df7, 0x1fd7f47c731d43c7, 0x0008c0733ab0bf41);
+  status |= test__muldf3(0x3ffce6d1246c46fb, 0x3ff0b3469ded2bcd, 0x3ffe2aa6f74c0ffd);
+  status |= test__muldf3(0x6ffce6d1246c46fb, 0x4ff0b3469ded2bcd, 0x7ff0000000000000);
+  status |= test__muldf3(0x201ce6d1246c46fb, 0x1fe0b3469ded2bcd, 0x000f15537ba607fe);
+  status |= test__muldf3(0x3ffd5701100ec79d, 0x3fee654fee13094b, 0x3ffbde74e37bb583);
+  status |= test__muldf3(0x6ffd5701100ec79d, 0x4fee654fee13094b, 0x7ff0000000000000);
+  status |= test__muldf3(0x201d5701100ec79d, 0x1fde654fee13094b, 0x000def3a71bddac1);
+  status |= test__muldf3(0x3ffce1a06e8bcfd3, 0x3ff01c54436a605b, 0x3ffd14c361885d61);
+  status |= test__muldf3(0x6ffce1a06e8bcfd3, 0x4ff01c54436a605b, 0x7ff0000000000000);
+  status |= test__muldf3(0x201ce1a06e8bcfd3, 0x1fe01c54436a605b, 0x000e8a61b0c42eb0);
+  status |= test__muldf3(0x3ff21d1a5ca518a5, 0x3ff29f0ce1150f2d, 0x3ff514cd72d743f2);
+  status |= test__muldf3(0x6ff21d1a5ca518a5, 0x4ff29f0ce1150f2d, 0x7ff0000000000000);
+  status |= test__muldf3(0x20121d1a5ca518a5, 0x1fe29f0ce1150f2d, 0x000a8a66b96ba1f9);
+  status |= test__muldf3(0x3ff031a98dbf97ba, 0x3ff4000000000000, 0x3ff43e13f12f7da8);
+  status |= test__muldf3(0x6ff031a98dbf97ba, 0x4ff4000000000000, 0x7ff0000000000000);
+  status |= test__muldf3(0x201031a98dbf97ba, 0x1fe4000000000000, 0x000a1f09f897bed4);
+  status |= test__muldf3(0x0000000000000003, 0xc00fffffffffffff, 0x800000000000000c);
+  status |= test__muldf3(0x0000000000000003, 0x400fffffffffffff, 0x000000000000000c);
+  status |= test__muldf3(0x8000000000000003, 0xc00fffffffffffff, 0x000000000000000c);
+  status |= test__muldf3(0x8000000000000003, 0x400fffffffffffff, 0x800000000000000c);
+  status |= test__muldf3(0x0000000000000003, 0xc00ffffffffffffd, 0x800000000000000c);
+  status |= test__muldf3(0x0000000000000003, 0x400ffffffffffffd, 0x000000000000000c);
+  status |= test__muldf3(0x8000000000000003, 0xc00ffffffffffffd, 0x000000000000000c);
+  status |= test__muldf3(0x8000000000000003, 0x400ffffffffffffd, 0x800000000000000c);
+  status |= test__muldf3(0x1e51f703ee090000, 0x1e5c8000e4000000, 0x0000000000000001);
+  status |= test__muldf3(0x1e561ed9745fdb21, 0x1e57255ca25b68e1, 0x0000000000000001);
+  status |= test__muldf3(0x7feffffffff00000, 0xc000000000080000, 0xfff0000000000000);
+
+  // Test that the result of an operation is a NaN at all when it should be.
+  //
+  // In most configurations these tests' results are checked compared using
+  // compareResultD, so we set all the answers to the canonical NaN
+  // 0x7ff8000000000000, which causes compareResultF to accept any NaN
+  // encoding. We also use the same value as the input NaN in tests that have
+  // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
+  // because 0x7ff8000000000000 is still the exact expected NaN.
+  status |= test__muldf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff8000000000000);
+  status |= test__muldf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff8000000000000);
+  status |= test__muldf3(0x8000000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |= test__muldf3(0x8000000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |= test__muldf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |= test__muldf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |= test__muldf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+
+#ifdef ARM_NAN_HANDLING
+  // Tests specific to the NaN handling of Arm hardware, mimicked by
+  // arm/muldf3.S:
+  //
+  //  - a quiet NaN is distinguished by the top mantissa bit being 1
+  //
+  //  - if a signalling NaN appears in the input, the output quiet NaN is
+  //    obtained by setting its top mantissa bit and leaving everything else
+  //    unchanged
+  //
+  //  - if both operands are signalling NaNs then the output NaN is derived
+  //    from the first operand
+  //
+  //  - if both operands are quiet NaNs then the output NaN is the first
+  //    operand
+  //
+  //  - invalid operations not involving an input NaN return the quiet
+  //    NaN with fewest bits set, 0x7ff8000000000000.
+  status |= test__muldf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |= test__muldf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |= test__muldf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |= test__muldf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |= test__muldf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |= test__muldf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |= test__muldf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |= test__muldf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |= test__muldf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |= test__muldf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |= test__muldf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |= test__muldf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |= test__muldf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |= test__muldf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |= test__muldf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |= test__muldf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |= test__muldf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |= test__muldf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |= test__muldf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |= test__muldf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |= test__muldf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |= test__muldf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |= test__muldf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |= test__muldf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |= test__muldf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |= test__muldf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |= test__muldf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |= test__muldf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |= test__muldf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |= test__muldf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |= test__muldf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |= test__muldf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |= test__muldf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |= test__muldf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |= test__muldf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |= test__muldf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |= test__muldf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |= test__muldf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |= test__muldf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |= test__muldf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |= test__muldf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |= test__muldf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |= test__muldf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |= test__muldf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |= test__muldf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |= test__muldf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |= test__muldf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |= test__muldf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |= test__muldf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |= test__muldf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |= test__muldf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |= test__muldf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+
+#endif // ARM_NAN_HANDLING
+
+  return status;
+}

>From c334fe75b5bc92469650b792a713341cb6be81a4 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 16:09:19 +0000
Subject: [PATCH 06/33] [compiler-rt][ARM] Optimized double-precision FP
 comparisons

The structure of these comparison functions consists of a header file
containing the main code, and several `.S` files that include that
header with different macro definitions, so that they can use the same
procedure to determine the logical comparison result and then just
translate it into a return value in different ways.
---
 compiler-rt/lib/builtins/CMakeLists.txt       |   8 +
 compiler-rt/lib/builtins/arm/cmpdf2.S         |  64 ++
 compiler-rt/lib/builtins/arm/dcmp.h           | 210 ++++++
 compiler-rt/lib/builtins/arm/gedf2.S          |  61 ++
 compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S  |  61 ++
 compiler-rt/lib/builtins/arm/thumb1/dcmp.h    | 236 +++++++
 compiler-rt/lib/builtins/arm/thumb1/gedf2.S   |  60 ++
 .../lib/builtins/arm/thumb1/unorddf2.S        |  60 ++
 compiler-rt/lib/builtins/arm/unorddf2.S       |  71 ++
 .../test/builtins/Unit/comparedf2new_test.c   | 609 ++++++++++++++++++
 10 files changed, 1440 insertions(+)
 create mode 100644 compiler-rt/lib/builtins/arm/cmpdf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/dcmp.h
 create mode 100644 compiler-rt/lib/builtins/arm/gedf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/dcmp.h
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/gedf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/unorddf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/unorddf2.S
 create mode 100644 compiler-rt/test/builtins/Unit/comparedf2new_test.c

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index b8e328f657eea..0e8b0fa553442 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -450,6 +450,9 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm")
       arm/adddf3.S
       arm/muldf3.S
       arm/divdf3.S
+      arm/cmpdf2.S
+      arm/gedf2.S
+      arm/unorddf2.S
       )
     set_source_files_properties(${assembly_files}
       PROPERTIES COMPILE_OPTIONS ${implicit_it_flag})
@@ -503,11 +506,16 @@ set_property(SOURCE arm/adddf3.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY cr
 if(COMPILER_RT_ARM_OPTIMIZED_FP)
   set(thumb1_base_SOURCES
     arm/thumb1/mulsf3.S
+    arm/thumb1/cmpdf2.S
+    arm/thumb1/gedf2.S
+    arm/thumb1/unorddf2.S
     arm/fnan2.c
     arm/fnorm2.c
     arm/funder.c
     ${thumb1_base_SOURCES}
   )
+  set_property(SOURCE arm/thumb1/cmpdf2.S PROPERTY crt_supersedes comparedf2.c)
+  set_property(SOURCE arm/thumb1/cmpdf2.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY crt_provides comparedf2)
 endif()
 
 set(arm_EABI_RT_SOURCES
diff --git a/compiler-rt/lib/builtins/arm/cmpdf2.S b/compiler-rt/lib/builtins/arm/cmpdf2.S
new file mode 100644
index 0000000000000..587c3f619f8ae
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/cmpdf2.S
@@ -0,0 +1,64 @@
+//===-- cmpdf2.S - double-precision floating point comparison -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpdf2: it's a three-way compare
+// which returns <0 if x<y, 0 if x==y, and >0 if x>y. If the result is
+// unordered (i.e. x or y or both is NaN) then it returns >0.
+//
+// This also makes it suitable for use as all of __eqdf2, __nedf2, __ltdf2 or
+// __ledf2.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+
+op0h .req xh
+op0l .req xl
+op1h .req yh
+op1l .req yl
+.macro SetReturnRegister
+  mov r0, #0
+  movhi r0, #1
+  movlo r0, #-1
+.endm
+.macro SetReturnRegisterNE
+  movne r0, #-1
+  movhi r0, #1
+.endm
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__cmpdf2)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  VMOV_FROM_DOUBLE(r2, r3, d1)
+  bl __compiler_rt_softfp_cmpdf2
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpdf2, __compiler_rt_softfp_cmpdf2)
+#endif
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__ledf2, __cmpdf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltdf2, __cmpdf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__eqdf2, __cmpdf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__nedf2, __cmpdf2)
+
+DEFINE_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpdf2)
+  #include "dcmp.h"
+
+LOCAL_LABEL(NaN):
+  mov r0, #+1
+  bx lr
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpdf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/dcmp.h b/compiler-rt/lib/builtins/arm/dcmp.h
new file mode 100644
index 0000000000000..c9fd0ef324365
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/dcmp.h
@@ -0,0 +1,210 @@
+//===-- dcmp.h - shared code for double-precision FP comparison functions -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This code is the skeleton of a double-precision FP compare, with two details
+// left out: which input value is in which register, and how to make the return
+// value. It allows the main comparison logic to be shared between (for
+// example) __ledf2 and __gedf2, varying only those details.
+//
+//===----------------------------------------------------------------------===//
+
+// How to use this header file:
+//
+// This header file is expected to be #included from inside a function
+// definition in a .S file. The source file including this header should
+// provide the following:
+//
+// op0h, op0l, op1h, op1l: register aliases (via .req) for the registers
+// containing the input operands.
+//  - For most comparisons, op0h,op0l will correspond to ah,al, and op1h,op1l
+//    to bh,bl (as defined in turn in endian.h).
+//  - But a function with the reversed semantics of __aeabi_cdrcmple wil define
+//    them the other way round.
+//
+// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up
+// an appropriate return value in r0, for the cases that do *not* involve NaN.
+//  - On entry to this macro, the condition codes LO, EQ and HI indicate that
+//    op0 < op1, op0 == op1 or op0 > op1 respectively.
+//  - For functions that return a result in the flags, this macro can be empty,
+//    because those are the correct flags to return anyway.
+//  - Functions that return a boolean in r0 should set it up by checking the
+//    flags.
+//
+// SetReturnRegisterNE: a macro that does the same thing as SetReturnRegister,
+// except that if the Z flag is set, it instead does nothing at all. (This
+// macro must not assume that the flags were set by a single CMP: in
+// particular, C=0 but Z=1 is possible on entry to this macro, so you must not
+// use the LO condition code and assume it is mutually exclusive with EQ.)
+//
+// LOCAL_LABEL(NaN): a label defined within the compare function, after the
+// #include of this header. Called when at least one input is a NaN, and sets
+// up the appropriate return value for that case.
+
+// --------------------------------------------------
+// The actual entry point of the compare function.
+//
+// The basic plan is to start by ORing together the two inputs. This tells us
+// two things:
+//  - the top bit of the output tells us whether both inputs are positive, or
+//    whether at least one is negative
+//  - if the 11 exponent bits of the output are not all 1, then there are
+//    definitely no NaNs, so a fast path can handle most non-NaN cases.
+
+  // First diverge control for the negative-numbers case.
+  orrs    r12, op0h, op1h
+  bmi     LOCAL_LABEL(negative)         // high bit set => at least one negative input
+
+  // Here, both inputs are positive. Try adding 1<<20 to their bitwise OR in
+  // r12. This will carry all the way into the top bit, setting the N flag, if
+  // all 11 exponent bits were set.
+  cmn     r12, #1 << 20
+  bmi     LOCAL_LABEL(NaNInf_check_positive) // need to look harder for NaNs
+
+  // The fastest fast path: both inputs positive and we could easily tell there
+  // were no NaNs. So we just compare op0 and op1 as unsigned integers.
+  cmp     op0h, op1h
+  SetReturnRegisterNE
+  bxne    lr
+  cmp     op0l, op1l
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaNInf_check_positive):
+  // Second tier for positive numbers. We come here if both inputs are
+  // positive, but our fast initial check didn't manage to rule out a NaN. But
+  // it's not guaranteed that there _is_ a NaN, for two reasons:
+  //
+  //  1. An input with exponent 0x7FF might be an infinity instead. Those
+  //     behave normally under comparison.
+  //
+  //  2. There might not even _be_ an input with exponent 0x7FF. All we know so
+  //     far is that the two inputs ORed together had all the exponent bits
+  //     set. So each of those bits is set in _at least one_ of the inputs, but
+  //     not necessarily all in the _same_ input.
+  //
+  // Test each exponent individually for 0x7FF, using the same CMN idiom as
+  // above. If neither one carries into the sign bit then we have no NaNs _or_
+  // infinities and can compare the registers and return again.
+  cmn     op0h, #1 << 20
+  cmnpl   op1h, #1 << 20
+  bmi     LOCAL_LABEL(NaN_check_positive)
+
+  // Second-tier return path, now we've ruled out anything difficult. By this
+  // time we know that the two operands have different exponents (because the
+  // exponents' bitwise OR is 0x7FF but neither one is 0x7FF by itself, so each
+  // must have a set bit not present in the other). So we only need to compare
+  // the high words.
+  cmp     op0h, op1h
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaN_check_positive):
+  // Third tier for positive numbers. Here we know that at least one of the
+  // inputs has exponent 0x7FF. But they might still be infinities rather than
+  // NaNs. So now we must check whether there's an actual NaN.
+  //
+  // We do this by shifting the high word of each input left to get rid of the
+  // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in
+  // the low word. Then we check if the result is _greater_ than 0xFFE00000
+  // (but not equal), via adding 0x00200000 to it and testing for the HI
+  // condition (carry flag set, but Z clear).
+  //
+  // We could have skipped the second-tier check and done this more rigorous
+  // test immediately. But that would cost an extra instruction in the case
+  // where there are no infinities or NaNs, and we assume that that is so much
+  // more common that it's worth optimizing for.
+  cmp     op0l, #1           // set C if op0l is nonzero
+  adc     op0h, op0h, op0h   // shift op0h left, bringing in the C bit
+  cmp     op1l, #1           // set C if op1l is nonzero
+  adc     op1h, op1h, op1h   // shift op1h left, bringing in the C bit
+  cmn     op0h, #1 << 21     // if HI, then op0 is a NaN
+  cmnls   op1h, #1 << 21     // if not HI, then do the same check for op1
+  bhi     LOCAL_LABEL(NaN)           // now, if HI, there's definitely a NaN
+
+  // Now we've finally ruled out NaNs! And we still know both inputs are
+  // positive. So the third-tier return path can just compare the top words
+  // again. (The fact that we've just shifted them left doesn't make a
+  // difference.)
+  cmp     op0h, op1h
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(negative):
+  // We come here if at least one operand is negative. We haven't checked for
+  // NaNs at all yet (the sign check came first), so repeat the first-tier
+  // check strategy of seeing if all exponent bits are set in r12.
+  //
+  // On this path, the sign bit in r12 is set, so if adding 1 to the low
+  // exponent bit carries all the way through into the sign bit, it will
+  // _clear_ the sign bit rather than setting it. So we expect MI to be the
+  // "definitely no NaNs" result, where it was PL on the positive branch.
+  cmn     r12, #1 << 20
+  bpl     LOCAL_LABEL(NaNInf_check_negative)
+
+  // Now we have no NaNs, but at least one negative number. This gives us two
+  // complications:
+  //
+  //  1. Floating-point numbers are sign/magnitude, not two's complement, so we
+  //     have to consider separately the cases of "both negative" and "one of
+  //     each sign".
+  //
+  //  2. -0 and +0 are required to compare equal.
+  //
+  // But problem #1 is not as hard as it sounds! If both operands are negative,
+  // then we can get the result we want by comparing them as unsigned integers
+  // the opposite way round, because the input with the smaller value (as an
+  // integer) is the larger number in an FP ordering sense. And if one operand
+  // is negative and the other is positive, the _same_ reversed comparison
+  // works, because the positive number (with zero sign bit) will always
+  // compare less than the negative one in an unsigned-integers sense.
+  //
+  // So we only have to worry about problem #2, signed zeroes. This only
+  // affects the answer if _both_ operands are zero. So we check that by
+  // testing all bits of both operands apart from the sign bit.
+  orrs    r12, op0l, op0h, LSL #1 // EQ if op0 is zero
+  orrseq  r12, op1l, op1h, LSL #1 // now only EQ if both are zero
+  cmpne   op1h, op0h              // otherwise, compare them backwards
+  SetReturnRegisterNE
+  bxne    lr
+  cmp     op1l, op0l
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaNInf_check_negative):
+  // Second tier for negative numbers: we know the OR of the exponents is 0xFF,
+  // but again, we might not have either _actual_ exponent 0xFF, and also, an
+  // exponent 0xFF might be an infinity instead of a NaN.
+  //
+  // On this path we've already branched twice (once for negative numbers and
+  // once for the first-tier NaN check), so we'll just go straight to the
+  // precise check for NaNs.
+  //
+  // Like the NaNInf_check_positive case, we do each NaN check by making a
+  // word consisting of (high word << 1) OR (1 if low word is nonzero). But
+  // unlike the positive case, we can't make those words _in place_,
+  // overwriting op0h and op1h themselves, because that would shift the sign
+  // bits off the top, and we still need the sign bits to get the comparison
+  // right. (In the positive case, we knew both sign bits were 0, enabling a
+  // shortcut.)
+  cmp     op0l, #1           // set C if op0l is nonzero
+  adc     r12, op0h, op0h    // shift op0h left, bringing in the C bit
+  cmn     r12, #1 << 21      // if HI, then op0 is a NaN
+  bhi     LOCAL_LABEL(NaN)
+  cmp     op1l, #1           // set C if op1l is nonzero
+  adc     r12, op1h, op1h    // shift op1h left, bringing in the C bit
+  cmn     r12, #1 << 21      // if HI, then op1 is a NaN
+  bhi     LOCAL_LABEL(NaN)
+
+  // Now we've ruled out NaNs, so we can just compare the two input registers
+  // and return. On this path we _don't_ need to check for the special case of
+  // comparing two zeroes, because we only came here if the bitwise OR of the
+  // exponent fields was 0x7FF, which means the exponents can't both have been
+  // zero! So we can _just_ do the reversed CMP and finish.
+  cmp     op1h, op0h
+  SetReturnRegister
+  bx      lr
diff --git a/compiler-rt/lib/builtins/arm/gedf2.S b/compiler-rt/lib/builtins/arm/gedf2.S
new file mode 100644
index 0000000000000..531827559b236
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/gedf2.S
@@ -0,0 +1,61 @@
+//===-- gedf2.S - double-precision floating point comparison --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpdf2, except for its NaN
+// handling. It's a three-way compare which returns <0 if x<y, 0 if x==y, and
+// >0 if x>y. If the result is unordered (i.e. x or y or both is NaN) then it
+// returns <0, where __cmpdf2 would return >0.
+//
+// This also makes it suitable for use as __gtdf2 or __gedf2 (or __eqdf2 or
+// __nedf2).
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+op0h .req xh
+op0l .req xl
+op1h .req yh
+op1l .req yl
+.macro SetReturnRegister
+  mov r0, #0
+  movhi r0, #1
+  movlo r0, #-1
+.endm
+.macro SetReturnRegisterNE
+  movne r0, #-1
+  movhi r0, #1
+.endm
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__gedf2)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  VMOV_FROM_DOUBLE(r2, r3, d1)
+  bl __compiler_rt_softfp_gedf2
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gedf2, __compiler_rt_softfp_gedf2)
+#endif
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gtdf2, __gedf2)
+
+DEFINE_COMPILERRT_FUNCTION(__compiler_rt_softfp_gedf2)
+  #include "dcmp.h"
+
+LOCAL_LABEL(NaN):
+  mov r0, #-1
+  bx lr
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_gedf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S b/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S
new file mode 100644
index 0000000000000..d6d37198b5145
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S
@@ -0,0 +1,61 @@
+//===-- cmpdf2.S - double-precision floating point comparison -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpdf2: it's a three-way compare
+// which returns <0 if x<y, 0 if x==y, and >0 if x>y. If the result is
+// unordered (i.e. x or y or both is NaN) then it returns >0.
+//
+// This also makes it suitable for use as all of __eqdf2, __nedf2, __ltdf2 or
+// __ledf2.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../assembly.h"
+#include "../endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+op0h .req xh
+op0l .req xl
+op1h .req yh
+op1l .req yl
+.macro SetReturnRegister
+  bhi 0f
+  blo 1f
+  movs r0, #0
+  // This macro is always called immediately before returning from the
+  // function, so it's safe to use the same return instruction here, instead of
+  // wasting time branching forward to the end of the macro.
+  pop     {r4,r5,r6,pc}
+0:
+  movs r0, #1
+  pop     {r4,r5,r6,pc}
+1:
+  movs r0, #1
+  rsbs r0, r0, #0
+  pop     {r4,r5,r6,pc}
+.endm
+
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpdf2, __compiler_rt_softfp_cmpdf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__ledf2, __cmpdf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltdf2, __cmpdf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__eqdf2, __cmpdf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__nedf2, __cmpdf2)
+
+DEFINE_COMPILERRT_THUMB_FUNCTION(__compiler_rt_softfp_cmpdf2)
+  #include "dcmp.h"
+
+LOCAL_LABEL(NaN):
+  movs r0, #1
+  pop     {r4,r5,r6,pc}
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpdf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/thumb1/dcmp.h b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
new file mode 100644
index 0000000000000..fc45b5d469120
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
@@ -0,0 +1,236 @@
+//===-- dcmp.h - shared code for double-precision FP comparison functions -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This code is the skeleton of a double-precision FP compare, with two details
+// left out: which input value is in which register, and how to make the return
+// value. It allows the main comparison logic to be shared between (for
+// example) __ledf2 and __gedf2, varying only those details.
+//
+//===----------------------------------------------------------------------===//
+
+// How to use this header file:
+//
+// This header file is expected to be #included from inside a function
+// definition in a .S file. The source file including this header should
+// provide the following:
+//
+// op0h, op0l, op1h, op1l: register aliases (via .req) for the registers
+// containing the input operands.
+//  - For most comparisons, op0h,op0l will correspond to ah,al, and op1h,op1l
+//    to bh,bl (as defined in turn in endian.h).
+//  - But a function with the reversed semantics of __aeabi_cdrcmple wil define
+//    them the other way round.
+//
+// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up
+// an appropriate return value in r0, for the cases that do *not* involve NaN.
+//  - On entry to this macro, the condition codes LO, EQ and HI indicate that
+//    op0 < op1, op0 == op1 or op0 > op1 respectively.
+//  - For functions that return a result in the flags, this macro can be empty,
+//    because those are the correct flags to return anyway.
+//  - Functions that return a boolean in r0 should set it up by checking the
+//    flags.
+//
+// LOCAL_LABEL(NaN): a label defined within the compare function, after the
+// #include of this header. Called when at least one input is a NaN, and sets
+// up the appropriate return value for that case.
+
+// --------------------------------------------------
+// The actual entry point of the compare function.
+//
+// The basic plan is to start by ORing together the two inputs. This tells us
+// two things:
+//  - the top bit of the output tells us whether both inputs are positive, or
+//    whether at least one is negative
+//  - if the 11 exponent bits of the output are not all 1, then there are
+//    definitely no NaNs, so a fast path can handle most non-NaN cases.
+
+  push    {r4,r5,r6,lr}
+
+  // Set up the constant 1 << 20 in a register, which we'll need on all
+  // branches.
+  movs    r5, #1
+  lsls    r5, r5, #20
+
+  // First diverge control for the negative-numbers case.
+  movs    r4, op0h
+  orrs    r4, r4, op1h
+  bmi     LOCAL_LABEL(negative)         // high bit set => at least one negative input
+
+  // Here, both inputs are positive. Try adding 1<<20 to their bitwise OR in
+  // r4. This will carry all the way into the top bit, setting the N flag, if
+  // all 11 exponent bits were set.
+  cmn     r4, r5
+  bmi     LOCAL_LABEL(NaNInf_check_positive) // need to look harder for NaNs
+
+  // The fastest fast path: both inputs positive and we could easily tell there
+  // were no NaNs. So we just compare op0 and op1 as unsigned integers.
+  cmp     op0h, op1h
+  beq     LOCAL_LABEL(low_word_positive)
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
+LOCAL_LABEL(low_word_positive):
+  cmp     op0l, op1l
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
+
+LOCAL_LABEL(NaNInf_check_positive):
+  // Second tier for positive numbers. We come here if both inputs are
+  // positive, but our fast initial check didn't manage to rule out a NaN. But
+  // it's not guaranteed that there _is_ a NaN, for two reasons:
+  //
+  //  1. An input with exponent 0x7FF might be an infinity instead. Those
+  //     behave normally under comparison.
+  //
+  //  2. There might not even _be_ an input with exponent 0x7FF. All we know so
+  //     far is that the two inputs ORed together had all the exponent bits
+  //     set. So each of those bits is set in _at least one_ of the inputs, but
+  //     not necessarily all in the _same_ input.
+  //
+  // Test each exponent individually for 0x7FF, using the same CMN idiom as
+  // above. If neither one carries into the sign bit then we have no NaNs _or_
+  // infinities and can compare the registers and return again.
+  cmn     op0h, r5
+  bmi     LOCAL_LABEL(NaN_check_positive)
+  cmn     op1h, r5
+  bmi     LOCAL_LABEL(NaN_check_positive)
+
+  // Second-tier return path, now we've ruled out anything difficult. By this
+  // time we know that the two operands have different exponents (because the
+  // exponents' bitwise OR is 0x7FF but neither one is 0x7FF by itself, so each
+  // must have a set bit not present in the other). So we only need to compare
+  // the high words.
+  cmp     op0h, op1h
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
+
+LOCAL_LABEL(NaN_check_positive):
+  // Third tier for positive numbers. Here we know that at least one of the
+  // inputs has exponent 0x7FF. But they might still be infinities rather than
+  // NaNs. So now we must check whether there's an actual NaN.
+  //
+  // We do this by shifting the high word of each input left to get rid of the
+  // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in
+  // the low word. Then we check if the result is _greater_ than 0xFFE00000
+  // (but not equal), via adding 0x00200000 to it and testing for the HI
+  // condition (carry flag set, but Z clear).
+  //
+  // We could have skipped the second-tier check and done this more rigorous
+  // test immediately. But that would cost an extra instruction in the case
+  // where there are no infinities or NaNs, and we assume that that is so much
+  // more common that it's worth optimizing for.
+  lsls    r6, r5, #1         // set r6 = 1<<21
+  cmp     op0l, #1           // set C if op0l is nonzero
+  adcs    op0h, op0h, op0h   // shift op0h left, bringing in the C bit
+  cmn     op0h, r6           // if HI, then op0 is a NaN
+  bhi     LOCAL_LABEL(NaN)
+  cmp     op1l, #1           // set C if op1l is nonzero
+  adcs    op1h, op1h, op1h   // shift op1h left, bringing in the C bit
+  cmn     op1h, r6           // if HI, then op1 is a NaN
+  bhi     LOCAL_LABEL(NaN)
+
+  // Now we've finally ruled out NaNs! And we still know both inputs are
+  // positive. So the third-tier return path can just compare the top words
+  // again. (The fact that we've just shifted them left doesn't make a
+  // difference.)
+  cmp     op0h, op1h
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
+
+LOCAL_LABEL(negative):
+  // We come here if at least one operand is negative. We haven't checked for
+  // NaNs at all yet (the sign check came first), so repeat the first-tier
+  // check strategy of seeing if all exponent bits are set in r12.
+  //
+  // On this path, the sign bit in r12 is set, so if adding 1 to the low
+  // exponent bit carries all the way through into the sign bit, it will
+  // _clear_ the sign bit rather than setting it. So we expect MI to be the
+  // "definitely no NaNs" result, where it was PL on the positive branch.
+  cmn     r4, r5
+  bpl     LOCAL_LABEL(NaNInf_check_negative)
+
+  // Now we have no NaNs, but at least one negative number. This gives us two
+  // complications:
+  //
+  //  1. Floating-point numbers are sign/magnitude, not two's complement, so we
+  //     have to consider separately the cases of "both negative" and "one of
+  //     each sign".
+  //
+  //  2. -0 and +0 are required to compare equal.
+  //
+  // But problem #1 is not as hard as it sounds! If both operands are negative,
+  // then we can get the result we want by comparing them as unsigned integers
+  // the opposite way round, because the input with the smaller value (as an
+  // integer) is the larger number in an FP ordering sense. And if one operand
+  // is negative and the other is positive, the _same_ reversed comparison
+  // works, because the positive number (with zero sign bit) will always
+  // compare less than the negative one in an unsigned-integers sense.
+  //
+  // So we only have to worry about problem #2, signed zeroes. This only
+  // affects the answer if _both_ operands are zero. So we check that by
+  // testing all bits of both operands apart from the sign bit.
+  lsls    r6, r4, #1         // logical OR of both high words except the signs
+  orrs    r6, r6, op0l       // combine that with the low word of op0
+  orrs    r6, r6, op1l       // and op1, so now only EQ if both are zero
+  beq     LOCAL_LABEL(equal)
+  // Now we've ruled out confusing zero cases, just compare the operands in
+  // reverse sense.
+  cmp     op1h, op0h
+  beq     LOCAL_LABEL(low_word_negative)
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
+LOCAL_LABEL(low_word_negative):
+  cmp     op1l, op0l
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
+
+LOCAL_LABEL(equal):
+  // We come here if we know the inputs are supposed to compare equal. Set up
+  // the flags by comparing a register with itself.
+  //
+  // (We might have come here via a BEQ, in which case we know Z=1, but we also
+  // need C=1 for our caller to get _all_ the right flags.)
+  cmp     r0, r0             // compare a register with itself
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
+
+LOCAL_LABEL(NaNInf_check_negative):
+  // Second tier for negative numbers: we know the OR of the exponents is 0xFF,
+  // but again, we might not have either _actual_ exponent 0xFF, and also, an
+  // exponent 0xFF might be an infinity instead of a NaN.
+  //
+  // On this path we've already branched twice (once for negative numbers and
+  // once for the first-tier NaN check), so we'll just go straight to the
+  // precise check for NaNs.
+  //
+  // Like the NaNInf_check_positive case, we do each NaN check by making a
+  // word consisting of (high word << 1) OR (1 if low word is nonzero). But
+  // unlike the positive case, we can't make those words _in place_,
+  // overwriting op0h and op1h themselves, because that would shift the sign
+  // bits off the top, and we still need the sign bits to get the comparison
+  // right. (In the positive case, we knew both sign bits were 0, enabling a
+  // shortcut.)
+  lsls    r6, r5, #1         // set r6 = 1<<21
+  movs    r4, op0h           // copy op0h into a scratch register to modify
+  cmp     op0l, #1           // set C if op0l is nonzero
+  adcs    r4, r4, r4         // shift left, bringing in the C bit
+  cmn     r4, r6             // if HI, then op0 is a NaN
+  bhi     LOCAL_LABEL(NaN)
+  movs    r4, op1h           // copy op1h into a scratch register to modify
+  cmp     op1l, #1           // set C if op1l is nonzero
+  adcs    r4, r4, r4         // shift left, bringing in the C bit
+  cmn     r4, r6             // if HI, then op1 is a NaN
+  bhi     LOCAL_LABEL(NaN)
+
+  // Now we've ruled out NaNs, so we can just compare the two input registers
+  // and return. On this path we _don't_ need to check for the special case of
+  // comparing two zeroes, because we only came here if the bitwise OR of the
+  // exponent fields was 0x7FF, which means the exponents can't both have been
+  // zero! So we can _just_ do the reversed CMP and finish.
+  cmp     op1h, op0h
+  SetReturnRegister
+  pop     {r4,r5,r6,pc}
diff --git a/compiler-rt/lib/builtins/arm/thumb1/gedf2.S b/compiler-rt/lib/builtins/arm/thumb1/gedf2.S
new file mode 100644
index 0000000000000..3486403761bd5
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/gedf2.S
@@ -0,0 +1,60 @@
+//===-- gedf2.S - double-precision floating point comparison --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpdf2, except for its NaN
+// handling. It's a three-way compare which returns <0 if x<y, 0 if x==y, and
+// >0 if x>y. If the result is unordered (i.e. x or y or both is NaN) then it
+// returns <0, where __cmpdf2 would return >0.
+//
+// This also makes it suitable for use as __gtdf2 or __gedf2 (or __eqdf2 or
+// __nedf2).
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../assembly.h"
+#include "../endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+op0h .req xh
+op0l .req xl
+op1h .req yh
+op1l .req yl
+.macro SetReturnRegister
+  bhi 0f
+  blo 1f
+  movs r0, #0
+  // This macro is always called immediately before returning from the
+  // function, so it's safe to use the same return instruction here, instead of
+  // wasting time branching forward to the end of the macro.
+  pop     {r4,r5,r6,pc}
+0:
+  movs r0, #1
+  pop     {r4,r5,r6,pc}
+1:
+  movs r0, #1
+  rsbs r0, r0, #0
+  pop     {r4,r5,r6,pc}
+.endm
+
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gedf2, __compiler_rt_softfp_gedf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gtdf2, __gedf2)
+
+DEFINE_COMPILERRT_THUMB_FUNCTION(__compiler_rt_softfp_gedf2)
+  #include "dcmp.h"
+
+LOCAL_LABEL(NaN):
+  movs r0, #1
+  rsbs r0, r0, #0
+  pop     {r4,r5,r6,pc}
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_gedf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/thumb1/unorddf2.S b/compiler-rt/lib/builtins/arm/thumb1/unorddf2.S
new file mode 100644
index 0000000000000..a489e8a54fca4
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/unorddf2.S
@@ -0,0 +1,60 @@
+//===-- unorddf2.S - double-precision floating point comparison -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Return 1 if the result of comparing x with y is 'unordered', i.e.
+// one of x and y is NaN.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../assembly.h"
+#include "../endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__unorddf2, __aeabi_dcmpun)
+
+DEFINE_COMPILERRT_THUMB_FUNCTION(__aeabi_dcmpun)
+
+  // This function isn't based on the general-purpose code in dcmp.h, because
+  // it's more effort than needed. Here we just need to identify whether or not
+  // there's at least one NaN in the inputs. There's no need to vary that check
+  // based on the sign bit, so we might as well just do the NaN test as quickly
+  // as possible.
+  //
+  // We do this by shifting the high word of each input left to get rid of the
+  // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in
+  // the low word. Then we check if the result is _greater_ than 0xFFE00000
+  // (but not equal), via adding 0x00200000 to it and testing for the HI
+  // condition (carry flag set, but Z clear).
+  //
+  // Once we've done that transformation to the first input xh:xl, we
+  // free up xl to contain our constant 0x00200000, so there's no need
+  // to push any registers.
+  cmp     xl, #1                // set C if xl is nonzero
+  adcs    xh, xh, xh            // shift xh left, bringing in the C bit
+  movs    xl, #1                // now xl is free, make the test constant
+  lsls    xl, xl, #21           //   by shifting 1 left to make 0x00200000
+  cmn     xh, xl                // HI if x is a NaN
+  bhi     LOCAL_LABEL(NaN)
+  cmp     yl, #1                // set C if yl is nonzero
+  adcs    yh, yh, yh            // shift yh left, bringing in the C bit
+  cmn     yh, xl                // HI if y is a NaN
+  bhi     LOCAL_LABEL(NaN)
+
+  movs    r0, #0
+  bx      lr
+
+LOCAL_LABEL(NaN):
+  movs    r0, #1
+  bx      lr
+
+END_COMPILERRT_FUNCTION(__aeabi_dcmpun)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/unorddf2.S b/compiler-rt/lib/builtins/arm/unorddf2.S
new file mode 100644
index 0000000000000..961b64bf21f44
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/unorddf2.S
@@ -0,0 +1,71 @@
+//===-- unorddf2.S - double-precision floating point comparison -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Return 1 if the result of comparing x with y is 'unordered', i.e.
+// one of x and y is NaN.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+
+  .syntax unified
+  .text
+  .p2align 2
+
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__unorddf2)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  VMOV_FROM_DOUBLE(r2, r3, d1)
+  bl __aeabi_dcmpun
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__unorddf2, __aeabi_dcmpun)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmpun)
+
+  // This function isn't based on the general-purpose code in dcmp.h, because
+  // it's more effort than needed. Here we just need to identify whether or not
+  // there's at least one NaN in the inputs. There's no need to vary that check
+  // based on the sign bit, so we might as well just do the NaN test as quickly
+  // as possible.
+  //
+  // We do this by shifting the high word of each input left to get rid of the
+  // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in
+  // the low word. Then we check if the result is _greater_ than 0xFFE00000
+  // (but not equal), via adding 0x00200000 to it and testing for the HI
+  // condition (carry flag set, but Z clear).
+  //
+  // Once we've done that transformation to the first input xh:xl, we
+  // free up xl to contain our constant 0x00200000, so there's no need
+  // to push any registers.
+  cmp     xl, #1                // set C if xl is nonzero
+  adc     xh, xh, xh            // shift xh left, bringing in the C bit
+  cmp     yl, #1                // set C if yl is nonzero
+  adc     yh, yh, yh            // shift yh left, bringing in the C bit
+  cmn     xh, #1 << 21          // if HI, then x is a NaN
+  cmnls   yh, #1 << 21          // if not HI, then do the same check for y
+
+  // If LS, then we have no NaNs and return false. We do this as quickly as we
+  // can (not stopping to take two instructions setting up r0 for both
+  // possibilities), on the assumption that NaNs are rare and we want to
+  // optimize for the non-NaN path.
+  movls   r0, #0
+  bxls    lr
+
+  // Otherwise, we have at least one NaN, and return true.
+  mov     r0, #1
+  bx      lr
+
+END_COMPILERRT_FUNCTION(__aeabi_dcmpun)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/test/builtins/Unit/comparedf2new_test.c b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
new file mode 100644
index 0000000000000..f78a1a6aaa02d
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
@@ -0,0 +1,609 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_comparedf2
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+COMPILER_RT_ABI int __eqdf2(double, double);
+COMPILER_RT_ABI int __nedf2(double, double);
+COMPILER_RT_ABI int __gedf2(double, double);
+COMPILER_RT_ABI int __gtdf2(double, double);
+COMPILER_RT_ABI int __ledf2(double, double);
+COMPILER_RT_ABI int __ltdf2(double, double);
+COMPILER_RT_ABI int __cmpdf2(double, double);
+COMPILER_RT_ABI int __unorddf2(double, double);
+
+enum Result {
+  RESULT_LT,
+  RESULT_GT,
+  RESULT_EQ,
+  RESULT_UN
+};
+
+int expect(int line, uint64_t a_rep, uint64_t b_rep, const char *name, int result, int ok, const char *expected) {
+  if (!ok)
+    printf("error at line %d: %s(%016" PRIx64 ", %016" PRIx64 ") = %d, expected %s\n",
+           line, name, a_rep, b_rep, result, expected);
+  return !ok;
+}
+
+int test__comparedf2(int line, uint64_t a_rep, uint64_t b_rep, enum Result result) {
+  double a = fromRep64(a_rep), b = fromRep64(b_rep);
+
+  int eq = __eqdf2(a, b);
+  int ne = __nedf2(a, b);
+  int ge = __gedf2(a, b);
+  int gt = __gtdf2(a, b);
+  int le = __ledf2(a, b);
+  int lt = __ltdf2(a, b);
+  int cmp = __cmpdf2(a, b);
+  int unord = __unorddf2(a, b);
+
+  int ret = 0;
+
+  switch (result) {
+  case RESULT_LT:
+    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0");
+    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt < 0, "< 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == -1, "== -1");
+    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0");
+    break;
+  case RESULT_GT:
+    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt > 0, "> 0");
+    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le > 0, "> 0");
+    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1");
+    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0");
+    break;
+  case RESULT_EQ:
+    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq == 0, "== 0");
+    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne == 0, "== 0");
+    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 0, "== 0");
+    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0");
+    break;
+  case RESULT_UN:
+    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0");
+    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le > 0, "> 0");
+    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1");
+    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 1, "== 1");
+    break;
+  }
+
+  return ret;
+}
+
+#define test__comparedf2(a,b,x) test__comparedf2(__LINE__,a,b,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__comparedf2(0x0000000000000000, 0x0000000000000001, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000000, 0x000fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000000, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000000, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000000, 0x7ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000000, 0x7ff00000a5a42e09, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000000, 0x7ffcd5b95f9b89ae, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000000, 0x7ffcd5b95f9b89ae, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000000, 0x8000000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x0000000000000000, 0x8000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000000, 0x800fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000000, 0x8010000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000000, 0xfff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000000, 0xfff00000a5a42e09, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000000, 0xfffcd5b95f9b89ae, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000000, 0xfffcd5b95f9b89ae, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000001, 0x0000000000000001, RESULT_EQ);
+  status |= test__comparedf2(0x0000000000000001, 0x3fefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x3ffffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x3fffffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x7fdfffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x7feffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x7fefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000001, 0x7ff00000887bcf03, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000001, 0x7ff753b1887bcf03, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000001, 0x7ffc3134b058fe20, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000001, 0x8000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xbfefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xbffffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xbfffffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xffdfffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xffeffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xffefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000001, 0xfff00000887bcf03, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000001, 0xfff753b1887bcf03, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000001, 0xfffc3134b058fe20, RESULT_UN);
+  status |= test__comparedf2(0x0000000000000002, 0x0000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000003, 0x0000000000000002, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000003, 0x4008000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000003, 0x4014000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000003, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0000000000000003, 0xc014000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000003, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0000000000000004, 0x0000000000000004, RESULT_EQ);
+  status |= test__comparedf2(0x000ffffffffffffc, 0x800ffffffffffffc, RESULT_GT);
+  status |= test__comparedf2(0x000ffffffffffffd, 0x000ffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0x000fffffffffffff, 0x0000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x000fffffffffffff, 0x000ffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x000fffffffffffff, 0x000fffffffffffff, RESULT_EQ);
+  status |= test__comparedf2(0x000fffffffffffff, 0x0010000000000000, RESULT_LT);
+  status |= test__comparedf2(0x000fffffffffffff, 0x7ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x000fffffffffffff, 0x7ff00000dfe15ee3, RESULT_UN);
+  status |= test__comparedf2(0x000fffffffffffff, 0x7ff6d1ebdfe15ee3, RESULT_UN);
+  status |= test__comparedf2(0x000fffffffffffff, 0x7ffed0664505a878, RESULT_UN);
+  status |= test__comparedf2(0x000fffffffffffff, 0x8000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x000fffffffffffff, 0xfff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x000fffffffffffff, 0xfff00000dfe15ee3, RESULT_UN);
+  status |= test__comparedf2(0x000fffffffffffff, 0xfff6d1ebdfe15ee3, RESULT_UN);
+  status |= test__comparedf2(0x000fffffffffffff, 0xfffed0664505a878, RESULT_UN);
+  status |= test__comparedf2(0x0010000000000000, 0x0000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0010000000000000, 0x0010000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x0010000000000000, 0x8010000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0010000000000001, 0x0010000000000000, RESULT_GT);
+  status |= test__comparedf2(0x0010000000000001, 0x0010000000000002, RESULT_LT);
+  status |= test__comparedf2(0x001fffffffffffff, 0x0020000000000000, RESULT_LT);
+  status |= test__comparedf2(0x001fffffffffffff, 0x0020000000000002, RESULT_LT);
+  status |= test__comparedf2(0x001fffffffffffff, 0x0020000000000004, RESULT_LT);
+  status |= test__comparedf2(0x0020000000000000, 0x001fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0020000000000001, 0x0010000000000001, RESULT_GT);
+  status |= test__comparedf2(0x0020000000000001, 0x001fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0020000000000002, 0x0010000000000001, RESULT_GT);
+  status |= test__comparedf2(0x002fffffffffffff, 0x0030000000000000, RESULT_LT);
+  status |= test__comparedf2(0x0030000000000000, 0x002fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0030000000000001, 0x002fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x0030000000000002, 0x0020000000000003, RESULT_GT);
+  status |= test__comparedf2(0x3fe0000000000000, 0x3fe0000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x3fefffffffffffff, 0x0000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x3fefffffffffffff, 0x8000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x3ff0000000000000, 0x3ff0000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x3ff0000000000000, 0x3ff0000000000003, RESULT_LT);
+  status |= test__comparedf2(0x3ff0000000000000, 0x4000000000000000, RESULT_LT);
+  status |= test__comparedf2(0x3ff0000000000000, 0x401c000000000000, RESULT_LT);
+  status |= test__comparedf2(0x3ff0000000000000, 0x7ff0000033022725, RESULT_UN);
+  status |= test__comparedf2(0x3ff0000000000000, 0x7ff4f5ad33022725, RESULT_UN);
+  status |= test__comparedf2(0x3ff0000000000000, 0x7ffd3870667efc9d, RESULT_UN);
+  status |= test__comparedf2(0x3ff0000000000000, 0x8000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x3ff0000000000000, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x3ff0000000000000, 0xbff0000000000003, RESULT_GT);
+  status |= test__comparedf2(0x3ff0000000000000, 0xfff0000033022725, RESULT_UN);
+  status |= test__comparedf2(0x3ff0000000000000, 0xfff4f5ad33022725, RESULT_UN);
+  status |= test__comparedf2(0x3ff0000000000000, 0xfffd3870667efc9d, RESULT_UN);
+  status |= test__comparedf2(0x3ff0000000000001, 0x3ff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x3ff0000000000001, 0x3ff0000000000002, RESULT_LT);
+  status |= test__comparedf2(0x3ff0000000000001, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x3ffffffffffffffc, 0x3ffffffffffffffd, RESULT_LT);
+  status |= test__comparedf2(0x3fffffffffffffff, 0x0000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x3fffffffffffffff, 0x4000000000000000, RESULT_LT);
+  status |= test__comparedf2(0x4000000000000000, 0x3ff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000000, 0x3fffffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000000, 0x4000000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x4000000000000000, 0x4000000000000001, RESULT_LT);
+  status |= test__comparedf2(0x4000000000000000, 0xc000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000000, 0xc000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000000, 0xc014000000000000, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000001, 0x3ff0000000000001, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000001, 0x4000000000000002, RESULT_LT);
+  status |= test__comparedf2(0x4000000000000001, 0xc000000000000002, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000002, 0x3ff0000000000001, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000002, 0x3ff0000000000003, RESULT_GT);
+  status |= test__comparedf2(0x4000000000000004, 0x4000000000000003, RESULT_GT);
+  status |= test__comparedf2(0x4008000000000000, 0x4008000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x400fffffffffffff, 0x400ffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x400fffffffffffff, 0x4010000000000002, RESULT_LT);
+  status |= test__comparedf2(0x4010000000000001, 0x400fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x4014000000000000, 0x0000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x4014000000000000, 0x8000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x4014000000000000, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x4014000000000000, 0xc014000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fb0000000000001, 0x7fafffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7fcfffffffffffff, 0x7fcffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x7fcfffffffffffff, 0x7fd0000000000002, RESULT_LT);
+  status |= test__comparedf2(0x7fd0000000000000, 0x7fcfffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7fd0000000000000, 0x7fd0000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x7fd0000000000000, 0x7fd0000000000001, RESULT_LT);
+  status |= test__comparedf2(0x7fd0000000000001, 0x7fd0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fd0000000000001, 0x7fe0000000000001, RESULT_LT);
+  status |= test__comparedf2(0x7fd0000000000001, 0xffd0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fd0000000000002, 0x7fc0000000000003, RESULT_GT);
+  status |= test__comparedf2(0x7fd0000000000004, 0x7fd0000000000003, RESULT_GT);
+  status |= test__comparedf2(0x7fdffffffffffffe, 0x7fdffffffffffffe, RESULT_EQ);
+  status |= test__comparedf2(0x7fdffffffffffffe, 0x7fdfffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x7fdffffffffffffe, 0xffdfffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7fdfffffffffffff, 0x3ff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fdfffffffffffff, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x7fdfffffffffffff, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fdfffffffffffff, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fe0000000000000, 0x3ff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fe0000000000000, 0x7fe0000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x7fe0000000000000, 0x7ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x7fe0000000000000, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fe0000000000000, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fe0000000000000, 0xfff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fe0000000000001, 0x7fe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fe0000000000001, 0x7fe0000000000002, RESULT_LT);
+  status |= test__comparedf2(0x7fe0000000000001, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fe0000000000002, 0x7fd0000000000001, RESULT_GT);
+  status |= test__comparedf2(0x7feffffffffffffe, 0x3ff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7feffffffffffffe, 0x7fefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x7feffffffffffffe, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7feffffffffffffe, 0xffefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7fefffffffffffff, 0x0000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x7fefffffffffffff, 0x3ff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fefffffffffffff, 0x7fefffffffffffff, RESULT_EQ);
+  status |= test__comparedf2(0x7fefffffffffffff, 0x7ff00000c901461b, RESULT_UN);
+  status |= test__comparedf2(0x7fefffffffffffff, 0x7ff784a9c901461b, RESULT_UN);
+  status |= test__comparedf2(0x7fefffffffffffff, 0x7ffe2c1db2e4a313, RESULT_UN);
+  status |= test__comparedf2(0x7fefffffffffffff, 0x8000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x7fefffffffffffff, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7fefffffffffffff, 0xfff00000c901461b, RESULT_UN);
+  status |= test__comparedf2(0x7fefffffffffffff, 0xfff784a9c901461b, RESULT_UN);
+  status |= test__comparedf2(0x7fefffffffffffff, 0xfffe2c1db2e4a313, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000000000000, 0x0000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0x0000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0x000fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0x7fe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0x7fefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0x7ff0000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x7ff0000000000000, 0x7ff0e6d059ac9171, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000000000000, 0x7ffbda2fc9024ae6, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000000000000, 0x8000000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0x8000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0x800fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0xffefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000000000000, 0xfff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x7ff0000047e8b9a0, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff4017647e8b9a0, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000abfe5d29, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ff2a1cdabfe5d29, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ff000005155db76, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff645cb5155db76, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000070c46aa0, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff2068470c46aa0, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000b5aee637, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff72b19b5aee637, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000c08c2788, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff1e0c1c08c2788, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000ec581a54, 0x7ff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000ec581a54, 0x7ff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff571eaec581a54, 0x7ff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff571eaec581a54, 0x7ff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff000003a3a1f94, 0x7ff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff000003a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff6439e3a3a1f94, 0x7ff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff6439e3a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000ec581a54, 0xfff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000ec581a54, 0xfff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff571eaec581a54, 0xfff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff571eaec581a54, 0xfff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0x7ff000003a3a1f94, 0xfff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff000003a3a1f94, 0xfffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff6439e3a3a1f94, 0xfff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff6439e3a3a1f94, 0xfffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000c31d528e, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff5fb72c31d528e, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000ac81d215, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ff4481aac81d215, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000d12062fd, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff707f6d12062fd, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff000001c6481ef, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff66ee91c6481ef, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000985729a7, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff19cff985729a7, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000053ec80fe, 0xfff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff7dbc153ec80fe, 0xfff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000816fb493, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff87f75816fb493, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff000000c2d7c33, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ff91ecb0c2d7c33, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000a68bae40, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ffc0acda68bae40, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff000002fe14961, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ffcfa4e2fe14961, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff000005c206da1, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff800bb5c206da1, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000051887a34, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ffce11951887a34, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff000002b4c32a8, 0x7ff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ff000002b4c32a8, 0x7ff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0x7ff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0x7ff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000bc88c2a9, 0x7ff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000bc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0x7ff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff000002b4c32a8, 0xfff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ff000002b4c32a8, 0xfff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0xfff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0xfff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000bc88c2a9, 0xfff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000bc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0xfff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000a47525ca, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ffcb028a47525ca, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000097c1af12, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ffc541e97c1af12, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000bb1c07a4, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff966b7bb1c07a4, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff000001d98f07c, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff9dbf61d98f07c, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff0000040e65504, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ffb2a7440e65504, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0x7ff00000d9dc7412, 0xfff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x7ff8af62d9dc7412, 0xfff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000000, 0x0000000000000000, RESULT_EQ);
+  status |= test__comparedf2(0x8000000000000000, 0x0000000000000001, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000000, 0x000fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000000, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000000, 0x7ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000000, 0x7ff000005a0faea3, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000000, 0x7ff225cc5a0faea3, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000000, 0x7ffa0cc436ad9daa, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000000, 0x8000000000000001, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000000, 0x800fffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000000, 0x8010000000000000, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000000, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000000, 0xfff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000000, 0xfff000005a0faea3, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000000, 0xfff225cc5a0faea3, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000000, 0xfffa0cc436ad9daa, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000001, 0x0000000000000001, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x3fefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x3ffffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x3fffffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x7fdfffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x7feffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x7fefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000001, 0x7ff0000013fd5944, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000001, 0x7ff4154313fd5944, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000001, 0x7ffd397ba0f9b5e1, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000001, 0x8000000000000001, RESULT_EQ);
+  status |= test__comparedf2(0x8000000000000001, 0xbfefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xbff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xbffffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xbfffffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xffdfffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xffeffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xffefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000001, 0xfff0000013fd5944, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000001, 0xfff4154313fd5944, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000001, 0xfffd397ba0f9b5e1, RESULT_UN);
+  status |= test__comparedf2(0x8000000000000002, 0x8000000000000001, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000003, 0x4008000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000003, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000003, 0x8000000000000002, RESULT_LT);
+  status |= test__comparedf2(0x8000000000000003, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x8000000000000004, 0x8000000000000004, RESULT_EQ);
+  status |= test__comparedf2(0x800ffffffffffffd, 0x800ffffffffffffe, RESULT_GT);
+  status |= test__comparedf2(0x800fffffffffffff, 0x0000000000000000, RESULT_LT);
+  status |= test__comparedf2(0x800fffffffffffff, 0x000fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x800fffffffffffff, 0x7ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0x800fffffffffffff, 0x7ff00000a2b85efa, RESULT_UN);
+  status |= test__comparedf2(0x800fffffffffffff, 0x7ff1d4fba2b85efa, RESULT_UN);
+  status |= test__comparedf2(0x800fffffffffffff, 0x7ffd08c114a37fe6, RESULT_UN);
+  status |= test__comparedf2(0x800fffffffffffff, 0x8000000000000000, RESULT_LT);
+  status |= test__comparedf2(0x800fffffffffffff, 0x800ffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0x800fffffffffffff, 0x800fffffffffffff, RESULT_EQ);
+  status |= test__comparedf2(0x800fffffffffffff, 0x8010000000000000, RESULT_GT);
+  status |= test__comparedf2(0x800fffffffffffff, 0xfff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0x800fffffffffffff, 0xfff00000a2b85efa, RESULT_UN);
+  status |= test__comparedf2(0x800fffffffffffff, 0xfff1d4fba2b85efa, RESULT_UN);
+  status |= test__comparedf2(0x800fffffffffffff, 0xfffd08c114a37fe6, RESULT_UN);
+  status |= test__comparedf2(0x8010000000000000, 0x0000000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8010000000000000, 0x0010000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8010000000000001, 0x8010000000000000, RESULT_LT);
+  status |= test__comparedf2(0x8010000000000001, 0x8010000000000002, RESULT_GT);
+  status |= test__comparedf2(0x801fffffffffffff, 0x8020000000000000, RESULT_GT);
+  status |= test__comparedf2(0x801fffffffffffff, 0x8020000000000002, RESULT_GT);
+  status |= test__comparedf2(0x801fffffffffffff, 0x8020000000000004, RESULT_GT);
+  status |= test__comparedf2(0x8020000000000000, 0x801fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8020000000000001, 0x8010000000000001, RESULT_LT);
+  status |= test__comparedf2(0x8020000000000001, 0x801fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8020000000000002, 0x8010000000000001, RESULT_LT);
+  status |= test__comparedf2(0x802fffffffffffff, 0x8030000000000000, RESULT_GT);
+  status |= test__comparedf2(0x8030000000000000, 0x802fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8030000000000001, 0x802fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0x8030000000000002, 0x8020000000000003, RESULT_LT);
+  status |= test__comparedf2(0xbff0000000000000, 0x3ff0000000000003, RESULT_LT);
+  status |= test__comparedf2(0xbff0000000000000, 0x7ff000000d32ab76, RESULT_UN);
+  status |= test__comparedf2(0xbff0000000000000, 0x7ff3d46c0d32ab76, RESULT_UN);
+  status |= test__comparedf2(0xbff0000000000000, 0x7ffb51e7ffa1e86b, RESULT_UN);
+  status |= test__comparedf2(0xbff0000000000000, 0x8000000000000000, RESULT_LT);
+  status |= test__comparedf2(0xbff0000000000000, 0xbff0000000000003, RESULT_GT);
+  status |= test__comparedf2(0xbff0000000000000, 0xfff000000d32ab76, RESULT_UN);
+  status |= test__comparedf2(0xbff0000000000000, 0xfff3d46c0d32ab76, RESULT_UN);
+  status |= test__comparedf2(0xbff0000000000000, 0xfffb51e7ffa1e86b, RESULT_UN);
+  status |= test__comparedf2(0xbff0000000000001, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xbff0000000000001, 0xbff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xbff0000000000001, 0xbff0000000000002, RESULT_GT);
+  status |= test__comparedf2(0xbffffffffffffffc, 0xbffffffffffffffd, RESULT_GT);
+  status |= test__comparedf2(0xbfffffffffffffff, 0x0000000000000001, RESULT_LT);
+  status |= test__comparedf2(0xbfffffffffffffff, 0xc000000000000000, RESULT_GT);
+  status |= test__comparedf2(0xc000000000000000, 0x4000000000000001, RESULT_LT);
+  status |= test__comparedf2(0xc000000000000000, 0xbfffffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xc000000000000000, 0xc000000000000001, RESULT_GT);
+  status |= test__comparedf2(0xc000000000000001, 0x4000000000000002, RESULT_LT);
+  status |= test__comparedf2(0xc000000000000001, 0xbff0000000000001, RESULT_LT);
+  status |= test__comparedf2(0xc000000000000001, 0xc000000000000002, RESULT_GT);
+  status |= test__comparedf2(0xc000000000000002, 0xbff0000000000001, RESULT_LT);
+  status |= test__comparedf2(0xc000000000000002, 0xbff0000000000003, RESULT_LT);
+  status |= test__comparedf2(0xc000000000000004, 0xc000000000000003, RESULT_LT);
+  status |= test__comparedf2(0xc008000000000000, 0x4008000000000000, RESULT_LT);
+  status |= test__comparedf2(0xc00fffffffffffff, 0xc00ffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0xc00fffffffffffff, 0xc010000000000002, RESULT_GT);
+  status |= test__comparedf2(0xc010000000000001, 0xc00fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xffb0000000000001, 0xffafffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xffcfffffffffffff, 0xffcffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0xffcfffffffffffff, 0xffd0000000000002, RESULT_GT);
+  status |= test__comparedf2(0xffd0000000000000, 0xffcfffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xffd0000000000000, 0xffd0000000000001, RESULT_GT);
+  status |= test__comparedf2(0xffd0000000000001, 0x7fd0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffd0000000000001, 0xffd0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffd0000000000001, 0xffe0000000000001, RESULT_GT);
+  status |= test__comparedf2(0xffd0000000000002, 0xffc0000000000003, RESULT_LT);
+  status |= test__comparedf2(0xffd0000000000004, 0xffd0000000000003, RESULT_LT);
+  status |= test__comparedf2(0xffdffffffffffffe, 0x7fdffffffffffffe, RESULT_LT);
+  status |= test__comparedf2(0xffdffffffffffffe, 0x7fdfffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xffdffffffffffffe, 0xffdffffffffffffe, RESULT_EQ);
+  status |= test__comparedf2(0xffdffffffffffffe, 0xffdfffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0xffdfffffffffffff, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffdfffffffffffff, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffdfffffffffffff, 0xbff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffdfffffffffffff, 0xffe0000000000000, RESULT_GT);
+  status |= test__comparedf2(0xffe0000000000000, 0x0000000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffe0000000000000, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffe0000000000000, 0x7ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffe0000000000000, 0x8000000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffe0000000000000, 0xbff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffe0000000000000, 0xffe0000000000000, RESULT_EQ);
+  status |= test__comparedf2(0xffe0000000000000, 0xfff0000000000000, RESULT_GT);
+  status |= test__comparedf2(0xffe0000000000001, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffe0000000000001, 0xffe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffe0000000000001, 0xffe0000000000002, RESULT_GT);
+  status |= test__comparedf2(0xffe0000000000002, 0xffd0000000000001, RESULT_LT);
+  status |= test__comparedf2(0xffeffffffffffffe, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffeffffffffffffe, 0x7fefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xffeffffffffffffe, 0xbff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffeffffffffffffe, 0xffefffffffffffff, RESULT_GT);
+  status |= test__comparedf2(0xffefffffffffffff, 0x0000000000000001, RESULT_LT);
+  status |= test__comparedf2(0xffefffffffffffff, 0x3ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffefffffffffffff, 0x7ff000007d4a42a6, RESULT_UN);
+  status |= test__comparedf2(0xffefffffffffffff, 0x7ff7252c7d4a42a6, RESULT_UN);
+  status |= test__comparedf2(0xffefffffffffffff, 0x7ff980ec6115c6fb, RESULT_UN);
+  status |= test__comparedf2(0xffefffffffffffff, 0x8000000000000001, RESULT_LT);
+  status |= test__comparedf2(0xffefffffffffffff, 0xbff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xffefffffffffffff, 0xffefffffffffffff, RESULT_EQ);
+  status |= test__comparedf2(0xffefffffffffffff, 0xfff000007d4a42a6, RESULT_UN);
+  status |= test__comparedf2(0xffefffffffffffff, 0xfff7252c7d4a42a6, RESULT_UN);
+  status |= test__comparedf2(0xffefffffffffffff, 0xfff980ec6115c6fb, RESULT_UN);
+  status |= test__comparedf2(0xfff0000000000000, 0x0000000000000000, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x0000000000000001, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x000fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x7fe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x7fefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x7ff0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x7ff00000578bbe24, RESULT_UN);
+  status |= test__comparedf2(0xfff0000000000000, 0x7ff63d54578bbe24, RESULT_UN);
+  status |= test__comparedf2(0xfff0000000000000, 0x7ffbc66614390083, RESULT_UN);
+  status |= test__comparedf2(0xfff0000000000000, 0x8000000000000000, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x8000000000000001, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0x800fffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0xffe0000000000000, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0xffefffffffffffff, RESULT_LT);
+  status |= test__comparedf2(0xfff0000000000000, 0xfff0000000000000, RESULT_EQ);
+  status |= test__comparedf2(0xfff0000000000000, 0xfff00000578bbe24, RESULT_UN);
+  status |= test__comparedf2(0xfff0000000000000, 0xfff63d54578bbe24, RESULT_UN);
+  status |= test__comparedf2(0xfff0000000000000, 0xfffbc66614390083, RESULT_UN);
+  status |= test__comparedf2(0xfff0000047e8b9a0, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff4017647e8b9a0, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff00000abfe5d29, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfff2a1cdabfe5d29, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfff000005155db76, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff645cb5155db76, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff0000070c46aa0, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff2068470c46aa0, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff00000b5aee637, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff72b19b5aee637, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff00000c08c2788, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff1e0c1c08c2788, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff00000ec581a54, 0x7ff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff00000ec581a54, 0x7ff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff571eaec581a54, 0x7ff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff571eaec581a54, 0x7ff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff000003a3a1f94, 0x7ff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff000003a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff6439e3a3a1f94, 0x7ff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff6439e3a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff00000ec581a54, 0xfff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff00000ec581a54, 0xfff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff571eaec581a54, 0xfff0000021ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff571eaec581a54, 0xfff45d2221ebdfaf, RESULT_UN);
+  status |= test__comparedf2(0xfff000003a3a1f94, 0xfff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff000003a3a1f94, 0xfffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff6439e3a3a1f94, 0xfff00000229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff6439e3a3a1f94, 0xfffb8fa0229f3502, RESULT_UN);
+  status |= test__comparedf2(0xfff00000c31d528e, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff5fb72c31d528e, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff00000ac81d215, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfff4481aac81d215, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfff00000d12062fd, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff707f6d12062fd, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff000001c6481ef, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff66ee91c6481ef, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff00000985729a7, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff19cff985729a7, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff0000053ec80fe, 0xfff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff7dbc153ec80fe, 0xfff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff00000816fb493, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff87f75816fb493, 0x0000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff000000c2d7c33, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfff91ecb0c2d7c33, 0x0000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfff00000a68bae40, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfffc0acda68bae40, 0x000fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff000002fe14961, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfffcfa4e2fe14961, 0x3ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff000005c206da1, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff800bb5c206da1, 0x7fefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff0000051887a34, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfffce11951887a34, 0x7ff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff000002b4c32a8, 0x7ff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfff000002b4c32a8, 0x7ff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfffbd6b52b4c32a8, 0x7ff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfffbd6b52b4c32a8, 0x7ff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfff00000bc88c2a9, 0x7ff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff00000bc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff8eaadbc88c2a9, 0x7ff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff8eaadbc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff000002b4c32a8, 0xfff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfff000002b4c32a8, 0xfff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfffbd6b52b4c32a8, 0xfff000001edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfffbd6b52b4c32a8, 0xfff342ea1edb8786, RESULT_UN);
+  status |= test__comparedf2(0xfff00000bc88c2a9, 0xfff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff00000bc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff8eaadbc88c2a9, 0xfff000002fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff8eaadbc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN);
+  status |= test__comparedf2(0xfff00000a47525ca, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfffcb028a47525ca, 0x8000000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff0000097c1af12, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfffc541e97c1af12, 0x8000000000000001, RESULT_UN);
+  status |= test__comparedf2(0xfff00000bb1c07a4, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff966b7bb1c07a4, 0x800fffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff000001d98f07c, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff9dbf61d98f07c, 0xbff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff0000040e65504, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfffb2a7440e65504, 0xffefffffffffffff, RESULT_UN);
+  status |= test__comparedf2(0xfff00000d9dc7412, 0xfff0000000000000, RESULT_UN);
+  status |= test__comparedf2(0xfff8af62d9dc7412, 0xfff0000000000000, RESULT_UN);
+
+  return status;
+}

>From 017a0e3bac60a714ef6923eead584a91eebbf2a1 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 16:10:11 +0000
Subject: [PATCH 07/33] [compiler-rt][ARM] Optimized single-precision FP
 comparisons

These comparison functions follow the same structure as the
double-precision ones in a prior commit, of a header file containing
the main logic and some entry points varying the construction of the
return value.

In this case, we have provided versions for Thumb1 as well as
Arm/Thumb2.
---
 compiler-rt/lib/builtins/CMakeLists.txt       |   9 +
 compiler-rt/lib/builtins/arm/cmpsf2.S         |  56 +++
 compiler-rt/lib/builtins/arm/fcmp.h           | 174 +++++++
 compiler-rt/lib/builtins/arm/gesf2.S          |  54 +++
 compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S  |  55 +++
 compiler-rt/lib/builtins/arm/thumb1/fcmp.h    | 191 ++++++++
 compiler-rt/lib/builtins/arm/thumb1/gesf2.S   |  54 +++
 .../lib/builtins/arm/thumb1/unordsf2.S        |  49 ++
 compiler-rt/lib/builtins/arm/unordsf2.S       |  56 +++
 .../test/builtins/Unit/comparesf2new_test.c   | 433 ++++++++++++++++++
 10 files changed, 1131 insertions(+)
 create mode 100644 compiler-rt/lib/builtins/arm/cmpsf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/fcmp.h
 create mode 100644 compiler-rt/lib/builtins/arm/gesf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/fcmp.h
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/gesf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/thumb1/unordsf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/unordsf2.S
 create mode 100644 compiler-rt/test/builtins/Unit/comparesf2new_test.c

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 0e8b0fa553442..0c53781a51392 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -451,8 +451,11 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm")
       arm/muldf3.S
       arm/divdf3.S
       arm/cmpdf2.S
+      arm/cmpsf2.S
       arm/gedf2.S
+      arm/gesf2.S
       arm/unorddf2.S
+      arm/unordsf2.S
       )
     set_source_files_properties(${assembly_files}
       PROPERTIES COMPILE_OPTIONS ${implicit_it_flag})
@@ -507,8 +510,11 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP)
   set(thumb1_base_SOURCES
     arm/thumb1/mulsf3.S
     arm/thumb1/cmpdf2.S
+    arm/thumb1/cmpsf2.S
     arm/thumb1/gedf2.S
+    arm/thumb1/gesf2.S
     arm/thumb1/unorddf2.S
+    arm/thumb1/unordsf2.S
     arm/fnan2.c
     arm/fnorm2.c
     arm/funder.c
@@ -516,6 +522,9 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP)
   )
   set_property(SOURCE arm/thumb1/cmpdf2.S PROPERTY crt_supersedes comparedf2.c)
   set_property(SOURCE arm/thumb1/cmpdf2.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY crt_provides comparedf2)
+  set_property(SOURCE arm/thumb1/cmpsf2.S PROPERTY crt_supersedes comparesf2.S)
+  # We don't need to set 'crt_provides' for cmpsf2.S, because the
+  # superseded comparesf2.S will already have enabled the comparesf2 tests.
 endif()
 
 set(arm_EABI_RT_SOURCES
diff --git a/compiler-rt/lib/builtins/arm/cmpsf2.S b/compiler-rt/lib/builtins/arm/cmpsf2.S
new file mode 100644
index 0000000000000..14166246101af
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/cmpsf2.S
@@ -0,0 +1,56 @@
+//===-- cmpsf2.S - single-precision floating point comparison -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpsf2: it's a three-way compare
+// which returns <0 if x<y, 0 if x==y, and >0 if x>y. If the result is
+// unordered (i.e. x or y or both is NaN) then it returns >0.
+//
+// This also makes it suitable for use as all of __eqsf2, __nesf2, __ltsf2 or
+// __lesf2.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+op0 .req r0
+op1 .req r1
+.macro SetReturnRegister
+  mov r0, #0
+  movhi r0, #1
+  movlo r0, #-1
+.endm
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__cmpsf2)
+  push {r4, lr}
+  vmov r0, s0
+  vmov r1, s1
+  bl __compiler_rt_softfp_cmpsf2
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpsf2, __compiler_rt_softfp_cmpsf2)
+#endif
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __cmpsf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __cmpsf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__eqsf2, __cmpsf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __cmpsf2)
+
+DEFINE_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpsf2)
+  #include "fcmp.h"
+
+LOCAL_LABEL(NaN):
+  mov r0, #+1
+  bx lr
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpsf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fcmp.h b/compiler-rt/lib/builtins/arm/fcmp.h
new file mode 100644
index 0000000000000..23bdd73a10c5b
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fcmp.h
@@ -0,0 +1,174 @@
+//===-- fcmp.h - shared code for single-precision FP comparison functions -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This code is the skeleton of a double-precision FP compare, with two details
+// left out: which input value is in which register, and how to make the return
+// value. It allows the main comparison logic to be shared between (for
+// example) __lesf2 and __gesf2, varying only those details.
+//
+//===----------------------------------------------------------------------===//
+
+// How to use this header file:
+//
+// This header file is expected to be #included from inside a function
+// definition in a .S file. The source file including this header should
+// provide the following:
+//
+// op0 and op1: register aliases (via .req) for the registers containing the
+// input operands.
+//  - For most comparisons, op0 will correspond to r0 and op1 to r1.
+//  - But a function with the reversed semantics of __aeabi_cfrcmple wil define
+//    them the other way round.
+//
+// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up
+// an appropriate return value in r0, for the cases that do *not* involve NaN.
+//  - On entry to this macro, the condition codes LO, EQ and HI indicate that
+//    op0 < op1, op0 == op1 or op0 > op1 respectively.
+//  - For functions that return a result in the flags, this macro can be empty,
+//    because those are the correct flags to return anyway.
+//  - Functions that return a boolean in r0 should set it up by checking the
+//    flags.
+//
+// LOCAL_LABEL(NaN): a label defined within the compare function, after the
+// #include of this header. Called when at least one input is a NaN, and sets
+// up the appropriate return value for that case.
+
+// --------------------------------------------------
+// The actual entry point of the compare function.
+//
+// The basic plan is to start by ORing together the two inputs. This tells us
+// two things:
+//  - the top bit of the output tells us whether both inputs are positive, or
+//    whether at least one is negative
+//  - if the 8 exponent bits of the output are not all 1, then there are
+//    definitely no NaNs, so a fast path can handle most non-NaN cases.
+
+  // First diverge control for the negative-numbers case.
+  orrs    r12, op0, op1
+  bmi     LOCAL_LABEL(negative)         // high bit set => at least one negative input
+
+  // Here, both inputs are positive. Try adding 1<<23 to their bitwise OR in
+  // r12. This will carry all the way into the top bit, setting the N flag, if
+  // all 8 exponent bits were set.
+  cmn     r12, #1 << 23
+  bmi     LOCAL_LABEL(NaNInf_check_positive) // need to look harder for NaNs
+
+  // The fastest fast path: both inputs positive and we could easily tell there
+  // were no NaNs. So we just compare op0 and op1 as unsigned integers.
+  cmp     op0, op1
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaNInf_check_positive):
+  // Second tier for positive numbers. We come here if both inputs are
+  // positive, but our fast initial check didn't manage to rule out a NaN. But
+  // it's not guaranteed that there _is_ a NaN, for two reasons:
+  //
+  //  1. An input with exponent 0xFF might be an infinity instead. Those behave
+  //    normally under comparison.
+  //
+  //  2. There might not even _be_ an input with exponent 0xFF. All we know so
+  //     far is that the two inputs ORed together had all the exponent bits
+  //     set. So each of those bits is set in _at least one_ of the inputs, but
+  //     not necessarily all in the _same_ input.
+  //
+  // Test each exponent individually for 0xFF, using the same CMN idiom as
+  // above. If neither one carries into the sign bit then we have no NaNs _or_
+  // infinities and can compare the registers and return again.
+  cmn     op0, #1 << 23
+  cmnpl   op1, #1 << 23
+  bmi     LOCAL_LABEL(NaN_check_positive)
+
+  // Second-tier return path, now we've ruled out anything difficult.
+  cmp     op0, op1
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaN_check_positive):
+  // Third tier for positive numbers. Here we know that at least one of the
+  // inputs has exponent 0xFF. But they might still be infinities rather than
+  // NaNs. So now we must check whether there's an actual NaN, by shifting each
+  // input left to get rid of the sign bit, and seeing if the result is
+  // _greater_ than 0xFF000000 (but not equal).
+  //
+  // We could have skipped the second-tier check and done this more rigorous
+  // test immediately. But that would cost an extra instruction in the case
+  // where there are no infinities or NaNs, and we assume that that is so much
+  // more common that it's worth optimizing for.
+  mov     r12, #0xFF << 24
+  cmp     r12, op0, LSL #1   // if LO, then r12 < (op0 << 1), so op0 is a NaN
+  cmphs   r12, op1, LSL #1   // if not LO, then do the same check for op1
+  blo     LOCAL_LABEL(NaN)           // now, if LO, there's definitely a NaN
+
+  // Now we've finally ruled out NaNs! And we still know both inputs are
+  // positive. So the third-tier return path can just compare the numbers
+  // again.
+  cmp     op0, op1
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(negative):
+  // We come here if at least one operand is negative. We haven't checked for
+  // NaNs at all yet (the sign check came first), so repeat the first-tier
+  // check strategy of seeing if all exponent bits are set in r12.
+  //
+  // On this path, the sign bit in r12 is set, so if adding 1 to the low
+  // exponent bit carries all the way through into the sign bit, it will
+  // _clear_ the sign bit rather than setting it. So we expect MI to be the
+  // "definitely no NaNs" result, where it was PL on the positive branch.
+  cmn     r12, #1 << 23
+  bpl     LOCAL_LABEL(NaNInf_check_negative)
+
+  // Now we have no NaNs, but at least one negative number. This gives us two
+  // complications:
+  //
+  //  1. Floating-point numbers are sign/magnitude, not two's complement, so we
+  //     have to consider separately the cases of "both negative" and "one of
+  //     each sign".
+  //
+  //  2. -0 and +0 are required to compare equal.
+  //
+  // But problem #1 is not as hard as it sounds! If both operands are negative,
+  // then we can get the result we want by comparing them as unsigned integers
+  // the opposite way round, because the input with the smaller value (as an
+  // integer) is the larger number in an FP ordering sense. And if one operand
+  // is negative and the other is positive, the _same_ reversed comparison
+  // works, because the positive number (with zero sign bit) will always
+  // compare less than the negative one in an unsigned-integers sense.
+  //
+  // So we only have to worry about problem #2, signed zeroes. This only
+  // affects the answer if _both_ operands are zero. And we can check that
+  // easily, because it happens if and only if r12 = 0x80000000. (We know r12
+  // has its sign bit set; if it has no other bits set, that's because both
+  // inputs were either 0x80000000 or 0x00000000.)
+  cmp     r12, #0x80000000        // EQ if both inputs are zero
+  cmpne   op1, op0                // otherwise, compare them backwards
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaNInf_check_negative):
+  // Second tier for negative numbers: we know the OR of the exponents is 0xFF,
+  // but again, we might not have either _actual_ exponent 0xFF, and also, an
+  // exponent 0xFF might be an infinity instead of a NaN.
+  //
+  // On this path we've already branched twice (once for negative numbers and
+  // once for the first-tier NaN check), so we'll just go straight to the
+  // precise check for NaNs.
+  mov     r12, #0xFF << 24
+  cmp     r12, op0, LSL #1   // if LO, then r12 < (op0 << 1), so op0 is a NaN
+  cmphs   r12, op1, LSL #1   // if not LO, then do the same check for op1
+  blo     LOCAL_LABEL(NaN)
+
+  // Now we've ruled out NaNs, so we can just compare the two input registers
+  // and return. On this path we _don't_ need to check for the special case of
+  // comparing two zeroes, because we only came here if the bitwise OR of the
+  // exponent fields was 0xFF, which means the exponents can't both have been
+  // zero! So we can _just_ do the reversed CMP and finish.
+  cmp     op1, op0
+  SetReturnRegister
+  bx      lr
diff --git a/compiler-rt/lib/builtins/arm/gesf2.S b/compiler-rt/lib/builtins/arm/gesf2.S
new file mode 100644
index 0000000000000..c149eea589f05
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/gesf2.S
@@ -0,0 +1,54 @@
+//===-- gesf2.S - single-precision floating point comparison --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpsf2, except for its NaN
+// handling. It's a three-way compare which returns <0 if x<y, 0 if x==y, and
+// >0 if x>y. If the result is unordered (i.e. x or y or both is NaN) then it
+// returns <0, where __cmpsf2 would return >0.
+//
+// This also makes it suitable for use as __gtsf2 or __gesf2 (or __eqsf2 or
+// __nesf2).
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+op0 .req r0
+op1 .req r1
+.macro SetReturnRegister
+  mov r0, #0
+  movhi r0, #1
+  movlo r0, #-1
+.endm
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__gesf2)
+  push {r4, lr}
+  vmov r0, s0
+  vmov r1, s1
+  bl __compiler_rt_softfp_gesf2
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __compiler_rt_softfp_gesf2)
+#endif
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gtsf2, __gesf2)
+
+DEFINE_COMPILERRT_FUNCTION(__compiler_rt_softfp_gesf2)
+  #include "fcmp.h"
+
+LOCAL_LABEL(NaN):
+  mov r0, #-1
+  bx lr
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_gesf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S b/compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S
new file mode 100644
index 0000000000000..c8611d1147366
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S
@@ -0,0 +1,55 @@
+//===-- cmpsf2.S - single-precision floating point comparison -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpsf2: it's a three-way compare
+// which returns <0 if x<y, 0 if x==y, and >0 if x>y. If the result is
+// unordered (i.e. x or y or both is NaN) then it returns >0.
+//
+// This also makes it suitable for use as all of __eqsf2, __nesf2, __ltsf2 or
+// __lesf2.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../assembly.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+op0 .req r0
+op1 .req r1
+.macro SetReturnRegister
+  bhi 0f
+  blo 1f
+  movs r0, #0
+  bx lr
+0:
+  movs r0, #1
+  bx lr
+1:
+  movs r0, #1
+  rsbs r0, r0, #0
+  bx lr
+.endm
+
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpsf2, __compiler_rt_softfp_cmpsf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __cmpsf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __cmpsf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__eqsf2, __cmpsf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __cmpsf2)
+
+DEFINE_COMPILERRT_THUMB_FUNCTION(__compiler_rt_softfp_cmpsf2)
+  #include "fcmp.h"
+
+LOCAL_LABEL(NaN):
+  movs r0, #1
+  bx lr
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpsf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/thumb1/fcmp.h b/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
new file mode 100644
index 0000000000000..bcfe928407e3c
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
@@ -0,0 +1,191 @@
+//===-- fcmp.h - shared code for single-precision FP comparison functions -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This code is the skeleton of a double-precision FP compare, with two details
+// left out: which input value is in which register, and how to make the return
+// value. It allows the main comparison logic to be shared between (for
+// example) __lesf2 and __gesf2, varying only those details.
+//
+//===----------------------------------------------------------------------===//
+
+// How to use this header file:
+//
+// This header file is expected to be #included from inside a function
+// definition in a .S file. The source file including this header should
+// provide the following:
+//
+// op0 and op1: register aliases (via .req) for the registers containing the
+// input operands.
+//  - For most comparisons, op0 will correspond to r0 and op1 to r1.
+//  - But a function with the reversed semantics of __aeabi_cfrcmple wil define
+//    them the other way round.
+//
+// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up
+// an appropriate return value in r0, for the cases that do *not* involve NaN.
+//  - On entry to this macro, the condition codes LO, EQ and HI indicate that
+//    op0 < op1, op0 == op1 or op0 > op1 respectively.
+//  - For functions that return a result in the flags, this macro can be empty,
+//    because those are the correct flags to return anyway.
+//  - Functions that return a boolean in r0 should set it up by checking the
+//    flags.
+//
+// LOCAL_LABEL(NaN): a label defined within the compare function, after the
+// #include of this header. Called when at least one input is a NaN, and sets
+// up the appropriate return value for that case.
+
+// --------------------------------------------------
+// The actual entry point of the compare function.
+//
+// The basic plan is to start by ORing together the two inputs. This tells us
+// two things:
+//  - the top bit of the output tells us whether both inputs are positive, or
+//    whether at least one is negative
+//  - if the 8 exponent bits of the output are not all 1, then there are
+//    definitely no NaNs, so a fast path can handle most non-NaN cases.
+
+  // Set up the constant 1 << 23 in a register, which we'll need on all
+  // branches.
+  movs    r3, #1
+  lsls    r3, r3, #23
+
+  // Diverge control for the negative-numbers case.
+  movs    r2, op0
+  orrs    r2, r2, op1
+  bmi     LOCAL_LABEL(negative)         // high bit set => at least one negative input
+
+  // Here, both inputs are positive. Try adding 1<<23 to their bitwise OR in
+  // r2. This will carry all the way into the top bit, setting the N flag, if
+  // all 8 exponent bits were set.
+  cmn     r2, r3
+  bmi     LOCAL_LABEL(NaNInf_check_positive) // need to look harder for NaNs
+
+  // The fastest fast path: both inputs positive and we could easily tell there
+  // were no NaNs. So we just compare op0 and op1 as unsigned integers.
+  cmp     op0, op1
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaNInf_check_positive):
+  // Second tier for positive numbers. We come here if both inputs are
+  // positive, but our fast initial check didn't manage to rule out a NaN. But
+  // it's not guaranteed that there _is_ a NaN, for two reasons:
+  //
+  //  1. An input with exponent 0xFF might be an infinity instead. Those behave
+  //    normally under comparison.
+  //
+  //  2. There might not even _be_ an input with exponent 0xFF. All we know so
+  //     far is that the two inputs ORed together had all the exponent bits
+  //     set. So each of those bits is set in _at least one_ of the inputs, but
+  //     not necessarily all in the _same_ input.
+  //
+  // Test each exponent individually for 0xFF, using the same CMN idiom as
+  // above. If neither one carries into the sign bit then we have no NaNs _or_
+  // infinities and can compare the registers and return again.
+  cmn     op0, r3
+  bmi     LOCAL_LABEL(NaN_check_positive)
+  cmn     op1, r3
+  bmi     LOCAL_LABEL(NaN_check_positive)
+
+  // Second-tier return path, now we've ruled out anything difficult.
+  cmp     op0, op1
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaN_check_positive):
+  // Third tier for positive numbers. Here we know that at least one of the
+  // inputs has exponent 0xFF. But they might still be infinities rather than
+  // NaNs. So now we must check whether there's an actual NaN, by shifting each
+  // input left to get rid of the sign bit, and seeing if the result is
+  // _greater_ than 0xFF000000 (but not equal).
+  //
+  // We could have skipped the second-tier check and done this more rigorous
+  // test immediately. But that would cost an extra instruction in the case
+  // where there are no infinities or NaNs, and we assume that that is so much
+  // more common that it's worth optimizing for.
+  movs    r2, #0xFF
+  lsls    r2, r2, #24
+  lsls    r3, op0, #1
+  cmp     r3, r2
+  bhi     LOCAL_LABEL(NaN)
+  lsls    r3, op1, #1
+  cmp     r3, r2
+  bhi     LOCAL_LABEL(NaN)
+
+  // Now we've finally ruled out NaNs! And we still know both inputs are
+  // positive. So the third-tier return path can just compare the numbers
+  // again.
+  cmp     op0, op1
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(negative):
+  // We come here if at least one operand is negative. We haven't checked for
+  // NaNs at all yet (the sign check came first), so repeat the first-tier
+  // check strategy of seeing if all exponent bits are set in r12.
+  //
+  // On this path, the sign bit in r12 is set, so if adding 1 to the low
+  // exponent bit carries all the way through into the sign bit, it will
+  // _clear_ the sign bit rather than setting it. So we expect MI to be the
+  // "definitely no NaNs" result, where it was PL on the positive branch.
+  cmn     r2, r3
+  bpl     LOCAL_LABEL(NaNInf_check_negative)
+
+  // Now we have no NaNs, but at least one negative number. This gives us two
+  // complications:
+  //
+  //  1. Floating-point numbers are sign/magnitude, not two's complement, so we
+  //     have to consider separately the cases of "both negative" and "one of
+  //     each sign".
+  //
+  //  2. -0 and +0 are required to compare equal.
+  //
+  // But problem #1 is not as hard as it sounds! If both operands are negative,
+  // then we can get the result we want by comparing them as unsigned integers
+  // the opposite way round, because the input with the smaller value (as an
+  // integer) is the larger number in an FP ordering sense. And if one operand
+  // is negative and the other is positive, the _same_ reversed comparison
+  // works, because the positive number (with zero sign bit) will always
+  // compare less than the negative one in an unsigned-integers sense.
+  //
+  // So we only have to worry about problem #2, signed zeroes. This only
+  // affects the answer if _both_ operands are zero. And we can check that
+  // easily, because it happens if and only if r12 = 0x80000000. (We know r12
+  // has its sign bit set; if it has no other bits set, that's because both
+  // inputs were either 0x80000000 or 0x00000000.)
+  lsls    r2, r2, #1              // EQ if both inputs are zero (also sets C)
+  beq     1f
+  cmp     op1, op0                // otherwise, compare them backwards
+1:
+  SetReturnRegister
+  bx      lr
+
+LOCAL_LABEL(NaNInf_check_negative):
+  // Second tier for negative numbers: we know the OR of the exponents is 0xFF,
+  // but again, we might not have either _actual_ exponent 0xFF, and also, an
+  // exponent 0xFF might be an infinity instead of a NaN.
+  //
+  // On this path we've already branched twice (once for negative numbers and
+  // once for the first-tier NaN check), so we'll just go straight to the
+  // precise check for NaNs.
+  movs    r2, #0xFF
+  lsls    r2, r2, #24
+  lsls    r3, op0, #1
+  cmp     r3, r2
+  bhi     LOCAL_LABEL(NaN)
+  lsls    r3, op1, #1
+  cmp     r3, r2
+  bhi     LOCAL_LABEL(NaN)
+
+  // Now we've ruled out NaNs, so we can just compare the two input registers
+  // and return. On this path we _don't_ need to check for the special case of
+  // comparing two zeroes, because we only came here if the bitwise OR of the
+  // exponent fields was 0xFF, which means the exponents can't both have been
+  // zero! So we can _just_ do the reversed CMP and finish.
+  cmp     op1, op0
+  SetReturnRegister
+  bx      lr
diff --git a/compiler-rt/lib/builtins/arm/thumb1/gesf2.S b/compiler-rt/lib/builtins/arm/thumb1/gesf2.S
new file mode 100644
index 0000000000000..aa75ec7b0a67b
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/gesf2.S
@@ -0,0 +1,54 @@
+//===-- gesf2.S - single-precision floating point comparison --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This function has the semantics of GNU __cmpsf2, except for its NaN
+// handling. It's a three-way compare which returns <0 if x<y, 0 if x==y, and
+// >0 if x>y. If the result is unordered (i.e. x or y or both is NaN) then it
+// returns <0, where __cmpsf2 would return >0.
+//
+// This also makes it suitable for use as __gtsf2 or __gesf2 (or __eqsf2 or
+// __nesf2).
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../assembly.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+op0 .req r0
+op1 .req r1
+.macro SetReturnRegister
+  bhi 0f
+  blo 1f
+  movs r0, #0
+  bx lr
+0:
+  movs r0, #1
+  bx lr
+1:
+  movs r0, #1
+  rsbs r0, r0, #0
+  bx lr
+.endm
+
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __compiler_rt_softfp_gesf2)
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__gtsf2, __gesf2)
+
+DEFINE_COMPILERRT_THUMB_FUNCTION(__compiler_rt_softfp_gesf2)
+  #include "fcmp.h"
+
+LOCAL_LABEL(NaN):
+  movs r0, #1
+  rsbs r0, r0, #0
+  bx lr
+
+END_COMPILERRT_FUNCTION(__compiler_rt_softfp_gesf2)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/thumb1/unordsf2.S b/compiler-rt/lib/builtins/arm/thumb1/unordsf2.S
new file mode 100644
index 0000000000000..5d74e0fdfe159
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/thumb1/unordsf2.S
@@ -0,0 +1,49 @@
+//===-- unordsf2.S - single-precision floating point comparison -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Return 1 if the result of comparing x with y is 'unordered', i.e.
+// one of x and y is NaN.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../assembly.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__unordsf2, __aeabi_fcmpun)
+
+DEFINE_COMPILERRT_THUMB_FUNCTION(__aeabi_fcmpun)
+
+  // This function isn't based on the general-purpose code in fcmp.h, because
+  // it's more effort than needed. Here we just need to identify whether or not
+  // there's at least one NaN in the inputs. There's no need to vary that check
+  // based on the sign bit, so we might as well just do the NaN test as quickly
+  // as possible.
+  movs    r2, #0xFF
+  lsls    r2, r2, #24
+  lsls    r3, r0, #1
+  cmp     r3, r2
+  bhi     LOCAL_LABEL(NaN)
+  lsls    r3, r1, #1
+  cmp     r3, r2
+  bhi     LOCAL_LABEL(NaN)
+
+  // If HS, then we have no NaNs and return false.
+  movs    r0, #0
+  bx      lr
+
+  // Otherwise, we have at least one NaN, and return true.
+LOCAL_LABEL(NaN):
+  movs    r0, #1
+  bx      lr
+
+END_COMPILERRT_FUNCTION(__aeabi_fcmpun)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/unordsf2.S b/compiler-rt/lib/builtins/arm/unordsf2.S
new file mode 100644
index 0000000000000..1930996779888
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/unordsf2.S
@@ -0,0 +1,56 @@
+//===-- unordsf2.S - single-precision floating point comparison -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Return 1 if the result of comparing x with y is 'unordered', i.e.
+// one of x and y is NaN.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+
+
+  .syntax unified
+  .text
+  .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__unordsf2)
+  push {r4, lr}
+  vmov r0, s0
+  vmov r1, s1
+  bl __aeabi_fcmpun
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__unordsf2, __aeabi_fcmpun)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmpun)
+
+  // This function isn't based on the general-purpose code in fcmp.h, because
+  // it's more effort than needed. Here we just need to identify whether or not
+  // there's at least one NaN in the inputs. There's no need to vary that check
+  // based on the sign bit, so we might as well just do the NaN test as quickly
+  // as possible.
+  mov     r12, #0xFF << 24
+  cmp     r12, r0, lsl #1    // if LO, then r12 < (r0 << 1), so r0 is a NaN
+  cmphs   r12, r1, lsl #1    // if not LO, then do the same check for r1
+
+  // If HS, then we have no NaNs and return false. We do this as quickly as we
+  // can (not stopping to take two instructions setting up r0 for both
+  // possibilities), on the assumption that NaNs are rare and we want to
+  // optimize for the non-NaN path.
+  movhs   r0, #0
+  bxhs    lr
+
+  // Otherwise, we have at least one NaN, and return true.
+  mov     r0, #1
+  bx      lr
+
+END_COMPILERRT_FUNCTION(__aeabi_fcmpun)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/test/builtins/Unit/comparesf2new_test.c b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
new file mode 100644
index 0000000000000..5c8be88354618
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
@@ -0,0 +1,433 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_comparesf2
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+COMPILER_RT_ABI int __eqsf2(float, float);
+COMPILER_RT_ABI int __nesf2(float, float);
+COMPILER_RT_ABI int __gesf2(float, float);
+COMPILER_RT_ABI int __gtsf2(float, float);
+COMPILER_RT_ABI int __lesf2(float, float);
+COMPILER_RT_ABI int __ltsf2(float, float);
+COMPILER_RT_ABI int __cmpsf2(float, float);
+COMPILER_RT_ABI int __unordsf2(float, float);
+
+enum Result {
+  RESULT_LT,
+  RESULT_GT,
+  RESULT_EQ,
+  RESULT_UN
+};
+
+int expect(int line, uint32_t a_rep, uint32_t b_rep, const char *name, int result, int ok, const char *expected) {
+  if (!ok)
+    printf("error at line %d: %s(%08" PRIx32 ", %08" PRIx32 ") = %d, expected %s\n",
+           line, name, a_rep, b_rep, result, expected);
+  return !ok;
+}
+
+int test__comparesf2(int line, uint32_t a_rep, uint32_t b_rep, enum Result result) {
+  float a = fromRep32(a_rep), b = fromRep32(b_rep);
+
+  int eq = __eqsf2(a, b);
+  int ne = __nesf2(a, b);
+  int ge = __gesf2(a, b);
+  int gt = __gtsf2(a, b);
+  int le = __lesf2(a, b);
+  int lt = __ltsf2(a, b);
+  int cmp = __cmpsf2(a, b);
+  int unord = __unordsf2(a, b);
+
+  int ret = 0;
+
+  switch (result) {
+  case RESULT_LT:
+    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge < 0, "< 0");
+    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt < 0, "< 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == -1, "== -1");
+    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0");
+    break;
+  case RESULT_GT:
+    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt > 0, "> 0");
+    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le > 0, "> 0");
+    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1");
+    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0");
+    break;
+  case RESULT_EQ:
+    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq == 0, "== 0");
+    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne == 0, "== 0");
+    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == 0, "== 0");
+    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0");
+    break;
+  case RESULT_UN:
+    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0");
+    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge < 0, "< 0");
+    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0");
+    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le > 0, "> 0");
+    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0");
+    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1");
+    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 1, "== 1");
+    break;
+  }
+
+  return ret;
+}
+
+#define test__comparesf2(a,b,x) test__comparesf2(__LINE__,a,b,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__comparesf2(0x00000000, 0x00000001, RESULT_LT);
+  status |= test__comparesf2(0x00000000, 0x007fffff, RESULT_LT);
+  status |= test__comparesf2(0x00000000, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0x00000000, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0x00000000, 0x7f800000, RESULT_LT);
+  status |= test__comparesf2(0x00000000, 0x7f872da0, RESULT_UN);
+  status |= test__comparesf2(0x00000000, 0x7fe42e09, RESULT_UN);
+  status |= test__comparesf2(0x00000000, 0x80000000, RESULT_EQ);
+  status |= test__comparesf2(0x00000000, 0x80000001, RESULT_GT);
+  status |= test__comparesf2(0x00000000, 0x807fffff, RESULT_GT);
+  status |= test__comparesf2(0x00000000, 0x80800000, RESULT_GT);
+  status |= test__comparesf2(0x00000000, 0xff800000, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0x00000001, RESULT_EQ);
+  status |= test__comparesf2(0x00000001, 0x3f7fffff, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x3ffffffe, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x3fffffff, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x7effffff, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x7f7ffffe, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x7f7fffff, RESULT_LT);
+  status |= test__comparesf2(0x00000001, 0x7f94d5b9, RESULT_UN);
+  status |= test__comparesf2(0x00000001, 0x7fef53b1, RESULT_UN);
+  status |= test__comparesf2(0x00000001, 0x80000001, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xbf7fffff, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xbffffffe, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xbfffffff, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xfeffffff, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xff7ffffe, RESULT_GT);
+  status |= test__comparesf2(0x00000001, 0xff7fffff, RESULT_GT);
+  status |= test__comparesf2(0x00000002, 0x00000001, RESULT_GT);
+  status |= test__comparesf2(0x00000003, 0x00000002, RESULT_GT);
+  status |= test__comparesf2(0x00000003, 0x40400000, RESULT_LT);
+  status |= test__comparesf2(0x00000003, 0x40a00000, RESULT_LT);
+  status |= test__comparesf2(0x00000003, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0x00000003, 0xc0a00000, RESULT_GT);
+  status |= test__comparesf2(0x00000003, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x00000004, 0x00000004, RESULT_EQ);
+  status |= test__comparesf2(0x007ffffc, 0x807ffffc, RESULT_GT);
+  status |= test__comparesf2(0x007ffffd, 0x007ffffe, RESULT_LT);
+  status |= test__comparesf2(0x007fffff, 0x00000000, RESULT_GT);
+  status |= test__comparesf2(0x007fffff, 0x007ffffe, RESULT_GT);
+  status |= test__comparesf2(0x007fffff, 0x007fffff, RESULT_EQ);
+  status |= test__comparesf2(0x007fffff, 0x00800000, RESULT_LT);
+  status |= test__comparesf2(0x007fffff, 0x7f800000, RESULT_LT);
+  status |= test__comparesf2(0x007fffff, 0x7fa111d3, RESULT_UN);
+  status |= test__comparesf2(0x007fffff, 0x7ff43134, RESULT_UN);
+  status |= test__comparesf2(0x007fffff, 0x80000000, RESULT_GT);
+  status |= test__comparesf2(0x007fffff, 0xff800000, RESULT_GT);
+  status |= test__comparesf2(0x00800000, 0x00000000, RESULT_GT);
+  status |= test__comparesf2(0x00800000, 0x00800000, RESULT_EQ);
+  status |= test__comparesf2(0x00800000, 0x80800000, RESULT_GT);
+  status |= test__comparesf2(0x00800001, 0x00800000, RESULT_GT);
+  status |= test__comparesf2(0x00800001, 0x00800002, RESULT_LT);
+  status |= test__comparesf2(0x00ffffff, 0x01000000, RESULT_LT);
+  status |= test__comparesf2(0x00ffffff, 0x01000002, RESULT_LT);
+  status |= test__comparesf2(0x00ffffff, 0x01000004, RESULT_LT);
+  status |= test__comparesf2(0x01000000, 0x00ffffff, RESULT_GT);
+  status |= test__comparesf2(0x01000001, 0x00800001, RESULT_GT);
+  status |= test__comparesf2(0x01000001, 0x00ffffff, RESULT_GT);
+  status |= test__comparesf2(0x01000002, 0x00800001, RESULT_GT);
+  status |= test__comparesf2(0x017fffff, 0x01800000, RESULT_LT);
+  status |= test__comparesf2(0x01800000, 0x017fffff, RESULT_GT);
+  status |= test__comparesf2(0x01800001, 0x017fffff, RESULT_GT);
+  status |= test__comparesf2(0x01800002, 0x01000003, RESULT_GT);
+  status |= test__comparesf2(0x3f000000, 0x3f000000, RESULT_EQ);
+  status |= test__comparesf2(0x3f7fffff, 0x00000001, RESULT_GT);
+  status |= test__comparesf2(0x3f7fffff, 0x80000001, RESULT_GT);
+  status |= test__comparesf2(0x3f800000, 0x3f800000, RESULT_EQ);
+  status |= test__comparesf2(0x3f800000, 0x3f800003, RESULT_LT);
+  status |= test__comparesf2(0x3f800000, 0x40000000, RESULT_LT);
+  status |= test__comparesf2(0x3f800000, 0x40e00000, RESULT_LT);
+  status |= test__comparesf2(0x3f800000, 0x7fb27f62, RESULT_UN);
+  status |= test__comparesf2(0x3f800000, 0x7fd9d4b4, RESULT_UN);
+  status |= test__comparesf2(0x3f800000, 0x80000000, RESULT_GT);
+  status |= test__comparesf2(0x3f800000, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x3f800000, 0xbf800003, RESULT_GT);
+  status |= test__comparesf2(0x3f800001, 0x3f800000, RESULT_GT);
+  status |= test__comparesf2(0x3f800001, 0x3f800002, RESULT_LT);
+  status |= test__comparesf2(0x3f800001, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x3ffffffc, 0x3ffffffd, RESULT_LT);
+  status |= test__comparesf2(0x3fffffff, 0x00000001, RESULT_GT);
+  status |= test__comparesf2(0x3fffffff, 0x40000000, RESULT_LT);
+  status |= test__comparesf2(0x40000000, 0x3f800000, RESULT_GT);
+  status |= test__comparesf2(0x40000000, 0x3fffffff, RESULT_GT);
+  status |= test__comparesf2(0x40000000, 0x40000000, RESULT_EQ);
+  status |= test__comparesf2(0x40000000, 0x40000001, RESULT_LT);
+  status |= test__comparesf2(0x40000000, 0xc0000000, RESULT_GT);
+  status |= test__comparesf2(0x40000000, 0xc0000001, RESULT_GT);
+  status |= test__comparesf2(0x40000000, 0xc0a00000, RESULT_GT);
+  status |= test__comparesf2(0x40000001, 0x3f800001, RESULT_GT);
+  status |= test__comparesf2(0x40000001, 0x40000002, RESULT_LT);
+  status |= test__comparesf2(0x40000001, 0xc0000002, RESULT_GT);
+  status |= test__comparesf2(0x40000002, 0x3f800001, RESULT_GT);
+  status |= test__comparesf2(0x40000002, 0x3f800003, RESULT_GT);
+  status |= test__comparesf2(0x40000004, 0x40000003, RESULT_GT);
+  status |= test__comparesf2(0x40400000, 0x40400000, RESULT_EQ);
+  status |= test__comparesf2(0x407fffff, 0x407ffffe, RESULT_GT);
+  status |= test__comparesf2(0x407fffff, 0x40800002, RESULT_LT);
+  status |= test__comparesf2(0x40800001, 0x407fffff, RESULT_GT);
+  status |= test__comparesf2(0x40a00000, 0x00000000, RESULT_GT);
+  status |= test__comparesf2(0x40a00000, 0x80000000, RESULT_GT);
+  status |= test__comparesf2(0x40a00000, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x40a00000, 0xc0a00000, RESULT_GT);
+  status |= test__comparesf2(0x7d800001, 0x7d7fffff, RESULT_GT);
+  status |= test__comparesf2(0x7e7fffff, 0x7e7ffffe, RESULT_GT);
+  status |= test__comparesf2(0x7e7fffff, 0x7e800002, RESULT_LT);
+  status |= test__comparesf2(0x7e800000, 0x7e7fffff, RESULT_GT);
+  status |= test__comparesf2(0x7e800000, 0x7e800000, RESULT_EQ);
+  status |= test__comparesf2(0x7e800000, 0x7e800001, RESULT_LT);
+  status |= test__comparesf2(0x7e800001, 0x7e800000, RESULT_GT);
+  status |= test__comparesf2(0x7e800001, 0x7f000001, RESULT_LT);
+  status |= test__comparesf2(0x7e800001, 0xfe800000, RESULT_GT);
+  status |= test__comparesf2(0x7e800002, 0x7e000003, RESULT_GT);
+  status |= test__comparesf2(0x7e800004, 0x7e800003, RESULT_GT);
+  status |= test__comparesf2(0x7efffffe, 0x7efffffe, RESULT_EQ);
+  status |= test__comparesf2(0x7efffffe, 0x7effffff, RESULT_LT);
+  status |= test__comparesf2(0x7efffffe, 0xfeffffff, RESULT_GT);
+  status |= test__comparesf2(0x7effffff, 0x3f800000, RESULT_GT);
+  status |= test__comparesf2(0x7effffff, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0x7effffff, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x7effffff, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x7f000000, 0x3f800000, RESULT_GT);
+  status |= test__comparesf2(0x7f000000, 0x7f000000, RESULT_EQ);
+  status |= test__comparesf2(0x7f000000, 0x7f800000, RESULT_LT);
+  status |= test__comparesf2(0x7f000000, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x7f000000, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x7f000000, 0xff800000, RESULT_GT);
+  status |= test__comparesf2(0x7f000001, 0x7f000000, RESULT_GT);
+  status |= test__comparesf2(0x7f000001, 0x7f000002, RESULT_LT);
+  status |= test__comparesf2(0x7f000001, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x7f000002, 0x7e800001, RESULT_GT);
+  status |= test__comparesf2(0x7f7ffffe, 0x3f800000, RESULT_GT);
+  status |= test__comparesf2(0x7f7ffffe, 0x7f7fffff, RESULT_LT);
+  status |= test__comparesf2(0x7f7ffffe, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x7f7ffffe, 0xff7fffff, RESULT_GT);
+  status |= test__comparesf2(0x7f7fffff, 0x00000001, RESULT_GT);
+  status |= test__comparesf2(0x7f7fffff, 0x3f800000, RESULT_GT);
+  status |= test__comparesf2(0x7f7fffff, 0x7f7fffff, RESULT_EQ);
+  status |= test__comparesf2(0x7f7fffff, 0x7fbed1eb, RESULT_UN);
+  status |= test__comparesf2(0x7f7fffff, 0x7fe15ee3, RESULT_UN);
+  status |= test__comparesf2(0x7f7fffff, 0x80000001, RESULT_GT);
+  status |= test__comparesf2(0x7f7fffff, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x00000000, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x00000001, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x007fffff, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x7f000000, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x7f7fffff, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x7f800000, RESULT_EQ);
+  status |= test__comparesf2(0x7f800000, 0x7f91a4da, RESULT_UN);
+  status |= test__comparesf2(0x7f800000, 0x7fd44a09, RESULT_UN);
+  status |= test__comparesf2(0x7f800000, 0x80000000, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x80000001, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0x807fffff, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0xff7fffff, RESULT_GT);
+  status |= test__comparesf2(0x7f800000, 0xff800000, RESULT_GT);
+  status |= test__comparesf2(0x7f86d066, 0x00000000, RESULT_UN);
+  status |= test__comparesf2(0x7f85a878, 0x00000001, RESULT_UN);
+  status |= test__comparesf2(0x7f8c0dca, 0x007fffff, RESULT_UN);
+  status |= test__comparesf2(0x7f822725, 0x3f800000, RESULT_UN);
+  status |= test__comparesf2(0x7f853870, 0x7f7fffff, RESULT_UN);
+  status |= test__comparesf2(0x7fbefc9d, 0x7f800000, RESULT_UN);
+  status |= test__comparesf2(0x7f9f84a9, 0x7f81461b, RESULT_UN);
+  status |= test__comparesf2(0x7f9e2c1d, 0x7fe4a313, RESULT_UN);
+  status |= test__comparesf2(0x7fb0e6d0, 0x80000000, RESULT_UN);
+  status |= test__comparesf2(0x7fac9171, 0x80000001, RESULT_UN);
+  status |= test__comparesf2(0x7f824ae6, 0x807fffff, RESULT_UN);
+  status |= test__comparesf2(0x7fa8b9a0, 0xbf800000, RESULT_UN);
+  status |= test__comparesf2(0x7f92a1cd, 0xff7fffff, RESULT_UN);
+  status |= test__comparesf2(0x7fbe5d29, 0xff800000, RESULT_UN);
+  status |= test__comparesf2(0x7fcc9a57, 0x00000000, RESULT_UN);
+  status |= test__comparesf2(0x7fec9d71, 0x00000001, RESULT_UN);
+  status |= test__comparesf2(0x7fd5db76, 0x007fffff, RESULT_UN);
+  status |= test__comparesf2(0x7fd003d9, 0x3f800000, RESULT_UN);
+  status |= test__comparesf2(0x7fca0684, 0x7f7fffff, RESULT_UN);
+  status |= test__comparesf2(0x7fc46aa0, 0x7f800000, RESULT_UN);
+  status |= test__comparesf2(0x7ff72b19, 0x7faee637, RESULT_UN);
+  status |= test__comparesf2(0x7fe9e0c1, 0x7fcc2788, RESULT_UN);
+  status |= test__comparesf2(0x7fc571ea, 0x80000000, RESULT_UN);
+  status |= test__comparesf2(0x7fd81a54, 0x80000001, RESULT_UN);
+  status |= test__comparesf2(0x7febdfaf, 0x807fffff, RESULT_UN);
+  status |= test__comparesf2(0x7ffa1f94, 0xbf800000, RESULT_UN);
+  status |= test__comparesf2(0x7ff38fa0, 0xff7fffff, RESULT_UN);
+  status |= test__comparesf2(0x7fdf3502, 0xff800000, RESULT_UN);
+  status |= test__comparesf2(0x80000000, 0x00000000, RESULT_EQ);
+  status |= test__comparesf2(0x80000000, 0x00000001, RESULT_LT);
+  status |= test__comparesf2(0x80000000, 0x007fffff, RESULT_LT);
+  status |= test__comparesf2(0x80000000, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0x80000000, 0x7f800000, RESULT_LT);
+  status |= test__comparesf2(0x80000000, 0x7fbdfb72, RESULT_UN);
+  status |= test__comparesf2(0x80000000, 0x7fdd528e, RESULT_UN);
+  status |= test__comparesf2(0x80000000, 0x80000001, RESULT_GT);
+  status |= test__comparesf2(0x80000000, 0x807fffff, RESULT_GT);
+  status |= test__comparesf2(0x80000000, 0x80800000, RESULT_GT);
+  status |= test__comparesf2(0x80000000, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x80000000, 0xff800000, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0x00000001, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x3f7fffff, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x3ffffffe, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x3fffffff, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x7effffff, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x7f7ffffe, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x7f7fffff, RESULT_LT);
+  status |= test__comparesf2(0x80000001, 0x7fac481a, RESULT_UN);
+  status |= test__comparesf2(0x80000001, 0x7fcf111d, RESULT_UN);
+  status |= test__comparesf2(0x80000001, 0x80000001, RESULT_EQ);
+  status |= test__comparesf2(0x80000001, 0xbf7fffff, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0xbf800000, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0xbffffffe, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0xbfffffff, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0xfeffffff, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0xff7ffffe, RESULT_GT);
+  status |= test__comparesf2(0x80000001, 0xff7fffff, RESULT_GT);
+  status |= test__comparesf2(0x80000002, 0x80000001, RESULT_LT);
+  status |= test__comparesf2(0x80000003, 0x40400000, RESULT_LT);
+  status |= test__comparesf2(0x80000003, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0x80000003, 0x80000002, RESULT_LT);
+  status |= test__comparesf2(0x80000003, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0x80000004, 0x80000004, RESULT_EQ);
+  status |= test__comparesf2(0x807ffffd, 0x807ffffe, RESULT_GT);
+  status |= test__comparesf2(0x807fffff, 0x00000000, RESULT_LT);
+  status |= test__comparesf2(0x807fffff, 0x007fffff, RESULT_LT);
+  status |= test__comparesf2(0x807fffff, 0x7f800000, RESULT_LT);
+  status |= test__comparesf2(0x807fffff, 0x7faf07f6, RESULT_UN);
+  status |= test__comparesf2(0x807fffff, 0x7fd18a54, RESULT_UN);
+  status |= test__comparesf2(0x807fffff, 0x80000000, RESULT_LT);
+  status |= test__comparesf2(0x807fffff, 0x807ffffe, RESULT_LT);
+  status |= test__comparesf2(0x807fffff, 0x807fffff, RESULT_EQ);
+  status |= test__comparesf2(0x807fffff, 0x80800000, RESULT_GT);
+  status |= test__comparesf2(0x807fffff, 0xff800000, RESULT_GT);
+  status |= test__comparesf2(0x80800000, 0x00000000, RESULT_LT);
+  status |= test__comparesf2(0x80800000, 0x00800000, RESULT_LT);
+  status |= test__comparesf2(0x80800001, 0x80800000, RESULT_LT);
+  status |= test__comparesf2(0x80800001, 0x80800002, RESULT_GT);
+  status |= test__comparesf2(0x80ffffff, 0x81000000, RESULT_GT);
+  status |= test__comparesf2(0x80ffffff, 0x81000002, RESULT_GT);
+  status |= test__comparesf2(0x80ffffff, 0x81000004, RESULT_GT);
+  status |= test__comparesf2(0x81000000, 0x80ffffff, RESULT_LT);
+  status |= test__comparesf2(0x81000001, 0x80800001, RESULT_LT);
+  status |= test__comparesf2(0x81000001, 0x80ffffff, RESULT_LT);
+  status |= test__comparesf2(0x81000002, 0x80800001, RESULT_LT);
+  status |= test__comparesf2(0x817fffff, 0x81800000, RESULT_GT);
+  status |= test__comparesf2(0x81800000, 0x817fffff, RESULT_LT);
+  status |= test__comparesf2(0x81800001, 0x817fffff, RESULT_LT);
+  status |= test__comparesf2(0x81800002, 0x81000003, RESULT_LT);
+  status |= test__comparesf2(0xbf800000, 0x3f800003, RESULT_LT);
+  status |= test__comparesf2(0xbf800000, 0x7fa66ee9, RESULT_UN);
+  status |= test__comparesf2(0xbf800000, 0x7fe481ef, RESULT_UN);
+  status |= test__comparesf2(0xbf800000, 0x80000000, RESULT_LT);
+  status |= test__comparesf2(0xbf800000, 0xbf800003, RESULT_GT);
+  status |= test__comparesf2(0xbf800001, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0xbf800001, 0xbf800000, RESULT_LT);
+  status |= test__comparesf2(0xbf800001, 0xbf800002, RESULT_GT);
+  status |= test__comparesf2(0xbffffffc, 0xbffffffd, RESULT_GT);
+  status |= test__comparesf2(0xbfffffff, 0x00000001, RESULT_LT);
+  status |= test__comparesf2(0xbfffffff, 0xc0000000, RESULT_GT);
+  status |= test__comparesf2(0xc0000000, 0x40000001, RESULT_LT);
+  status |= test__comparesf2(0xc0000000, 0xbfffffff, RESULT_LT);
+  status |= test__comparesf2(0xc0000000, 0xc0000001, RESULT_GT);
+  status |= test__comparesf2(0xc0000001, 0x40000002, RESULT_LT);
+  status |= test__comparesf2(0xc0000001, 0xbf800001, RESULT_LT);
+  status |= test__comparesf2(0xc0000001, 0xc0000002, RESULT_GT);
+  status |= test__comparesf2(0xc0000002, 0xbf800001, RESULT_LT);
+  status |= test__comparesf2(0xc0000002, 0xbf800003, RESULT_LT);
+  status |= test__comparesf2(0xc0000004, 0xc0000003, RESULT_LT);
+  status |= test__comparesf2(0xc0400000, 0x40400000, RESULT_LT);
+  status |= test__comparesf2(0xc07fffff, 0xc07ffffe, RESULT_LT);
+  status |= test__comparesf2(0xc07fffff, 0xc0800002, RESULT_GT);
+  status |= test__comparesf2(0xc0800001, 0xc07fffff, RESULT_LT);
+  status |= test__comparesf2(0xfd800001, 0xfd7fffff, RESULT_LT);
+  status |= test__comparesf2(0xfe7fffff, 0xfe7ffffe, RESULT_LT);
+  status |= test__comparesf2(0xfe7fffff, 0xfe800002, RESULT_GT);
+  status |= test__comparesf2(0xfe800000, 0xfe7fffff, RESULT_LT);
+  status |= test__comparesf2(0xfe800000, 0xfe800001, RESULT_GT);
+  status |= test__comparesf2(0xfe800001, 0x7e800000, RESULT_LT);
+  status |= test__comparesf2(0xfe800001, 0xfe800000, RESULT_LT);
+  status |= test__comparesf2(0xfe800001, 0xff000001, RESULT_GT);
+  status |= test__comparesf2(0xfe800002, 0xfe000003, RESULT_LT);
+  status |= test__comparesf2(0xfe800004, 0xfe800003, RESULT_LT);
+  status |= test__comparesf2(0xfefffffe, 0x7efffffe, RESULT_LT);
+  status |= test__comparesf2(0xfefffffe, 0x7effffff, RESULT_LT);
+  status |= test__comparesf2(0xfefffffe, 0xfefffffe, RESULT_EQ);
+  status |= test__comparesf2(0xfefffffe, 0xfeffffff, RESULT_GT);
+  status |= test__comparesf2(0xfeffffff, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0xfeffffff, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0xfeffffff, 0xbf800000, RESULT_LT);
+  status |= test__comparesf2(0xfeffffff, 0xff000000, RESULT_GT);
+  status |= test__comparesf2(0xff000000, 0x00000000, RESULT_LT);
+  status |= test__comparesf2(0xff000000, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0xff000000, 0x7f800000, RESULT_LT);
+  status |= test__comparesf2(0xff000000, 0x80000000, RESULT_LT);
+  status |= test__comparesf2(0xff000000, 0xbf800000, RESULT_LT);
+  status |= test__comparesf2(0xff000000, 0xff000000, RESULT_EQ);
+  status |= test__comparesf2(0xff000000, 0xff800000, RESULT_GT);
+  status |= test__comparesf2(0xff000001, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0xff000001, 0xff000000, RESULT_LT);
+  status |= test__comparesf2(0xff000001, 0xff000002, RESULT_GT);
+  status |= test__comparesf2(0xff000002, 0xfe800001, RESULT_LT);
+  status |= test__comparesf2(0xff7ffffe, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0xff7ffffe, 0x7f7fffff, RESULT_LT);
+  status |= test__comparesf2(0xff7ffffe, 0xbf800000, RESULT_LT);
+  status |= test__comparesf2(0xff7ffffe, 0xff7fffff, RESULT_GT);
+  status |= test__comparesf2(0xff7fffff, 0x00000001, RESULT_LT);
+  status |= test__comparesf2(0xff7fffff, 0x3f800000, RESULT_LT);
+  status |= test__comparesf2(0xff7fffff, 0x7f919cff, RESULT_UN);
+  status |= test__comparesf2(0xff7fffff, 0x7fd729a7, RESULT_UN);
+  status |= test__comparesf2(0xff7fffff, 0x80000001, RESULT_LT);
+  status |= test__comparesf2(0xff7fffff, 0xbf800000, RESULT_LT);
+  status |= test__comparesf2(0xff7fffff, 0xff7fffff, RESULT_EQ);
+  status |= test__comparesf2(0xff800000, 0x00000000, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x00000001, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x007fffff, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x7f000000, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x7f7fffff, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x7f800000, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x7fafdbc1, RESULT_UN);
+  status |= test__comparesf2(0xff800000, 0x7fec80fe, RESULT_UN);
+  status |= test__comparesf2(0xff800000, 0x80000000, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x80000001, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0x807fffff, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0xff000000, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0xff7fffff, RESULT_LT);
+  status |= test__comparesf2(0xff800000, 0xff800000, RESULT_EQ);
+
+  return status;
+}

>From 35dd800cbe1eb4d571c47254530ee75e7b98f500 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 16:12:53 +0000
Subject: [PATCH 08/33] [compiler-rt][ARM] Optimized FP double <-> single
 conversion

This commit provides assembly versions of the conversions both ways
between double and float.
---
 compiler-rt/lib/builtins/CMakeLists.txt       |   2 +
 compiler-rt/lib/builtins/arm/extendsfdf2.S    | 195 ++++++++++
 compiler-rt/lib/builtins/arm/truncdfsf2.S     | 198 ++++++++++
 .../test/builtins/Unit/extendsfdf2new_test.c  | 123 ++++++
 .../test/builtins/Unit/truncdfsf2new_test.c   | 367 ++++++++++++++++++
 5 files changed, 885 insertions(+)
 create mode 100644 compiler-rt/lib/builtins/arm/extendsfdf2.S
 create mode 100644 compiler-rt/lib/builtins/arm/truncdfsf2.S
 create mode 100644 compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
 create mode 100644 compiler-rt/test/builtins/Unit/truncdfsf2new_test.c

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 0c53781a51392..6b392c8eb22f0 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -456,6 +456,8 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm")
       arm/gesf2.S
       arm/unorddf2.S
       arm/unordsf2.S
+      arm/extendsfdf2.S
+      arm/truncdfsf2.S
       )
     set_source_files_properties(${assembly_files}
       PROPERTIES COMPILE_OPTIONS ${implicit_it_flag})
diff --git a/compiler-rt/lib/builtins/arm/extendsfdf2.S b/compiler-rt/lib/builtins/arm/extendsfdf2.S
new file mode 100644
index 0000000000000..21518d4a75b1a
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/extendsfdf2.S
@@ -0,0 +1,195 @@
+//===-- extendsfdf2.S - single- to double-precision FP conversion ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the __extendsfdf2 function (single to double precision
+// floating point conversion) for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__extendsfdf2)
+  push {r4, lr}
+  vmov r0, s0
+  bl __aeabi_f2d
+  VMOV_TO_DOUBLE(d0, r0, r1)
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__extendsfdf2, __aeabi_f2d)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_f2d)
+
+  // Start with the fast path, dealing with normalized single-precision inputs.
+  // We handle these as quickly as possible in straight-line code, and branch
+  // out of line to a single 'handle everything else' label which will have to
+  // figure out what kind of unusual thing has happened.
+
+  // Extend the exponent field by 3 bits, by shifting the sign bit off the top
+  // of r0 into the carry flag, shifting the rest of the input word right by 3,
+  // then using RRX to put the sign back. So we end up with a word shaped like
+  // the top half of a double, but the exponent field is still biased by the
+  // single-precision offset of 0x7f instead of the double-precision 0x3ff.
+  lsls    r3, r0, #1
+  lsr     r12, r3, #3
+  rrx     r12, r12
+
+  // For a normalized number, the remaining steps are to rebias the exponent,
+  // recover the remaining 3 mantissa bits from r0 which aren't included in the
+  // word we've just made, and move both into the right output registers.
+  //
+  // But we must also check for the difficult cases. These occur when the input
+  // exponent is either 0 or 0xFF. Those two values can be identified by the
+  // property that exp XOR (exp << 1) has the top 7 bits all zero.
+
+  // Do the test for uncommon values. Instead of using a shifter operand in the
+  // obvious way (EOR output, r0, r0, lsl #1), we use the fact that the setup
+  // code above already has a shifted-left copy of the input word in r3. In
+  // Thumb, this makes the EORS a 16-bit instruction instead of 32-bit.
+  eors    r3, r3, r0
+
+  // Now prepare the output, for normal inputs.
+  //
+  // We make this pair of instructions conditional on NE, i.e. we skip it if r3
+  // and r0 were actually equal (which could only happen if r0 was 0, i.e. the
+  // input was +0). This is fine, because in that situation the input wasn't
+  // normalized, so we aren't going to return this output anyway.
+  //
+  // The _point_ of conditionalizing these two instructions is that this way we
+  // have only one IT instruction on the fast path, and it's _here_, where this
+  // comment is, so that it comes immediately after the above 16-bit EORS and
+  // can be executed in the same cycle by Cortex-M3.
+  lslne   xl, r0, #29           // xl now has the bottom 3 input mantissa bits
+  addne   xh, r12, #(0x3ff - 0x7f) << 20 // rebias exponent in xh
+
+  // Finally, check whether the test word in r3 has its top 7 exponent bits
+  // zero. If not, we can return the fast-path answer.
+  tstne   r3, #0x7f000000
+  bxne    lr
+
+  // Now we've handled the fast-path cases as fast as we know how, what do we
+  // do next? We almost certainly don't have the input value in r0 any more,
+  // because we overwrote it by writing an unused output to xh:xl in the above
+  // code. Worse, we didn't _reliably_ overwrite it, because those writes to
+  // xh:xl might not have happened if the whole test word in r3 was zero. So
+  // where can we find the input bits?
+  //
+  // We have r3 = input XOR (input << 1). That's actually an invertible
+  // transformation, so in principle we could recover the full original input
+  // float from just r3. The quickest way to do that involves these five
+  // instructions (in any order, since they commute):
+  //
+  //   EOR     r3, r3, r3, lsl #16
+  //   EOR     r3, r3, r3, lsl #8
+  //   EOR     r3, r3, r3, lsl #4
+  //   EOR     r3, r3, r3, lsl #2
+  //   EOR     r3, r3, r3, lsl #1
+  //
+  // But that's rather slow, and we can do better. r12 contains most of the
+  // input bits in a more usable form: we inserted three zero bits between the
+  // sign and the top of the exponent, but everything from the input is there
+  // _somewhere_, except for the low 3 bits.
+  //
+  // However, on one code path below we'll use a subset of those EOR
+  // instructions to recover the low 3 bits of the input.
+
+  // First, find out whether the input exponent was 0 (zero or denormal), or
+  // 0xFF (infinity or NaN). We know it was one of the two, or we would have
+  // taken the early return from the fast path. So it's enough to test any
+  // single bit of the exponent in r12.
+  tst     r12, #1<<27           // bit 27 is topmost bit of the 8-bit exponent
+  bne     LOCAL_LABEL(inf_or_nan)
+
+  // If we didn't take that branch, we have a denormal or zero. Zeroes are
+  // likely to be common, so we'd prefer to handle those with highest priority.
+  //
+  // r3 = (input XOR (input << 1)) will take the values 0 or 0x80000000 for a
+  // zero input. So it contains precisely the right value to return in xh.
+  //
+  // The BICS here combines the zeroing of xl with the test of r3, because it
+  // sets Z if and only if the input was one of those two values, and if so,
+  // sets xl=0.
+  //
+  // Unfortunately this has the side effect of clobbering xl in the case where
+  // we _don't_ take the early return, so now we've lost our verbatim copy of
+  // the low 3 input bits! On the denormal-handling path we'll have to recover
+  // those from r3 more awkwardly. But denormal handling is rare, and slow
+  // anyway, so it's worth the awkwardness to save a cycle in the much more
+  // common case of a zero input.
+  bics    xl, r3, #0x80000000   // EQ if output is zero
+  moveq   xh, r3                // if so, copy input sign into xh
+  bxeq    lr                    // and return
+
+  // Now we know we're dealing with a denormal, so we need to recover the whole
+  // input mantissa. Most of it is in r12, but those last three bits now need
+  // to be reconstructed from r3 by using part of the shift+EOR trick shown
+  // above. We only need the left shifts by 1 and by 2, because the other three
+  // don't affect the bottom 3 bits at all.
+  eor     r3, r3, r3, lsl #2
+  eor     r3, r3, r3, lsl #1
+  and     r3, r3, #7
+
+  // Now r3 contains just the low bits of the mantissa. The rest of the
+  // mantissa is in r12, shifted right by 3 bits, so this instruction rebuilds
+  // the entire input mantissa in xh. (The exponent field is known to be zero,
+  // and the sign bit at the top of r12 is discarded by the left shift.)
+  orr     xh, r3, r12, lsl #3
+
+  // Renormalize that input mantissa so that its high bit is at the top of the
+  // word.
+  clz     r2, xh
+  lsl     xh, xh, r2
+
+  // Compute the right sign + exponent to go with that mantissa.
+  //
+  // If the input mantissa had had only its low bit set, then the input float
+  // would be 2^-149, which has a double-precision exponent of 0x36a. In that
+  // situation we'd have r2 = 31 (output from the CLZ). So we need the output
+  // exponent to be (0x389 - r2). But the leading bit of the mantissa will
+  // increment the exponent field when we add them together, so in fact we want
+  // to calculate (0x388 - r2). That's particularly convenient, because 0x388
+  // fits in an AArch32 immediate field!
+  and     r3, r12, #0x80000000  // get the sign bit from the top of r12
+  add     r3, r3, #0x388 << 20  // add the exponent bias as calculated above
+  sub     r3, r3, r2, lsl #20   // subtract the CLZ output
+
+  // Finally, distribute the normalized mantissa across the two output words,
+  // and combine the top half with the exponent we just computed.
+  lsls    xl, xh, #21           // low word = low 3 bits of normalized mantissa
+  add     xh, r3, xh, lsr #11   // high word = sign + exp + rest of mantissa
+  bx      lr
+
+LOCAL_LABEL(inf_or_nan):
+  // We come here if the input was either infinity or a NaN. In this situation
+  // we can be sure that the instructions that set up the fast-path return
+  // value _did_ happen, because the input was nonzero. Also we branched away
+  // before the test for a zero input clobbered xl.
+  //
+  // So xh:xl will contain what _would_ be the right output value if 0xFF were
+  // not a special input: the exponent field will be 0x47f, and the sign and
+  // mantissa will be in place.
+  //
+  // This is almost exactly what we really want to return, except for two
+  // things: the exponent should be corrected to 0x7ff for an output infinity
+  // or NaN, and if the mantissa is nonzero at all (so that we're returning a
+  // NaN and not an infinity) then we should set its top bit to make it a quiet
+  // NaN.
+  orrs    xh, xh, #0x7f000000   // set the missing bits in the exponent field
+  orrs    r2, xl, xh, lsl #12   // is any bit of the mantissa set?
+  orrne   xh, xh, #0x00080000   // if so, set the top mantissa bit
+  bx      lr
+
+END_COMPILERRT_FUNCTION(__aeabi_f2d)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/truncdfsf2.S b/compiler-rt/lib/builtins/arm/truncdfsf2.S
new file mode 100644
index 0000000000000..d87fce8d1bcbb
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/truncdfsf2.S
@@ -0,0 +1,198 @@
+//===-- truncdfsf2.S - double- to single precision FP conversion ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the __truncdfsf2 function (double to single precision
+// floating point conversion), with the IEEE-754 default rounding (to nearest,
+// ties to even), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+  .syntax unified
+  .text
+  .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__truncdfsf2)
+  push {r4, lr}
+  VMOV_FROM_DOUBLE(r0, r1, d0)
+  bl __aeabi_d2f
+  vmov s0, r0
+  pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__truncdfsf2, __aeabi_d2f)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_d2f)
+
+  // Start with the fast path, dealing with input values that give a normalized
+  // single-precision output. We handle these as quickly as possible in
+  // straight-line code, and branch out of line to a single 'handle everything
+  // else' label which will have to figure out what kind of unusual thing has
+  // happened.
+
+  // Split xh into the sign bit (in r3) and everything else (r2), so that we
+  // can change the width of the exponent field and then put the sign back on
+  // later.
+  bic     r2, xh, #0x80000000
+  and     r3, xh, #0x80000000
+
+  // Rebias the exponent, still in its double-precision location, to account
+  // for the difference between double- and single-precision exponents.
+  sub     r2, r2, #(0x3ff-0x7f) << 20
+
+  // If the exponent field is now 0 or less, we have an underflow or an exact
+  // zero. If it's 0xFF or more, we have an overflow, or a NaN or infinity as
+  // input. Detect all of those in a combined test, and branch out of line.
+  cmp     r2, #0x00100000       // LO if output too small
+  rsbshs  r12, r2, #0x0ff00000  // otherwise, set LS if output too large
+  bls     LOCAL_LABEL(uncommon)          // so now LS means one or the other happened
+
+  // We've disposed of all the uncommon cases, so we know we're returning a
+  // normalized float, but we might still need to round it. Shift the round bit
+  // into the C flag, also setting Z if everything below that is zero.
+  lsls    r12, xl, #4
+
+  // Put the result back together, by recombining the sign (in r3) with the
+  // exponent and top of the mantissa (in r2, needing to be shifted left 3
+  // bits), plus the top 3 bits of xl. The last of those is put on with an ADC
+  // instruction, which also rounds up if the bit we just shifted into C was
+  // set.
+  orr     r2, r3, r2, lsl #3    // sign + exponent + most of mantissa
+  adc     r0, r2, xl, lsr #29   // low 3 bits of mantissa + maybe round up
+
+  // If C=1 and Z=1, we need to round to even. Otherwise we're finished. So we
+  // conditionally return based on one of those flags, then clear the low
+  // output bit based on the other.
+  //
+  // Which way round? On the assumption that input mantissas are roughly
+  // uniformly distributed, _almost all_ input doubles will contain a 1 bit
+  // somewhere in the bottom 28 bits, so we return early in the vast majority
+  // of cases by testing Z first. If we tested C first, we'd expect to return
+  // early only half the time, costing two extra instructions half the time
+  // instead of 1/2^28 of the time.
+  //
+  // (That's a bit optimistic, because of course in some situations input
+  // mantissas _won't_ be that uniform. In particular, if you converted from a
+  // float, did a small amount of calculation in double, and converted back,
+  // the round-to-even case might come up more often. But at least _some_
+  // applications will be passing doubles that make use of the whole mantissa,
+  // so I think this is still the more sensible way round to do the test.)
+  bxne    lr                    // return if Z=0
+  biccs   r0, r0, #1            // Z=1, so round to even if C=1 too
+  bx      lr                    // and now return unconditionally
+
+LOCAL_LABEL(uncommon):
+  // We come here if anything at all goes wrong on the fast path. We could have
+  // an interesting kind of input - zero, denormal, infinity or NaN - or we
+  // could have a normalized double-precision input too large or too small to
+  // yield a normalized single-precision output.
+  //
+  // Of the various cases, the most important one to handle quickly is a zero
+  // input, because those are probably fairly common. So the very first thing
+  // we do is test if the input is zero, and if so, return the same sign of
+  // zero by simply using xh as the return value.
+  orrs    r12, xl, xh, lsl #1   // are all bits of xh:xl 0 except the sign bit?
+
+#ifndef __BIG_ENDIAN__
+  // In little-endian, xh (containing the desired sign bit) and r0 (the output
+  // register) aren't the same. This instruction can be skipped in big-endian,
+  // where the correct output value is already in r0.
+  moveq   r0, xh
+#endif
+  bxeq    lr
+
+  // Separate the remaining cases into three types: too small (underflow,
+  // whether or not the input was a denormal), too big (overflow or input
+  // infinity, which we treat the same in the absence of FP exceptions), and
+  // NaN.
+  //
+  // At this stage r2 contains the output exponent, rebiased to its
+  // single-precision value, but at bit 20 (that is, still in the
+  // double-precision position). Detect underflow by doing a signed comparison
+  // against the minimum normalized single-precision exponent.
+  cmp     r2, #0x00100000
+  blt     LOCAL_LABEL(underflow)
+
+  // Now figure out whether we had a NaN as input, by shifting xh left by a bit
+  // (discarding the sign) and setting the new low bit if xl != 0. This gives a
+  // value which is greater than 0xFFE00000 (in an unsigned comparison) for
+  // precisely NaN inputs.
+  cmp     xl, #1                // set C if xl != 0
+  adc     r12, xh, xh           // shift that in to the bottom of xh
+  cmn     r12, #0x00200000      // is the result > 0xFFE00000?
+  bhi     LOCAL_LABEL(nan)               // if so, go and handle a NaN
+
+  // If we're still here, we have a finite overflow, or an input infinity. We
+  // don't have to figure out which: we return an infinity of the appropriate
+  // sign in both cases. So keep just the sign of xh, and make an infinity out
+  // of the rest of the bits.
+  mvn     r0, xh, lsr #31       // shift sign bit down to bit 0 and flip it
+  mvn     r0, r0, lsl #8        // flip it back, putting 8 set bits below it
+  lsl     r0, r0, #23           // and shift those 9 bits back up to the top
+  bx      lr
+
+LOCAL_LABEL(nan):
+  // We have a double-precision NaN input. The Arm NaN handling rules say that
+  // we make the output single-precision NaN by keeping the sign and as much of
+  // the mantissa as possible (starting from the top bit). But we also set the
+  // top bit of the mantissa, which makes the output NaN quiet even if the
+  // input one was signaling.
+  //
+  // So this code looks a bit like a miniature version of the fast path: we
+  // keep the bottom 8 bits of the exponent in xh as the output exponent (we
+  // know it's all 1s, which is what we want), plus all the mantissa bits below
+  // it; shift all of that 3 bits left and recombine with the sign; then
+  // combine with the top 3 bits of xl. Finally, set the top mantissa bit.
+  bic     r2, xh, #0xF0000000   // everything from xh we want to shift left
+  orr     r0, r3, xl, lsr #29   // combine sign with low 3 output mantissa bits
+  orr     r0, r0, r2, lsl #3    // combine that with the shifted-up value in r2
+  orr     r0, r0, #0x00400000   // set the top mantissa bit to make it a QNaN
+  bx      lr
+
+LOCAL_LABEL(underflow):
+  // We have an input value small enough to underflow. The basic strategy is to
+  // leave __funder to deal with the details.
+  //
+  // Normally __funder expects to get a value that's already been rounded, and
+  // will re-round it, for which it also needs to know which way the value has
+  // been rounded already. In this case we haven't rounded _yet_. Rather than
+  // carefully rounding to nearest, it's easier to just make the __funder input
+  // value by truncating the mantissa (i.e. round towards zero), and set the
+  // rounding direction accordingly.
+
+  // Rebias the exponent (again) to make an IEEE 754 underflow intermediate. If
+  // this still doesn't make r2 positive, then the result is so small that it
+  // will underflow to 0 anyway, so it doesn't really matter what exponent we
+  // do provide - we just clear the top 8 bits of r2 to ensure the sign is
+  // right and the exponent is _something_ small.
+  adds    r2, r2, #0x0c000000   // exponent bias (still shifted down 3 bits)
+  bicmi   r2, r2, #0xff000000   // handle exponent still being negative
+
+  // Test the bits we're going to shift off the mantissa, to see if any are
+  // zero. This will determine the rounding direction we pass to __funder,
+  // because although we never round _up_ on this path, we must still tell it
+  // whether the value we pass it was rounded down or was already exact.
+  lsls    r12, xl, #3           // set Z if the intermediate value is exact
+
+  // Put together the intermediate value to pass to __funder.
+  orr     r2, r3, r2, lsl #3    // sign + exponent + most of mantissa
+  orr     r0, r2, xl, lsr #29   // combine with top 3 bits of xl
+
+  // Set the rounding direction flag based on the test above.
+  moveq   r1, #0                // intermediate is exact
+  movne   r1, #1                // intermediate is too small (we didn't round)
+
+  // And tailcall __funder to do the rest of the job.
+  b       SYMBOL_NAME(__compiler_rt_funder)
+
+END_COMPILERRT_FUNCTION(__aeabi_d2f)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c b/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
new file mode 100644
index 0000000000000..04446488f73bf
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
@@ -0,0 +1,123 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_extendsfdf2
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test uses compareResultD to check the returned floats, which
+// accepts any returned NaN if the expected result is the canonical NaN value
+// 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
+// to a more detailed handling of NaNs, we tighten up the check and include
+// some extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#  define EXPECT_EXACT_RESULTS
+#  define ARM_NAN_HANDLING
+#endif
+
+// Returns: a converted from float to double
+COMPILER_RT_ABI double __extendsfdf2(float a);
+
+int test__extendsfdf2(int line, uint32_t a_rep, uint64_t expected_rep) {
+  float a = fromRep32(a_rep);
+  double x = __extendsfdf2(a);
+#ifdef EXPECT_EXACT_RESULTS
+  int ret = toRep64(x) != expected_rep;
+#else
+  int ret = compareResultD(x, expected_rep);
+#endif
+
+  if (ret) {
+    printf("error at line %d: __extendsfdf2(%08" PRIx32 ") = %016" PRIx64
+           ", expected %016" PRIx64 "\n",
+           line, a_rep, toRep64(x), expected_rep);
+  }
+  return ret;
+}
+
+#define test__extendsfdf2(a,x) test__extendsfdf2(__LINE__,a,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__extendsfdf2(0x00000001, 0x36a0000000000000);
+  status |= test__extendsfdf2(0x00000003, 0x36b8000000000000);
+  status |= test__extendsfdf2(0x00000005, 0x36c4000000000000);
+  status |= test__extendsfdf2(0x00000009, 0x36d2000000000000);
+  status |= test__extendsfdf2(0x00000011, 0x36e1000000000000);
+  status |= test__extendsfdf2(0x00000021, 0x36f0800000000000);
+  status |= test__extendsfdf2(0x00000041, 0x3700400000000000);
+  status |= test__extendsfdf2(0x00000081, 0x3710200000000000);
+  status |= test__extendsfdf2(0x00000101, 0x3720100000000000);
+  status |= test__extendsfdf2(0x00000201, 0x3730080000000000);
+  status |= test__extendsfdf2(0x00000401, 0x3740040000000000);
+  status |= test__extendsfdf2(0x00000801, 0x3750020000000000);
+  status |= test__extendsfdf2(0x00001001, 0x3760010000000000);
+  status |= test__extendsfdf2(0x00002001, 0x3770008000000000);
+  status |= test__extendsfdf2(0x00004001, 0x3780004000000000);
+  status |= test__extendsfdf2(0x00008001, 0x3790002000000000);
+  status |= test__extendsfdf2(0x00010001, 0x37a0001000000000);
+  status |= test__extendsfdf2(0x00020001, 0x37b0000800000000);
+  status |= test__extendsfdf2(0x00040001, 0x37c0000400000000);
+  status |= test__extendsfdf2(0x00080001, 0x37d0000200000000);
+  status |= test__extendsfdf2(0x00100001, 0x37e0000100000000);
+  status |= test__extendsfdf2(0x00200001, 0x37f0000080000000);
+  status |= test__extendsfdf2(0x00400001, 0x3800000040000000);
+  status |= test__extendsfdf2(0x00800001, 0x3810000020000000);
+  status |= test__extendsfdf2(0x01000001, 0x3820000020000000);
+  status |= test__extendsfdf2(0x20000001, 0x3c00000020000000);
+  status |= test__extendsfdf2(0x30000001, 0x3e00000020000000);
+  status |= test__extendsfdf2(0x3f800000, 0x3ff0000000000000);
+  status |= test__extendsfdf2(0x7f000000, 0x47e0000000000000);
+  status |= test__extendsfdf2(0x7f7fffff, 0x47efffffe0000000);
+  status |= test__extendsfdf2(0x7f800000, 0x7ff0000000000000);
+  status |= test__extendsfdf2(0xff000000, 0xc7e0000000000000);
+  status |= test__extendsfdf2(0xff7fffff, 0xc7efffffe0000000);
+  status |= test__extendsfdf2(0xff800000, 0xfff0000000000000);
+  status |= test__extendsfdf2(0x80800000, 0xb810000000000000);
+  status |= test__extendsfdf2(0x807fffff, 0xb80fffffc0000000);
+  status |= test__extendsfdf2(0x80400000, 0xb800000000000000);
+  status |= test__extendsfdf2(0x803fffff, 0xb7ffffff80000000);
+  status |= test__extendsfdf2(0x80000003, 0xb6b8000000000000);
+  status |= test__extendsfdf2(0x80000002, 0xb6b0000000000000);
+  status |= test__extendsfdf2(0x80000001, 0xb6a0000000000000);
+  status |= test__extendsfdf2(0x80000000, 0x8000000000000000);
+
+  // Test that the result of an operation is a NaN at all when it should be.
+  //
+  // In most configurations these tests' results are checked compared using
+  // compareResultD, so we set all the answers to the canonical NaN
+  // 0x7ff8000000000000, which causes compareResultF to accept any NaN
+  // encoding. We also use the same value as the input NaN in tests that have
+  // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
+  // because 0x7ff8000000000000 is still the exact expected NaN.
+  status |= test__extendsfdf2(0x7fc00000, 0x7ff8000000000000);
+
+#ifdef ARM_NAN_HANDLING
+  // Tests specific to the NaN handling of Arm hardware, mimicked by
+  // arm/extendsfdf2.S:
+  //
+  //  - a quiet NaN is distinguished by the top mantissa bit being 1
+  //
+  //  - converting a quiet NaN from float to double is done by copying
+  //    the input mantissa bits to the top of the output mantissa and
+  //    appending 0 bits below them
+  //
+  //  - if the input is a signalling NaN, its top mantissa bit is set
+  //    to turn it quiet, and then that quiet NaN is converted to
+  //    double as above
+  status |= test__extendsfdf2(0x7faf53b1, 0x7ffdea7620000000);
+  status |= test__extendsfdf2(0x7fe111d3, 0x7ffc223a60000000);
+  status |= test__extendsfdf2(0xffaf53b1, 0xfffdea7620000000);
+  status |= test__extendsfdf2(0xffe111d3, 0xfffc223a60000000);
+
+#endif // ARM_NAN_HANDLING
+
+  return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c b/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
new file mode 100644
index 0000000000000..0542f97643618
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
@@ -0,0 +1,367 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_truncdfsf2
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test uses compareResultF to check the returned floats, which
+// accepts any returned NaN if the expected result is the canonical NaN value
+// 0x7fc00000. For the Arm optimized FP implementation, which commits to a more
+// detailed handling of NaNs, we tighten up the check and include some extra
+// test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#  define EXPECT_EXACT_RESULTS
+#  define ARM_NAN_HANDLING
+#endif
+
+// Returns: a converted from double to float
+COMPILER_RT_ABI float __truncdfsf2(double a);
+
+int test__truncdfsf2(int line, uint64_t a_rep, uint32_t expected_rep) {
+  double a = fromRep64(a_rep);
+  float x = __truncdfsf2(a);
+#ifdef EXPECT_EXACT_RESULTS
+  int ret = toRep32(x) != expected_rep;
+#else
+  int ret = compareResultF(x, expected_rep);
+#endif
+
+  if (ret) {
+    printf("error at line %d: __truncdfsf2(%016" PRIx64 ") = %08" PRIx32
+           ", expected %08" PRIx32 "\n",
+           line, a_rep, toRep32(x), expected_rep);
+  }
+  return ret;
+}
+
+#define test__truncdfsf2(a,x) test__truncdfsf2(__LINE__,a,x)
+
+int main(void) {
+  int status = 0;
+
+  status |= test__truncdfsf2(0x0000000000000001, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000002, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000004, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000008, 0x00000000);
+  status |= test__truncdfsf2(0x000000000000001a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000020, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000040, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000080, 0x00000000);
+  status |= test__truncdfsf2(0x000000000000019a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000200, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000400, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000000800, 0x00000000);
+  status |= test__truncdfsf2(0x000000000000189a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000002000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000004000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000008000, 0x00000000);
+  status |= test__truncdfsf2(0x000000000001789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000020000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000040000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000080000, 0x00000000);
+  status |= test__truncdfsf2(0x000000000016789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000200000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000400000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000000800000, 0x00000000);
+  status |= test__truncdfsf2(0x000000000156789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000002000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000004000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000008000000, 0x00000000);
+  status |= test__truncdfsf2(0x000000001456789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000020000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000040000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000080000000, 0x00000000);
+  status |= test__truncdfsf2(0x000000013465789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000000200000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000400000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000000800000000, 0x00000000);
+  status |= test__truncdfsf2(0x000000123456789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000002000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000004000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000008000000000, 0x00000000);
+  status |= test__truncdfsf2(0x000001123456789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000020000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000040000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000080000000000, 0x00000000);
+  status |= test__truncdfsf2(0x000010123456789a, 0x00000000);
+  status |= test__truncdfsf2(0x0000200000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000400000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0000800000000000, 0x00000000);
+  status |= test__truncdfsf2(0x000100123456789a, 0x00000000);
+  status |= test__truncdfsf2(0x0002000000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0004000000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0008000000000000, 0x00000000);
+  status |= test__truncdfsf2(0x0010000000000000, 0x00000000);
+  status |= test__truncdfsf2(0x36a0000000000000, 0x00000001);
+  status |= test__truncdfsf2(0x36b0000000000000, 0x00000002);
+  status |= test__truncdfsf2(0x36b2000000000000, 0x00000002);
+  status |= test__truncdfsf2(0x36b4000000000000, 0x00000002);
+  status |= test__truncdfsf2(0x36b6000000000000, 0x00000003);
+  status |= test__truncdfsf2(0x36b8000000000000, 0x00000003);
+  status |= test__truncdfsf2(0x36ba000000000000, 0x00000003);
+  status |= test__truncdfsf2(0x36bc000000000000, 0x00000004);
+  status |= test__truncdfsf2(0x36be000000000000, 0x00000004);
+  status |= test__truncdfsf2(0x36c0000000000000, 0x00000004);
+  status |= test__truncdfsf2(0x36c1000000000000, 0x00000004);
+  status |= test__truncdfsf2(0x36c2000000000000, 0x00000004);
+  status |= test__truncdfsf2(0x36c3000000000000, 0x00000005);
+  status |= test__truncdfsf2(0x36c4000000000000, 0x00000005);
+  status |= test__truncdfsf2(0x36c5000000000000, 0x00000005);
+  status |= test__truncdfsf2(0x36c6000000000000, 0x00000006);
+  status |= test__truncdfsf2(0x36c7000000000000, 0x00000006);
+  status |= test__truncdfsf2(0x36d0000000000000, 0x00000008);
+  status |= test__truncdfsf2(0x36d0800000000000, 0x00000008);
+  status |= test__truncdfsf2(0x36d1000000000000, 0x00000008);
+  status |= test__truncdfsf2(0x36d1800000000000, 0x00000009);
+  status |= test__truncdfsf2(0x36d2000000000000, 0x00000009);
+  status |= test__truncdfsf2(0x36d2800000000000, 0x00000009);
+  status |= test__truncdfsf2(0x36d3000000000000, 0x0000000a);
+  status |= test__truncdfsf2(0x36d3800000000000, 0x0000000a);
+  status |= test__truncdfsf2(0x36e0000000000000, 0x00000010);
+  status |= test__truncdfsf2(0x36e0400000000000, 0x00000010);
+  status |= test__truncdfsf2(0x36e0800000000000, 0x00000010);
+  status |= test__truncdfsf2(0x36e0c00000000000, 0x00000011);
+  status |= test__truncdfsf2(0x36e1000000000000, 0x00000011);
+  status |= test__truncdfsf2(0x36e1400000000000, 0x00000011);
+  status |= test__truncdfsf2(0x36e1800000000000, 0x00000012);
+  status |= test__truncdfsf2(0x36e1c00000000000, 0x00000012);
+  status |= test__truncdfsf2(0x36f0000000000000, 0x00000020);
+  status |= test__truncdfsf2(0x36f0200000000000, 0x00000020);
+  status |= test__truncdfsf2(0x36f0400000000000, 0x00000020);
+  status |= test__truncdfsf2(0x36f0600000000000, 0x00000021);
+  status |= test__truncdfsf2(0x36f0800000000000, 0x00000021);
+  status |= test__truncdfsf2(0x36f0a00000000000, 0x00000021);
+  status |= test__truncdfsf2(0x36f0c00000000000, 0x00000022);
+  status |= test__truncdfsf2(0x36f0e00000000000, 0x00000022);
+  status |= test__truncdfsf2(0x3700000000000000, 0x00000040);
+  status |= test__truncdfsf2(0x3700100000000000, 0x00000040);
+  status |= test__truncdfsf2(0x3700200000000000, 0x00000040);
+  status |= test__truncdfsf2(0x3700300000000000, 0x00000041);
+  status |= test__truncdfsf2(0x3700400000000000, 0x00000041);
+  status |= test__truncdfsf2(0x3700500000000000, 0x00000041);
+  status |= test__truncdfsf2(0x3700600000000000, 0x00000042);
+  status |= test__truncdfsf2(0x3700700000000000, 0x00000042);
+  status |= test__truncdfsf2(0x3710000000000000, 0x00000080);
+  status |= test__truncdfsf2(0x3710080000000000, 0x00000080);
+  status |= test__truncdfsf2(0x3710100000000000, 0x00000080);
+  status |= test__truncdfsf2(0x3710180000000000, 0x00000081);
+  status |= test__truncdfsf2(0x3710200000000000, 0x00000081);
+  status |= test__truncdfsf2(0x3710280000000000, 0x00000081);
+  status |= test__truncdfsf2(0x3710300000000000, 0x00000082);
+  status |= test__truncdfsf2(0x3710380000000000, 0x00000082);
+  status |= test__truncdfsf2(0x3720000000000000, 0x00000100);
+  status |= test__truncdfsf2(0x3720040000000000, 0x00000100);
+  status |= test__truncdfsf2(0x3720080000000000, 0x00000100);
+  status |= test__truncdfsf2(0x37200c0000000000, 0x00000101);
+  status |= test__truncdfsf2(0x3720100000000000, 0x00000101);
+  status |= test__truncdfsf2(0x3720140000000000, 0x00000101);
+  status |= test__truncdfsf2(0x3720180000000000, 0x00000102);
+  status |= test__truncdfsf2(0x37201c0000000000, 0x00000102);
+  status |= test__truncdfsf2(0x3730000000000000, 0x00000200);
+  status |= test__truncdfsf2(0x3730020000000000, 0x00000200);
+  status |= test__truncdfsf2(0x3730040000000000, 0x00000200);
+  status |= test__truncdfsf2(0x3730060000000000, 0x00000201);
+  status |= test__truncdfsf2(0x3730080000000000, 0x00000201);
+  status |= test__truncdfsf2(0x37300a0000000000, 0x00000201);
+  status |= test__truncdfsf2(0x37300c0000000000, 0x00000202);
+  status |= test__truncdfsf2(0x37300e0000000000, 0x00000202);
+  status |= test__truncdfsf2(0x3740000000000000, 0x00000400);
+  status |= test__truncdfsf2(0x3740010000000000, 0x00000400);
+  status |= test__truncdfsf2(0x3740020000000000, 0x00000400);
+  status |= test__truncdfsf2(0x3740030000000000, 0x00000401);
+  status |= test__truncdfsf2(0x3740040000000000, 0x00000401);
+  status |= test__truncdfsf2(0x3740050000000000, 0x00000401);
+  status |= test__truncdfsf2(0x3740060000000000, 0x00000402);
+  status |= test__truncdfsf2(0x3740070000000000, 0x00000402);
+  status |= test__truncdfsf2(0x3750000000000000, 0x00000800);
+  status |= test__truncdfsf2(0x3750008000000000, 0x00000800);
+  status |= test__truncdfsf2(0x3750010000000000, 0x00000800);
+  status |= test__truncdfsf2(0x3750018000000000, 0x00000801);
+  status |= test__truncdfsf2(0x3750020000000000, 0x00000801);
+  status |= test__truncdfsf2(0x3750028000000000, 0x00000801);
+  status |= test__truncdfsf2(0x3750030000000000, 0x00000802);
+  status |= test__truncdfsf2(0x3750038000000000, 0x00000802);
+  status |= test__truncdfsf2(0x3760000000000000, 0x00001000);
+  status |= test__truncdfsf2(0x3760004000000000, 0x00001000);
+  status |= test__truncdfsf2(0x3760008000000000, 0x00001000);
+  status |= test__truncdfsf2(0x376000c000000000, 0x00001001);
+  status |= test__truncdfsf2(0x3760010000000000, 0x00001001);
+  status |= test__truncdfsf2(0x3760014000000000, 0x00001001);
+  status |= test__truncdfsf2(0x3760018000000000, 0x00001002);
+  status |= test__truncdfsf2(0x376001c000000000, 0x00001002);
+  status |= test__truncdfsf2(0x3770000000000000, 0x00002000);
+  status |= test__truncdfsf2(0x3770002000000000, 0x00002000);
+  status |= test__truncdfsf2(0x3770004000000000, 0x00002000);
+  status |= test__truncdfsf2(0x3770006000000000, 0x00002001);
+  status |= test__truncdfsf2(0x3770008000000000, 0x00002001);
+  status |= test__truncdfsf2(0x377000a000000000, 0x00002001);
+  status |= test__truncdfsf2(0x377000c000000000, 0x00002002);
+  status |= test__truncdfsf2(0x377000e000000000, 0x00002002);
+  status |= test__truncdfsf2(0x3780000000000000, 0x00004000);
+  status |= test__truncdfsf2(0x3780001000000000, 0x00004000);
+  status |= test__truncdfsf2(0x3780002000000000, 0x00004000);
+  status |= test__truncdfsf2(0x3780003000000000, 0x00004001);
+  status |= test__truncdfsf2(0x3780004000000000, 0x00004001);
+  status |= test__truncdfsf2(0x3780005000000000, 0x00004001);
+  status |= test__truncdfsf2(0x3780006000000000, 0x00004002);
+  status |= test__truncdfsf2(0x3780007000000000, 0x00004002);
+  status |= test__truncdfsf2(0x3790000000000000, 0x00008000);
+  status |= test__truncdfsf2(0x3790000800000000, 0x00008000);
+  status |= test__truncdfsf2(0x3790001000000000, 0x00008000);
+  status |= test__truncdfsf2(0x3790001800000000, 0x00008001);
+  status |= test__truncdfsf2(0x3790002000000000, 0x00008001);
+  status |= test__truncdfsf2(0x3790002800000000, 0x00008001);
+  status |= test__truncdfsf2(0x3790003000000000, 0x00008002);
+  status |= test__truncdfsf2(0x3790003800000000, 0x00008002);
+  status |= test__truncdfsf2(0x37a0000000000000, 0x00010000);
+  status |= test__truncdfsf2(0x37a0000400000000, 0x00010000);
+  status |= test__truncdfsf2(0x37a0000800000000, 0x00010000);
+  status |= test__truncdfsf2(0x37a0000c00000000, 0x00010001);
+  status |= test__truncdfsf2(0x37a0001000000000, 0x00010001);
+  status |= test__truncdfsf2(0x37a0001400000000, 0x00010001);
+  status |= test__truncdfsf2(0x37a0001800000000, 0x00010002);
+  status |= test__truncdfsf2(0x37a0001c00000000, 0x00010002);
+  status |= test__truncdfsf2(0x37b0000000000000, 0x00020000);
+  status |= test__truncdfsf2(0x37b0000200000000, 0x00020000);
+  status |= test__truncdfsf2(0x37b0000400000000, 0x00020000);
+  status |= test__truncdfsf2(0x37b0000600000000, 0x00020001);
+  status |= test__truncdfsf2(0x37b0000800000000, 0x00020001);
+  status |= test__truncdfsf2(0x37b0000a00000000, 0x00020001);
+  status |= test__truncdfsf2(0x37b0000c00000000, 0x00020002);
+  status |= test__truncdfsf2(0x37b0000e00000000, 0x00020002);
+  status |= test__truncdfsf2(0x37c0000000000000, 0x00040000);
+  status |= test__truncdfsf2(0x37c0000100000000, 0x00040000);
+  status |= test__truncdfsf2(0x37c0000200000000, 0x00040000);
+  status |= test__truncdfsf2(0x37c0000300000000, 0x00040001);
+  status |= test__truncdfsf2(0x37c0000400000000, 0x00040001);
+  status |= test__truncdfsf2(0x37c0000500000000, 0x00040001);
+  status |= test__truncdfsf2(0x37c0000600000000, 0x00040002);
+  status |= test__truncdfsf2(0x37c0000700000000, 0x00040002);
+  status |= test__truncdfsf2(0x37d0000000000000, 0x00080000);
+  status |= test__truncdfsf2(0x37d0000080000000, 0x00080000);
+  status |= test__truncdfsf2(0x37d0000100000000, 0x00080000);
+  status |= test__truncdfsf2(0x37d0000180000000, 0x00080001);
+  status |= test__truncdfsf2(0x37d0000200000000, 0x00080001);
+  status |= test__truncdfsf2(0x37d0000280000000, 0x00080001);
+  status |= test__truncdfsf2(0x37d0000300000000, 0x00080002);
+  status |= test__truncdfsf2(0x37d0000380000000, 0x00080002);
+  status |= test__truncdfsf2(0x37e0000000000000, 0x00100000);
+  status |= test__truncdfsf2(0x37e0000040000000, 0x00100000);
+  status |= test__truncdfsf2(0x37e0000080000000, 0x00100000);
+  status |= test__truncdfsf2(0x37e00000c0000000, 0x00100001);
+  status |= test__truncdfsf2(0x37e0000100000000, 0x00100001);
+  status |= test__truncdfsf2(0x37e0000140000000, 0x00100001);
+  status |= test__truncdfsf2(0x37e0000180000000, 0x00100002);
+  status |= test__truncdfsf2(0x37e00001c0000000, 0x00100002);
+  status |= test__truncdfsf2(0x37f0000000000000, 0x00200000);
+  status |= test__truncdfsf2(0x37f0000020000000, 0x00200000);
+  status |= test__truncdfsf2(0x37f000003fffffff, 0x00200000);
+  status |= test__truncdfsf2(0x37f0000040000000, 0x00200000);
+  status |= test__truncdfsf2(0x37f0000040000001, 0x00200001);
+  status |= test__truncdfsf2(0x37f0000060000000, 0x00200001);
+  status |= test__truncdfsf2(0x37f0000080000000, 0x00200001);
+  status |= test__truncdfsf2(0x37f00000a0000000, 0x00200001);
+  status |= test__truncdfsf2(0x37f00000bfffffff, 0x00200001);
+  status |= test__truncdfsf2(0x37f00000c0000000, 0x00200002);
+  status |= test__truncdfsf2(0x37f00000c0000001, 0x00200002);
+  status |= test__truncdfsf2(0x37f00000e0000000, 0x00200002);
+  status |= test__truncdfsf2(0x3800000000000000, 0x00400000);
+  status |= test__truncdfsf2(0x3800000010000000, 0x00400000);
+  status |= test__truncdfsf2(0x3800000020000000, 0x00400000);
+  status |= test__truncdfsf2(0x3800000030000000, 0x00400001);
+  status |= test__truncdfsf2(0x3800000040000000, 0x00400001);
+  status |= test__truncdfsf2(0x3800000050000000, 0x00400001);
+  status |= test__truncdfsf2(0x3800000060000000, 0x00400002);
+  status |= test__truncdfsf2(0x3800000070000000, 0x00400002);
+  status |= test__truncdfsf2(0x380fffffffffffff, 0x00800000);
+  status |= test__truncdfsf2(0x3810000000000000, 0x00800000);
+  status |= test__truncdfsf2(0x3810000008000000, 0x00800000);
+  status |= test__truncdfsf2(0x3810000010000000, 0x00800000);
+  status |= test__truncdfsf2(0x3810000018000000, 0x00800001);
+  status |= test__truncdfsf2(0x3810000020000000, 0x00800001);
+  status |= test__truncdfsf2(0x3810000028000000, 0x00800001);
+  status |= test__truncdfsf2(0x3810000030000000, 0x00800002);
+  status |= test__truncdfsf2(0x3810000038000000, 0x00800002);
+  status |= test__truncdfsf2(0x3ff0000000000000, 0x3f800000);
+  status |= test__truncdfsf2(0x3ff0000008000000, 0x3f800000);
+  status |= test__truncdfsf2(0x3ff0000010000000, 0x3f800000);
+  status |= test__truncdfsf2(0x3ff0000018000000, 0x3f800001);
+  status |= test__truncdfsf2(0x3ff0000028000000, 0x3f800001);
+  status |= test__truncdfsf2(0x3ff0000030000000, 0x3f800002);
+  status |= test__truncdfsf2(0x3ff0000038000000, 0x3f800002);
+  status |= test__truncdfsf2(0x4000000000000000, 0x40000000);
+  status |= test__truncdfsf2(0x47efffffe8000000, 0x7f7fffff);
+  status |= test__truncdfsf2(0x47effffff0000000, 0x7f800000);
+  status |= test__truncdfsf2(0x47effffff8000000, 0x7f800000);
+  status |= test__truncdfsf2(0x7fc0000000000000, 0x7f800000);
+  status |= test__truncdfsf2(0x7ff0000000000000, 0x7f800000);
+  status |= test__truncdfsf2(0x8010000000000000, 0x80000000);
+  status |= test__truncdfsf2(0xbff0000008000000, 0xbf800000);
+  status |= test__truncdfsf2(0xbff0000010000000, 0xbf800000);
+  status |= test__truncdfsf2(0xbff0000018000000, 0xbf800001);
+  status |= test__truncdfsf2(0xbff0000028000000, 0xbf800001);
+  status |= test__truncdfsf2(0xbff0000030000000, 0xbf800002);
+  status |= test__truncdfsf2(0xbff0000038000000, 0xbf800002);
+  status |= test__truncdfsf2(0xc024000000000000, 0xc1200000);
+  status |= test__truncdfsf2(0xc7efffffe8000000, 0xff7fffff);
+  status |= test__truncdfsf2(0xc7effffff0000000, 0xff800000);
+  status |= test__truncdfsf2(0xc7effffff8000000, 0xff800000);
+  status |= test__truncdfsf2(0xffc0000000000000, 0xff800000);
+  status |= test__truncdfsf2(0xfff0000000000000, 0xff800000);
+  status |= test__truncdfsf2(0x3780000000000000, 0x00004000);
+  status |= test__truncdfsf2(0xb780000000000000, 0x80004000);
+  status |= test__truncdfsf2(0x0000000080000000, 0x00000000);
+  status |= test__truncdfsf2(0x8000000080000000, 0x80000000);
+  status |= test__truncdfsf2(0x380ffffff0000000, 0x00800000);
+  status |= test__truncdfsf2(0x380fffffd0000000, 0x007fffff);
+  status |= test__truncdfsf2(0x380fffffe8000000, 0x00800000);
+  status |= test__truncdfsf2(0x380fffffc8000000, 0x007fffff);
+  status |= test__truncdfsf2(0xb80ffffff0000000, 0x80800000);
+  status |= test__truncdfsf2(0xb80fffffd0000000, 0x807fffff);
+  status |= test__truncdfsf2(0xb80fffffe8000000, 0x80800000);
+  status |= test__truncdfsf2(0xb80fffffc8000000, 0x807fffff);
+  status |= test__truncdfsf2(0x0000000000000000, 0x00000000);
+  status |= test__truncdfsf2(0x8000000000000000, 0x80000000);
+  status |= test__truncdfsf2(0xc7e0000010000000, 0xff000000);
+
+  // Test that the result of an operation is a NaN at all when it should be.
+  //
+  // In most configurations these tests' results are checked compared using
+  // compareResultF, so we set all the answers to the canonical NaN 0x7fc00000,
+  // which causes compareResultF to accept any NaN encoding. We also use the
+  // same value as the input NaN in tests that have one, so that even in
+  // EXPECT_EXACT_RESULTS mode these tests should pass, because 0x7fc00000 is
+  // still the exact expected NaN.
+  status |= test__truncdfsf2(0x7ff8000000000000, 0x7fc00000);
+
+#ifdef ARM_NAN_HANDLING
+  // Tests specific to the NaN handling of Arm hardware, mimicked by
+  // arm/truncdfsf2.S:
+  //
+  //  - a quiet NaN is distinguished by the top mantissa bit being 1
+  //
+  //  - converting a quiet NaN from double to float is done by keeping
+  //    the topmost 23 bits of the mantissa and discarding the lower
+  //    ones
+  //
+  //  - if the input is a signalling NaN, its top mantissa bit is set
+  //    to turn it quiet, and then that quiet NaN is converted to
+  //    float as above
+  status |= test__truncdfsf2(0x7ff0000000000001, 0x7fc00000);
+  status |= test__truncdfsf2(0x7ff753b1887bcf03, 0x7ffa9d8c);
+  status |= test__truncdfsf2(0x7ff911d3c0abfdda, 0x7fc88e9e);
+  status |= test__truncdfsf2(0xfff0000000000001, 0xffc00000);
+  status |= test__truncdfsf2(0xfff753b1887bcf03, 0xfffa9d8c);
+  status |= test__truncdfsf2(0xfff911d3c0abfdda, 0xffc88e9e);
+
+#endif // ARM_NAN_HANDLING
+
+  return status;
+}

>From 749a5b2a141e47faa14c16624f2bcea7d01182ca Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 13:46:32 +0000
Subject: [PATCH 09/33] clang-format

---
 compiler-rt/test/builtins/Unit/divsf3_test.c | 9 +++++----
 compiler-rt/test/builtins/Unit/mulsf3_test.c | 9 +++++----
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/divsf3_test.c b/compiler-rt/test/builtins/Unit/divsf3_test.c
index c335c22c77243..a2d823fec840b 100644
--- a/compiler-rt/test/builtins/Unit/divsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/divsf3_test.c
@@ -24,7 +24,8 @@
 // Returns: a / b
 COMPILER_RT_ABI float __divsf3(float a, float b);
 
-int test__divsf3(int line, uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep) {
+int test__divsf3(int line, uint32_t a_rep, uint32_t b_rep,
+                 uint32_t expected_rep) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
   float x = __divsf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -34,14 +35,14 @@ int test__divsf3(int line, uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep
 #endif
 
   if (ret) {
-    printf("error at line %d: __divsf3(%08" PRIx32 ", %08" PRIx32 ") = %08" PRIx32
-           ", expected %08" PRIx32 "\n",
+    printf("error at line %d: __divsf3(%08" PRIx32 ", %08" PRIx32
+           ") = %08" PRIx32 ", expected %08" PRIx32 "\n",
            line, a_rep, b_rep, toRep32(x), expected_rep);
   }
   return ret;
 }
 
-#define test__divsf3(a,b,x) test__divsf3(__LINE__,a,b,x)
+#define test__divsf3(a, b, x) test__divsf3(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/mulsf3_test.c b/compiler-rt/test/builtins/Unit/mulsf3_test.c
index 8460a8c117aa5..42bee8a60ff58 100644
--- a/compiler-rt/test/builtins/Unit/mulsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/mulsf3_test.c
@@ -24,7 +24,8 @@
 // Returns: a * b
 COMPILER_RT_ABI float __mulsf3(float a, float b);
 
-int test__mulsf3(int line, uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep) {
+int test__mulsf3(int line, uint32_t a_rep, uint32_t b_rep,
+                 uint32_t expected_rep) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
   float x = __mulsf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -34,14 +35,14 @@ int test__mulsf3(int line, uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep
 #endif
 
   if (ret) {
-    printf("error at line %d: __mulsf3(%08" PRIx32 ", %08" PRIx32 ") = %08" PRIx32
-           ", expected %08" PRIx32 "\n",
+    printf("error at line %d: __mulsf3(%08" PRIx32 ", %08" PRIx32
+           ") = %08" PRIx32 ", expected %08" PRIx32 "\n",
            line, a_rep, b_rep, toRep32(x), expected_rep);
   }
   return ret;
 }
 
-#define test__mulsf3(a,b,x) test__mulsf3(__LINE__,a,b,x)
+#define test__mulsf3(a, b, x) test__mulsf3(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;

>From fea8e45575ab02aa0a0c76c85593da6edd5932f9 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:08:24 +0000
Subject: [PATCH 10/33] Move property-setting into a function

This is more concise at each call site, but more importantly, gives me
a place to check `COMPILER_RT_BUILTINS_STANDALONE_BUILD`.
---
 compiler-rt/lib/builtins/CMakeLists.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index f43ef4743ff97..c1a0ffc0fe2da 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -57,6 +57,19 @@ if (COMPILER_RT_STANDALONE_BUILD)
     ON)
 endif()
 
+function(set_special_properties source_file)
+  cmake_parse_arguments(ARG "" "SUPERSEDES;PROVIDES" "" ${ARGN})
+  if(ARG_SUPERSEDES)
+    set_property(SOURCE ${source_file}
+      PROPERTY crt_supersedes ${ARG_SUPERSEDES})
+  endif()
+  if(ARG_PROVIDES AND NOT COMPILER_RT_BUILTINS_STANDALONE_BUILD)
+    set_property(SOURCE ${source_file}
+      DIRECTORY ${COMPILER_RT_SOURCE_DIR}
+      PROPERTY crt_provides ${ARG_PROVIDES})
+  endif()
+endfunction()
+
 include(builtin-config-ix)
 include(CMakeDependentOption)
 include(CMakePushCheckState)

>From 4c5cccbd70ce96f282d16fe4e1d3dc074b259597 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:16:46 +0000
Subject: [PATCH 11/33] clang-format fixes

---
 compiler-rt/lib/builtins/arm/dnan2.c  | 2 +-
 compiler-rt/lib/builtins/arm/endian.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/compiler-rt/lib/builtins/arm/dnan2.c b/compiler-rt/lib/builtins/arm/dnan2.c
index 3b3bb50d3f587..9f788f170b455 100644
--- a/compiler-rt/lib/builtins/arm/dnan2.c
+++ b/compiler-rt/lib/builtins/arm/dnan2.c
@@ -40,6 +40,6 @@ uint64_t __compiler_rt_dnan2(uint64_t a, uint64_t b) {
     return b | 0x0008000000000000; //   if so, return it with the quiet bit set
   if (aadj < 0x0010000000000000)   // a is a quiet NaN?
     return a;                      // if so, return it
-  else /* expect (badj < 0x0010000000000000) */
+  else                             // expect (badj < 0x0010000000000000)
     return b;                      // in that case b must be a quiet NaN
 }
diff --git a/compiler-rt/lib/builtins/arm/endian.h b/compiler-rt/lib/builtins/arm/endian.h
index f603fa9cc678f..be2411f7d471a 100644
--- a/compiler-rt/lib/builtins/arm/endian.h
+++ b/compiler-rt/lib/builtins/arm/endian.h
@@ -20,6 +20,8 @@
 #ifndef COMPILER_RT_ARM_FP_ENDIAN_H
 #define COMPILER_RT_ARM_FP_ENDIAN_H
 
+// clang-format off
+
 #ifdef __BIG_ENDIAN__
 // Big-endian: high words are in lower-numbered registers.
 xh .req r0

>From 4c809b3780f05d59bac6e6863b8fe005e25cfdc3 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:17:58 +0000
Subject: [PATCH 12/33] clang-format

---
 .../test/builtins/Unit/adddf3new_test.c       | 912 +++++++++++------
 .../test/builtins/Unit/subdf3new_test.c       | 945 ++++++++++++------
 2 files changed, 1236 insertions(+), 621 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/adddf3new_test.c b/compiler-rt/test/builtins/Unit/adddf3new_test.c
index a3d8084b103ad..f7c5edf6c4d9d 100644
--- a/compiler-rt/test/builtins/Unit/adddf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/adddf3new_test.c
@@ -24,7 +24,8 @@
 // Returns: a + b
 COMPILER_RT_ABI double __adddf3(double a, double b);
 
-int test__adddf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+int test__adddf3(int line, uint64_t a_rep, uint64_t b_rep,
+                 uint64_t expected_rep) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __adddf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -34,262 +35,506 @@ int test__adddf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep
 #endif
 
   if (ret) {
-    printf("error at line %d: __adddf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
-           ", expected %016" PRIx64 "\n",
+    printf("error at line %d: __adddf3(%016" PRIx64 ", %016" PRIx64
+           ") = %016" PRIx64 ", expected %016" PRIx64 "\n",
            line, a_rep, b_rep, toRep64(x), expected_rep);
   }
   return ret;
 }
 
-#define test__adddf3(a,b,x) (test__adddf3)(__LINE__,a,b,x)
+#define test__adddf3(a, b, x) (test__adddf3)(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;
 
-  status |= test__adddf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x0000000000000000, 0x000fffffffffffff, 0x000fffffffffffff);
-  status |= test__adddf3(0x0000000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
-  status |= test__adddf3(0x0000000000000000, 0x7fe0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x0000000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x0000000000000000, 0x8000000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x0000000000000000, 0x800fffffffffffff, 0x800fffffffffffff);
-  status |= test__adddf3(0x0000000000000000, 0x8010000000000000, 0x8010000000000000);
-  status |= test__adddf3(0x0000000000000000, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000002);
-  status |= test__adddf3(0x0000000000000001, 0x3fefffffffffffff, 0x3fefffffffffffff);
-  status |= test__adddf3(0x0000000000000001, 0x3ff0000000000000, 0x3ff0000000000000);
-  status |= test__adddf3(0x0000000000000001, 0x3ffffffffffffffe, 0x3ffffffffffffffe);
-  status |= test__adddf3(0x0000000000000001, 0x3fffffffffffffff, 0x3fffffffffffffff);
-  status |= test__adddf3(0x0000000000000001, 0x7fdfffffffffffff, 0x7fdfffffffffffff);
-  status |= test__adddf3(0x0000000000000001, 0x7fe0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x0000000000000001, 0x7feffffffffffffe, 0x7feffffffffffffe);
-  status |= test__adddf3(0x0000000000000001, 0x7fefffffffffffff, 0x7fefffffffffffff);
-  status |= test__adddf3(0x0000000000000001, 0x8000000000000001, 0x0000000000000000);
-  status |= test__adddf3(0x0000000000000002, 0x8000000000000001, 0x0000000000000001);
-  status |= test__adddf3(0x0000000000000003, 0x0000000000000000, 0x0000000000000003);
-  status |= test__adddf3(0x0000000000000003, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x0000000000000003, 0x8000000000000000, 0x0000000000000003);
-  status |= test__adddf3(0x0000000000000003, 0x8000000000000002, 0x0000000000000001);
-  status |= test__adddf3(0x0000000000000003, 0xc014000000000000, 0xc014000000000000);
-  status |= test__adddf3(0x0000000000000003, 0xffe0000000000000, 0xffe0000000000000);
-  status |= test__adddf3(0x0000000000000003, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0x0000000000000004, 0x0000000000000004, 0x0000000000000008);
-  status |= test__adddf3(0x000ffffffffffffc, 0x800ffffffffffffc, 0x0000000000000000);
-  status |= test__adddf3(0x000ffffffffffffd, 0x800ffffffffffffe, 0x8000000000000001);
-  status |= test__adddf3(0x000fffffffffffff, 0x000fffffffffffff, 0x001ffffffffffffe);
-  status |= test__adddf3(0x000fffffffffffff, 0x800ffffffffffffe, 0x0000000000000001);
-  status |= test__adddf3(0x000fffffffffffff, 0x8010000000000000, 0x8000000000000001);
-  status |= test__adddf3(0x0010000000000000, 0x0000000000000000, 0x0010000000000000);
-  status |= test__adddf3(0x0010000000000000, 0x0010000000000000, 0x0020000000000000);
-  status |= test__adddf3(0x0010000000000000, 0x8010000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x0010000000000001, 0x8010000000000000, 0x0000000000000001);
-  status |= test__adddf3(0x0010000000000001, 0x8010000000000002, 0x8000000000000001);
-  status |= test__adddf3(0x001fffffffffffff, 0x8020000000000000, 0x8000000000000001);
-  status |= test__adddf3(0x001fffffffffffff, 0x8020000000000002, 0x8000000000000005);
-  status |= test__adddf3(0x001fffffffffffff, 0x8020000000000004, 0x8000000000000009);
-  status |= test__adddf3(0x0020000000000000, 0x801fffffffffffff, 0x0000000000000001);
-  status |= test__adddf3(0x0020000000000001, 0x8010000000000001, 0x0010000000000001);
-  status |= test__adddf3(0x0020000000000001, 0x801fffffffffffff, 0x0000000000000003);
-  status |= test__adddf3(0x0020000000000002, 0x8010000000000001, 0x0010000000000003);
-  status |= test__adddf3(0x002fffffffffffff, 0x8030000000000000, 0x8000000000000002);
-  status |= test__adddf3(0x0030000000000000, 0x802fffffffffffff, 0x0000000000000002);
-  status |= test__adddf3(0x0030000000000001, 0x802fffffffffffff, 0x0000000000000006);
-  status |= test__adddf3(0x0030000000000002, 0x8020000000000003, 0x0020000000000001);
-  status |= test__adddf3(0x3fefffffffffffff, 0x8000000000000001, 0x3fefffffffffffff);
-  status |= test__adddf3(0x3ff0000000000000, 0x3ff0000000000000, 0x4000000000000000);
-  status |= test__adddf3(0x3ff0000000000000, 0x3ff0000000000003, 0x4000000000000002);
-  status |= test__adddf3(0x3ff0000000000000, 0x4000000000000000, 0x4008000000000000);
-  status |= test__adddf3(0x3ff0000000000000, 0x401c000000000000, 0x4020000000000000);
-  status |= test__adddf3(0x3ff0000000000000, 0x8000000000000000, 0x3ff0000000000000);
-  status |= test__adddf3(0x3ff0000000000000, 0xbff0000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x3ff0000000000001, 0x3ff0000000000000, 0x4000000000000000);
-  status |= test__adddf3(0x3ff0000000000001, 0xbff0000000000000, 0x3cb0000000000000);
-  status |= test__adddf3(0x3ff0000000000001, 0xbff0000000000002, 0xbcb0000000000000);
-  status |= test__adddf3(0x3ffffffffffffffc, 0xbffffffffffffffd, 0xbcb0000000000000);
-  status |= test__adddf3(0x3fffffffffffffff, 0xc000000000000000, 0xbcb0000000000000);
-  status |= test__adddf3(0x4000000000000000, 0x3cb0000000000000, 0x4000000000000000);
-  status |= test__adddf3(0x4000000000000000, 0x3ff0000000000000, 0x4008000000000000);
-  status |= test__adddf3(0x4000000000000000, 0x4000000000000000, 0x4010000000000000);
-  status |= test__adddf3(0x4000000000000000, 0x4000000000000001, 0x4010000000000000);
-  status |= test__adddf3(0x4000000000000000, 0xbfffffffffffffff, 0x3cb0000000000000);
-  status |= test__adddf3(0x4000000000000000, 0xc000000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x4000000000000000, 0xc000000000000001, 0xbcc0000000000000);
-  status |= test__adddf3(0x4000000000000000, 0xc014000000000000, 0xc008000000000000);
-  status |= test__adddf3(0x4000000000000001, 0x3cb0000000000000, 0x4000000000000002);
-  status |= test__adddf3(0x4000000000000001, 0x4000000000000002, 0x4010000000000002);
-  status |= test__adddf3(0x4000000000000001, 0xbff0000000000001, 0x3ff0000000000001);
-  status |= test__adddf3(0x4000000000000002, 0xbff0000000000001, 0x3ff0000000000003);
-  status |= test__adddf3(0x4000000000000002, 0xbff0000000000003, 0x3ff0000000000001);
-  status |= test__adddf3(0x4000000000000004, 0xc000000000000003, 0x3cc0000000000000);
-  status |= test__adddf3(0x4008000000000000, 0x4008000000000000, 0x4018000000000000);
-  status |= test__adddf3(0x400fffffffffffff, 0x3cafffffffffffff, 0x400fffffffffffff);
-  status |= test__adddf3(0x400fffffffffffff, 0x3cb0000000000000, 0x4010000000000000);
-  status |= test__adddf3(0x400fffffffffffff, 0xc00ffffffffffffe, 0x3cc0000000000000);
-  status |= test__adddf3(0x400fffffffffffff, 0xc010000000000002, 0xbce4000000000000);
-  status |= test__adddf3(0x4010000000000001, 0xc00fffffffffffff, 0x3cd8000000000000);
-  status |= test__adddf3(0x4014000000000000, 0x0000000000000000, 0x4014000000000000);
-  status |= test__adddf3(0x4014000000000000, 0x8000000000000000, 0x4014000000000000);
-  status |= test__adddf3(0x4014000000000000, 0xbff0000000000000, 0x4010000000000000);
-  status |= test__adddf3(0x4014000000000000, 0xc014000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x7fb0000000000001, 0xffafffffffffffff, 0x7c78000000000000);
-  status |= test__adddf3(0x7fcfffffffffffff, 0xffcffffffffffffe, 0x7c80000000000000);
-  status |= test__adddf3(0x7fcfffffffffffff, 0xffd0000000000002, 0xfca4000000000000);
-  status |= test__adddf3(0x7fd0000000000000, 0x7fd0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x7fd0000000000000, 0xffcfffffffffffff, 0x7c80000000000000);
-  status |= test__adddf3(0x7fd0000000000000, 0xffd0000000000001, 0xfc90000000000000);
-  status |= test__adddf3(0x7fd0000000000001, 0x7fd0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x7fd0000000000001, 0xffe0000000000001, 0xffd0000000000001);
-  status |= test__adddf3(0x7fd0000000000002, 0xffc0000000000003, 0x7fc0000000000001);
-  status |= test__adddf3(0x7fd0000000000004, 0xffd0000000000003, 0x7c90000000000000);
-  status |= test__adddf3(0x7fdffffffffffffe, 0x7fdffffffffffffe, 0x7feffffffffffffe);
-  status |= test__adddf3(0x7fdffffffffffffe, 0x7fdfffffffffffff, 0x7feffffffffffffe);
-  status |= test__adddf3(0x7fdfffffffffffff, 0x3ff0000000000000, 0x7fdfffffffffffff);
-  status |= test__adddf3(0x7fdfffffffffffff, 0x7fe0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7fdfffffffffffff, 0xbff0000000000000, 0x7fdfffffffffffff);
-  status |= test__adddf3(0x7fdfffffffffffff, 0xffe0000000000000, 0xfc90000000000000);
-  status |= test__adddf3(0x7fe0000000000000, 0x3ff0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x7fe0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7fe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7fe0000000000000, 0xbff0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x7fe0000000000000, 0xffe0000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x7fe0000000000000, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0x7fe0000000000001, 0x7fe0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7fe0000000000001, 0xffe0000000000000, 0x7ca0000000000000);
-  status |= test__adddf3(0x7fe0000000000001, 0xffe0000000000002, 0xfca0000000000000);
-  status |= test__adddf3(0x7fe0000000000002, 0xffd0000000000001, 0x7fd0000000000003);
-  status |= test__adddf3(0x7feffffffffffffe, 0x3ff0000000000000, 0x7feffffffffffffe);
-  status |= test__adddf3(0x7feffffffffffffe, 0x7feffffffffffffe, 0x7ff0000000000000);
-  status |= test__adddf3(0x7feffffffffffffe, 0x7fefffffffffffff, 0x7ff0000000000000);
-  status |= test__adddf3(0x7feffffffffffffe, 0xbff0000000000000, 0x7feffffffffffffe);
-  status |= test__adddf3(0x7feffffffffffffe, 0xffefffffffffffff, 0xfca0000000000000);
-  status |= test__adddf3(0x7fefffffffffffff, 0x3ff0000000000000, 0x7fefffffffffffff);
-  status |= test__adddf3(0x7fefffffffffffff, 0x8000000000000001, 0x7fefffffffffffff);
-  status |= test__adddf3(0x7fefffffffffffff, 0xbff0000000000000, 0x7fefffffffffffff);
-  status |= test__adddf3(0x7fefffffffffffff, 0xffefffffffffffff, 0x0000000000000000);
-  status |= test__adddf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
-  status |= test__adddf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x7ff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
-  status |= test__adddf3(0x7ff0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x8000000000000000, 0x0000000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x8000000000000000, 0x000fffffffffffff, 0x000fffffffffffff);
-  status |= test__adddf3(0x8000000000000000, 0x7fe0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x8000000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x8000000000000000, 0x8000000000000000, 0x8000000000000000);
-  status |= test__adddf3(0x8000000000000000, 0x800fffffffffffff, 0x800fffffffffffff);
-  status |= test__adddf3(0x8000000000000000, 0x8010000000000000, 0x8010000000000000);
-  status |= test__adddf3(0x8000000000000000, 0xbff0000000000000, 0xbff0000000000000);
-  status |= test__adddf3(0x8000000000000000, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0x8000000000000001, 0x0000000000000001, 0x0000000000000000);
-  status |= test__adddf3(0x8000000000000001, 0x8000000000000001, 0x8000000000000002);
-  status |= test__adddf3(0x8000000000000001, 0xbfefffffffffffff, 0xbfefffffffffffff);
-  status |= test__adddf3(0x8000000000000001, 0xbff0000000000000, 0xbff0000000000000);
-  status |= test__adddf3(0x8000000000000001, 0xbffffffffffffffe, 0xbffffffffffffffe);
-  status |= test__adddf3(0x8000000000000001, 0xbfffffffffffffff, 0xbfffffffffffffff);
-  status |= test__adddf3(0x8000000000000001, 0xffdfffffffffffff, 0xffdfffffffffffff);
-  status |= test__adddf3(0x8000000000000001, 0xffe0000000000000, 0xffe0000000000000);
-  status |= test__adddf3(0x8000000000000001, 0xffeffffffffffffe, 0xffeffffffffffffe);
-  status |= test__adddf3(0x8000000000000001, 0xffefffffffffffff, 0xffefffffffffffff);
-  status |= test__adddf3(0x8000000000000002, 0x0000000000000001, 0x8000000000000001);
-  status |= test__adddf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000003);
-  status |= test__adddf3(0x8000000000000003, 0x0000000000000002, 0x8000000000000001);
-  status |= test__adddf3(0x8000000000000003, 0x4008000000000000, 0x4008000000000000);
-  status |= test__adddf3(0x8000000000000003, 0x7fe0000000000000, 0x7fe0000000000000);
-  status |= test__adddf3(0x8000000000000003, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0x8000000000000003, 0x8000000000000000, 0x8000000000000003);
-  status |= test__adddf3(0x8000000000000003, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0x8000000000000004, 0x8000000000000004, 0x8000000000000008);
-  status |= test__adddf3(0x800ffffffffffffd, 0x000ffffffffffffe, 0x0000000000000001);
-  status |= test__adddf3(0x800fffffffffffff, 0x000ffffffffffffe, 0x8000000000000001);
-  status |= test__adddf3(0x800fffffffffffff, 0x000fffffffffffff, 0x0000000000000000);
-  status |= test__adddf3(0x800fffffffffffff, 0x0010000000000000, 0x0000000000000001);
-  status |= test__adddf3(0x800fffffffffffff, 0x800fffffffffffff, 0x801ffffffffffffe);
-  status |= test__adddf3(0x8010000000000000, 0x0000000000000000, 0x8010000000000000);
-  status |= test__adddf3(0x8010000000000000, 0x0010000000000000, 0x0000000000000000);
-  status |= test__adddf3(0x8010000000000001, 0x0010000000000000, 0x8000000000000001);
-  status |= test__adddf3(0x8010000000000001, 0x0010000000000002, 0x0000000000000001);
-  status |= test__adddf3(0x801fffffffffffff, 0x0020000000000000, 0x0000000000000001);
-  status |= test__adddf3(0x801fffffffffffff, 0x0020000000000002, 0x0000000000000005);
-  status |= test__adddf3(0x801fffffffffffff, 0x0020000000000004, 0x0000000000000009);
-  status |= test__adddf3(0x8020000000000000, 0x001fffffffffffff, 0x8000000000000001);
-  status |= test__adddf3(0x8020000000000001, 0x0010000000000001, 0x8010000000000001);
-  status |= test__adddf3(0x8020000000000001, 0x001fffffffffffff, 0x8000000000000003);
-  status |= test__adddf3(0x8020000000000002, 0x0010000000000001, 0x8010000000000003);
-  status |= test__adddf3(0x802fffffffffffff, 0x0030000000000000, 0x0000000000000002);
-  status |= test__adddf3(0x8030000000000000, 0x002fffffffffffff, 0x8000000000000002);
-  status |= test__adddf3(0x8030000000000001, 0x002fffffffffffff, 0x8000000000000006);
-  status |= test__adddf3(0x8030000000000002, 0x0020000000000003, 0x8020000000000001);
-  status |= test__adddf3(0xbff0000000000000, 0x8000000000000000, 0xbff0000000000000);
-  status |= test__adddf3(0xbff0000000000000, 0xbff0000000000003, 0xc000000000000002);
-  status |= test__adddf3(0xbff0000000000001, 0x3ff0000000000000, 0xbcb0000000000000);
-  status |= test__adddf3(0xbff0000000000001, 0x3ff0000000000002, 0x3cb0000000000000);
-  status |= test__adddf3(0xbff0000000000001, 0xbff0000000000000, 0xc000000000000000);
-  status |= test__adddf3(0xbffffffffffffffc, 0x3ffffffffffffffd, 0x3cb0000000000000);
-  status |= test__adddf3(0xbfffffffffffffff, 0x0000000000000001, 0xbfffffffffffffff);
-  status |= test__adddf3(0xbfffffffffffffff, 0x4000000000000000, 0x3cb0000000000000);
-  status |= test__adddf3(0xc000000000000000, 0x3fffffffffffffff, 0xbcb0000000000000);
-  status |= test__adddf3(0xc000000000000000, 0x4000000000000001, 0x3cc0000000000000);
-  status |= test__adddf3(0xc000000000000000, 0xc000000000000001, 0xc010000000000000);
-  status |= test__adddf3(0xc000000000000001, 0x3ff0000000000001, 0xbff0000000000001);
-  status |= test__adddf3(0xc000000000000001, 0xc000000000000002, 0xc010000000000002);
-  status |= test__adddf3(0xc000000000000002, 0x3ff0000000000001, 0xbff0000000000003);
-  status |= test__adddf3(0xc000000000000002, 0x3ff0000000000003, 0xbff0000000000001);
-  status |= test__adddf3(0xc000000000000004, 0x4000000000000003, 0xbcc0000000000000);
-  status |= test__adddf3(0xc008000000000000, 0x4008000000000000, 0x0000000000000000);
-  status |= test__adddf3(0xc00fffffffffffff, 0x400ffffffffffffe, 0xbcc0000000000000);
-  status |= test__adddf3(0xc00fffffffffffff, 0x4010000000000002, 0x3ce4000000000000);
-  status |= test__adddf3(0xc00fffffffffffff, 0xbcafffffffffffff, 0xc00fffffffffffff);
-  status |= test__adddf3(0xc00fffffffffffff, 0xbcb0000000000000, 0xc010000000000000);
-  status |= test__adddf3(0xc010000000000001, 0x400fffffffffffff, 0xbcd8000000000000);
-  status |= test__adddf3(0xffb0000000000001, 0x7fafffffffffffff, 0xfc78000000000000);
-  status |= test__adddf3(0xffcfffffffffffff, 0x7fcffffffffffffe, 0xfc80000000000000);
-  status |= test__adddf3(0xffcfffffffffffff, 0x7fd0000000000002, 0x7ca4000000000000);
-  status |= test__adddf3(0xffd0000000000000, 0x7fcfffffffffffff, 0xfc80000000000000);
-  status |= test__adddf3(0xffd0000000000000, 0x7fd0000000000001, 0x7c90000000000000);
-  status |= test__adddf3(0xffd0000000000001, 0x7fe0000000000001, 0x7fd0000000000001);
-  status |= test__adddf3(0xffd0000000000001, 0xffd0000000000000, 0xffe0000000000000);
-  status |= test__adddf3(0xffd0000000000002, 0x7fc0000000000003, 0xffc0000000000001);
-  status |= test__adddf3(0xffd0000000000004, 0x7fd0000000000003, 0xfc90000000000000);
-  status |= test__adddf3(0xffdffffffffffffe, 0x7fdffffffffffffe, 0x0000000000000000);
-  status |= test__adddf3(0xffdffffffffffffe, 0xffdffffffffffffe, 0xffeffffffffffffe);
-  status |= test__adddf3(0xffdffffffffffffe, 0xffdfffffffffffff, 0xffeffffffffffffe);
-  status |= test__adddf3(0xffdfffffffffffff, 0x3ff0000000000000, 0xffdfffffffffffff);
-  status |= test__adddf3(0xffdfffffffffffff, 0x7fe0000000000000, 0x7c90000000000000);
-  status |= test__adddf3(0xffdfffffffffffff, 0xbff0000000000000, 0xffdfffffffffffff);
-  status |= test__adddf3(0xffdfffffffffffff, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xffe0000000000000, 0x0000000000000000, 0xffe0000000000000);
-  status |= test__adddf3(0xffe0000000000000, 0x3ff0000000000000, 0xffe0000000000000);
-  status |= test__adddf3(0xffe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__adddf3(0xffe0000000000000, 0x8000000000000000, 0xffe0000000000000);
-  status |= test__adddf3(0xffe0000000000000, 0xbff0000000000000, 0xffe0000000000000);
-  status |= test__adddf3(0xffe0000000000000, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xffe0000000000000, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xffe0000000000001, 0x7fe0000000000000, 0xfca0000000000000);
-  status |= test__adddf3(0xffe0000000000001, 0x7fe0000000000002, 0x7ca0000000000000);
-  status |= test__adddf3(0xffe0000000000001, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xffe0000000000002, 0x7fd0000000000001, 0xffd0000000000003);
-  status |= test__adddf3(0xffeffffffffffffe, 0x3ff0000000000000, 0xffeffffffffffffe);
-  status |= test__adddf3(0xffeffffffffffffe, 0x7fefffffffffffff, 0x7ca0000000000000);
-  status |= test__adddf3(0xffeffffffffffffe, 0xbff0000000000000, 0xffeffffffffffffe);
-  status |= test__adddf3(0xffeffffffffffffe, 0xffeffffffffffffe, 0xfff0000000000000);
-  status |= test__adddf3(0xffeffffffffffffe, 0xffefffffffffffff, 0xfff0000000000000);
-  status |= test__adddf3(0xffefffffffffffff, 0x0000000000000001, 0xffefffffffffffff);
-  status |= test__adddf3(0xffefffffffffffff, 0x3ff0000000000000, 0xffefffffffffffff);
-  status |= test__adddf3(0xffefffffffffffff, 0xbff0000000000000, 0xffefffffffffffff);
-  status |= test__adddf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
-  status |= test__adddf3(0xfff0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xfff0000000000000, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xfff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
-  status |= test__adddf3(0xfff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0xfff0000000000000, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__adddf3(0x3de3a83a83a83a83, 0xbff0000000000000, 0xbfefffffffec57c5);
-  status |= test__adddf3(0x0000000007ffffff, 0x0010000000010000, 0x001000000800ffff);
-  status |= test__adddf3(0x001effffffffffff, 0x0000000000400000, 0x001f0000003fffff);
-  status |= test__adddf3(0x80000000000003ff, 0x801ffffbffffffff, 0x801ffffc000003fe);
-  status |= test__adddf3(0x80003fffffffffff, 0x8010000000100000, 0x80104000000fffff);
+  status |=
+      test__adddf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x0000000000000000, 0x000fffffffffffff, 0x000fffffffffffff);
+  status |=
+      test__adddf3(0x0000000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__adddf3(0x0000000000000000, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x0000000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x0000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x0000000000000000, 0x800fffffffffffff, 0x800fffffffffffff);
+  status |=
+      test__adddf3(0x0000000000000000, 0x8010000000000000, 0x8010000000000000);
+  status |=
+      test__adddf3(0x0000000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000002);
+  status |=
+      test__adddf3(0x0000000000000001, 0x3fefffffffffffff, 0x3fefffffffffffff);
+  status |=
+      test__adddf3(0x0000000000000001, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__adddf3(0x0000000000000001, 0x3ffffffffffffffe, 0x3ffffffffffffffe);
+  status |=
+      test__adddf3(0x0000000000000001, 0x3fffffffffffffff, 0x3fffffffffffffff);
+  status |=
+      test__adddf3(0x0000000000000001, 0x7fdfffffffffffff, 0x7fdfffffffffffff);
+  status |=
+      test__adddf3(0x0000000000000001, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x0000000000000001, 0x7feffffffffffffe, 0x7feffffffffffffe);
+  status |=
+      test__adddf3(0x0000000000000001, 0x7fefffffffffffff, 0x7fefffffffffffff);
+  status |=
+      test__adddf3(0x0000000000000001, 0x8000000000000001, 0x0000000000000000);
+  status |=
+      test__adddf3(0x0000000000000002, 0x8000000000000001, 0x0000000000000001);
+  status |=
+      test__adddf3(0x0000000000000003, 0x0000000000000000, 0x0000000000000003);
+  status |=
+      test__adddf3(0x0000000000000003, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x0000000000000003, 0x8000000000000000, 0x0000000000000003);
+  status |=
+      test__adddf3(0x0000000000000003, 0x8000000000000002, 0x0000000000000001);
+  status |=
+      test__adddf3(0x0000000000000003, 0xc014000000000000, 0xc014000000000000);
+  status |=
+      test__adddf3(0x0000000000000003, 0xffe0000000000000, 0xffe0000000000000);
+  status |=
+      test__adddf3(0x0000000000000003, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0x0000000000000004, 0x0000000000000004, 0x0000000000000008);
+  status |=
+      test__adddf3(0x000ffffffffffffc, 0x800ffffffffffffc, 0x0000000000000000);
+  status |=
+      test__adddf3(0x000ffffffffffffd, 0x800ffffffffffffe, 0x8000000000000001);
+  status |=
+      test__adddf3(0x000fffffffffffff, 0x000fffffffffffff, 0x001ffffffffffffe);
+  status |=
+      test__adddf3(0x000fffffffffffff, 0x800ffffffffffffe, 0x0000000000000001);
+  status |=
+      test__adddf3(0x000fffffffffffff, 0x8010000000000000, 0x8000000000000001);
+  status |=
+      test__adddf3(0x0010000000000000, 0x0000000000000000, 0x0010000000000000);
+  status |=
+      test__adddf3(0x0010000000000000, 0x0010000000000000, 0x0020000000000000);
+  status |=
+      test__adddf3(0x0010000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x0010000000000001, 0x8010000000000000, 0x0000000000000001);
+  status |=
+      test__adddf3(0x0010000000000001, 0x8010000000000002, 0x8000000000000001);
+  status |=
+      test__adddf3(0x001fffffffffffff, 0x8020000000000000, 0x8000000000000001);
+  status |=
+      test__adddf3(0x001fffffffffffff, 0x8020000000000002, 0x8000000000000005);
+  status |=
+      test__adddf3(0x001fffffffffffff, 0x8020000000000004, 0x8000000000000009);
+  status |=
+      test__adddf3(0x0020000000000000, 0x801fffffffffffff, 0x0000000000000001);
+  status |=
+      test__adddf3(0x0020000000000001, 0x8010000000000001, 0x0010000000000001);
+  status |=
+      test__adddf3(0x0020000000000001, 0x801fffffffffffff, 0x0000000000000003);
+  status |=
+      test__adddf3(0x0020000000000002, 0x8010000000000001, 0x0010000000000003);
+  status |=
+      test__adddf3(0x002fffffffffffff, 0x8030000000000000, 0x8000000000000002);
+  status |=
+      test__adddf3(0x0030000000000000, 0x802fffffffffffff, 0x0000000000000002);
+  status |=
+      test__adddf3(0x0030000000000001, 0x802fffffffffffff, 0x0000000000000006);
+  status |=
+      test__adddf3(0x0030000000000002, 0x8020000000000003, 0x0020000000000001);
+  status |=
+      test__adddf3(0x3fefffffffffffff, 0x8000000000000001, 0x3fefffffffffffff);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x3ff0000000000000, 0x4000000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x3ff0000000000003, 0x4000000000000002);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x4000000000000000, 0x4008000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x401c000000000000, 0x4020000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x8000000000000000, 0x3ff0000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0xbff0000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000001, 0x3ff0000000000000, 0x4000000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000001, 0xbff0000000000000, 0x3cb0000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000001, 0xbff0000000000002, 0xbcb0000000000000);
+  status |=
+      test__adddf3(0x3ffffffffffffffc, 0xbffffffffffffffd, 0xbcb0000000000000);
+  status |=
+      test__adddf3(0x3fffffffffffffff, 0xc000000000000000, 0xbcb0000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0x3cb0000000000000, 0x4000000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0x3ff0000000000000, 0x4008000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0x4000000000000000, 0x4010000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0x4000000000000001, 0x4010000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0xbfffffffffffffff, 0x3cb0000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0xc000000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0xc000000000000001, 0xbcc0000000000000);
+  status |=
+      test__adddf3(0x4000000000000000, 0xc014000000000000, 0xc008000000000000);
+  status |=
+      test__adddf3(0x4000000000000001, 0x3cb0000000000000, 0x4000000000000002);
+  status |=
+      test__adddf3(0x4000000000000001, 0x4000000000000002, 0x4010000000000002);
+  status |=
+      test__adddf3(0x4000000000000001, 0xbff0000000000001, 0x3ff0000000000001);
+  status |=
+      test__adddf3(0x4000000000000002, 0xbff0000000000001, 0x3ff0000000000003);
+  status |=
+      test__adddf3(0x4000000000000002, 0xbff0000000000003, 0x3ff0000000000001);
+  status |=
+      test__adddf3(0x4000000000000004, 0xc000000000000003, 0x3cc0000000000000);
+  status |=
+      test__adddf3(0x4008000000000000, 0x4008000000000000, 0x4018000000000000);
+  status |=
+      test__adddf3(0x400fffffffffffff, 0x3cafffffffffffff, 0x400fffffffffffff);
+  status |=
+      test__adddf3(0x400fffffffffffff, 0x3cb0000000000000, 0x4010000000000000);
+  status |=
+      test__adddf3(0x400fffffffffffff, 0xc00ffffffffffffe, 0x3cc0000000000000);
+  status |=
+      test__adddf3(0x400fffffffffffff, 0xc010000000000002, 0xbce4000000000000);
+  status |=
+      test__adddf3(0x4010000000000001, 0xc00fffffffffffff, 0x3cd8000000000000);
+  status |=
+      test__adddf3(0x4014000000000000, 0x0000000000000000, 0x4014000000000000);
+  status |=
+      test__adddf3(0x4014000000000000, 0x8000000000000000, 0x4014000000000000);
+  status |=
+      test__adddf3(0x4014000000000000, 0xbff0000000000000, 0x4010000000000000);
+  status |=
+      test__adddf3(0x4014000000000000, 0xc014000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x7fb0000000000001, 0xffafffffffffffff, 0x7c78000000000000);
+  status |=
+      test__adddf3(0x7fcfffffffffffff, 0xffcffffffffffffe, 0x7c80000000000000);
+  status |=
+      test__adddf3(0x7fcfffffffffffff, 0xffd0000000000002, 0xfca4000000000000);
+  status |=
+      test__adddf3(0x7fd0000000000000, 0x7fd0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x7fd0000000000000, 0xffcfffffffffffff, 0x7c80000000000000);
+  status |=
+      test__adddf3(0x7fd0000000000000, 0xffd0000000000001, 0xfc90000000000000);
+  status |=
+      test__adddf3(0x7fd0000000000001, 0x7fd0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x7fd0000000000001, 0xffe0000000000001, 0xffd0000000000001);
+  status |=
+      test__adddf3(0x7fd0000000000002, 0xffc0000000000003, 0x7fc0000000000001);
+  status |=
+      test__adddf3(0x7fd0000000000004, 0xffd0000000000003, 0x7c90000000000000);
+  status |=
+      test__adddf3(0x7fdffffffffffffe, 0x7fdffffffffffffe, 0x7feffffffffffffe);
+  status |=
+      test__adddf3(0x7fdffffffffffffe, 0x7fdfffffffffffff, 0x7feffffffffffffe);
+  status |=
+      test__adddf3(0x7fdfffffffffffff, 0x3ff0000000000000, 0x7fdfffffffffffff);
+  status |=
+      test__adddf3(0x7fdfffffffffffff, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7fdfffffffffffff, 0xbff0000000000000, 0x7fdfffffffffffff);
+  status |=
+      test__adddf3(0x7fdfffffffffffff, 0xffe0000000000000, 0xfc90000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000000, 0x3ff0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000000, 0xbff0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000000, 0xffe0000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000001, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000001, 0xffe0000000000000, 0x7ca0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000001, 0xffe0000000000002, 0xfca0000000000000);
+  status |=
+      test__adddf3(0x7fe0000000000002, 0xffd0000000000001, 0x7fd0000000000003);
+  status |=
+      test__adddf3(0x7feffffffffffffe, 0x3ff0000000000000, 0x7feffffffffffffe);
+  status |=
+      test__adddf3(0x7feffffffffffffe, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7feffffffffffffe, 0x7fefffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7feffffffffffffe, 0xbff0000000000000, 0x7feffffffffffffe);
+  status |=
+      test__adddf3(0x7feffffffffffffe, 0xffefffffffffffff, 0xfca0000000000000);
+  status |=
+      test__adddf3(0x7fefffffffffffff, 0x3ff0000000000000, 0x7fefffffffffffff);
+  status |=
+      test__adddf3(0x7fefffffffffffff, 0x8000000000000001, 0x7fefffffffffffff);
+  status |=
+      test__adddf3(0x7fefffffffffffff, 0xbff0000000000000, 0x7fefffffffffffff);
+  status |=
+      test__adddf3(0x7fefffffffffffff, 0xffefffffffffffff, 0x0000000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x8000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x8000000000000000, 0x000fffffffffffff, 0x000fffffffffffff);
+  status |=
+      test__adddf3(0x8000000000000000, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x8000000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x8000000000000000, 0x8000000000000000, 0x8000000000000000);
+  status |=
+      test__adddf3(0x8000000000000000, 0x800fffffffffffff, 0x800fffffffffffff);
+  status |=
+      test__adddf3(0x8000000000000000, 0x8010000000000000, 0x8010000000000000);
+  status |=
+      test__adddf3(0x8000000000000000, 0xbff0000000000000, 0xbff0000000000000);
+  status |=
+      test__adddf3(0x8000000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0x8000000000000001, 0x0000000000000001, 0x0000000000000000);
+  status |=
+      test__adddf3(0x8000000000000001, 0x8000000000000001, 0x8000000000000002);
+  status |=
+      test__adddf3(0x8000000000000001, 0xbfefffffffffffff, 0xbfefffffffffffff);
+  status |=
+      test__adddf3(0x8000000000000001, 0xbff0000000000000, 0xbff0000000000000);
+  status |=
+      test__adddf3(0x8000000000000001, 0xbffffffffffffffe, 0xbffffffffffffffe);
+  status |=
+      test__adddf3(0x8000000000000001, 0xbfffffffffffffff, 0xbfffffffffffffff);
+  status |=
+      test__adddf3(0x8000000000000001, 0xffdfffffffffffff, 0xffdfffffffffffff);
+  status |=
+      test__adddf3(0x8000000000000001, 0xffe0000000000000, 0xffe0000000000000);
+  status |=
+      test__adddf3(0x8000000000000001, 0xffeffffffffffffe, 0xffeffffffffffffe);
+  status |=
+      test__adddf3(0x8000000000000001, 0xffefffffffffffff, 0xffefffffffffffff);
+  status |=
+      test__adddf3(0x8000000000000002, 0x0000000000000001, 0x8000000000000001);
+  status |=
+      test__adddf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000003);
+  status |=
+      test__adddf3(0x8000000000000003, 0x0000000000000002, 0x8000000000000001);
+  status |=
+      test__adddf3(0x8000000000000003, 0x4008000000000000, 0x4008000000000000);
+  status |=
+      test__adddf3(0x8000000000000003, 0x7fe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__adddf3(0x8000000000000003, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0x8000000000000003, 0x8000000000000000, 0x8000000000000003);
+  status |=
+      test__adddf3(0x8000000000000003, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0x8000000000000004, 0x8000000000000004, 0x8000000000000008);
+  status |=
+      test__adddf3(0x800ffffffffffffd, 0x000ffffffffffffe, 0x0000000000000001);
+  status |=
+      test__adddf3(0x800fffffffffffff, 0x000ffffffffffffe, 0x8000000000000001);
+  status |=
+      test__adddf3(0x800fffffffffffff, 0x000fffffffffffff, 0x0000000000000000);
+  status |=
+      test__adddf3(0x800fffffffffffff, 0x0010000000000000, 0x0000000000000001);
+  status |=
+      test__adddf3(0x800fffffffffffff, 0x800fffffffffffff, 0x801ffffffffffffe);
+  status |=
+      test__adddf3(0x8010000000000000, 0x0000000000000000, 0x8010000000000000);
+  status |=
+      test__adddf3(0x8010000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0x8010000000000001, 0x0010000000000000, 0x8000000000000001);
+  status |=
+      test__adddf3(0x8010000000000001, 0x0010000000000002, 0x0000000000000001);
+  status |=
+      test__adddf3(0x801fffffffffffff, 0x0020000000000000, 0x0000000000000001);
+  status |=
+      test__adddf3(0x801fffffffffffff, 0x0020000000000002, 0x0000000000000005);
+  status |=
+      test__adddf3(0x801fffffffffffff, 0x0020000000000004, 0x0000000000000009);
+  status |=
+      test__adddf3(0x8020000000000000, 0x001fffffffffffff, 0x8000000000000001);
+  status |=
+      test__adddf3(0x8020000000000001, 0x0010000000000001, 0x8010000000000001);
+  status |=
+      test__adddf3(0x8020000000000001, 0x001fffffffffffff, 0x8000000000000003);
+  status |=
+      test__adddf3(0x8020000000000002, 0x0010000000000001, 0x8010000000000003);
+  status |=
+      test__adddf3(0x802fffffffffffff, 0x0030000000000000, 0x0000000000000002);
+  status |=
+      test__adddf3(0x8030000000000000, 0x002fffffffffffff, 0x8000000000000002);
+  status |=
+      test__adddf3(0x8030000000000001, 0x002fffffffffffff, 0x8000000000000006);
+  status |=
+      test__adddf3(0x8030000000000002, 0x0020000000000003, 0x8020000000000001);
+  status |=
+      test__adddf3(0xbff0000000000000, 0x8000000000000000, 0xbff0000000000000);
+  status |=
+      test__adddf3(0xbff0000000000000, 0xbff0000000000003, 0xc000000000000002);
+  status |=
+      test__adddf3(0xbff0000000000001, 0x3ff0000000000000, 0xbcb0000000000000);
+  status |=
+      test__adddf3(0xbff0000000000001, 0x3ff0000000000002, 0x3cb0000000000000);
+  status |=
+      test__adddf3(0xbff0000000000001, 0xbff0000000000000, 0xc000000000000000);
+  status |=
+      test__adddf3(0xbffffffffffffffc, 0x3ffffffffffffffd, 0x3cb0000000000000);
+  status |=
+      test__adddf3(0xbfffffffffffffff, 0x0000000000000001, 0xbfffffffffffffff);
+  status |=
+      test__adddf3(0xbfffffffffffffff, 0x4000000000000000, 0x3cb0000000000000);
+  status |=
+      test__adddf3(0xc000000000000000, 0x3fffffffffffffff, 0xbcb0000000000000);
+  status |=
+      test__adddf3(0xc000000000000000, 0x4000000000000001, 0x3cc0000000000000);
+  status |=
+      test__adddf3(0xc000000000000000, 0xc000000000000001, 0xc010000000000000);
+  status |=
+      test__adddf3(0xc000000000000001, 0x3ff0000000000001, 0xbff0000000000001);
+  status |=
+      test__adddf3(0xc000000000000001, 0xc000000000000002, 0xc010000000000002);
+  status |=
+      test__adddf3(0xc000000000000002, 0x3ff0000000000001, 0xbff0000000000003);
+  status |=
+      test__adddf3(0xc000000000000002, 0x3ff0000000000003, 0xbff0000000000001);
+  status |=
+      test__adddf3(0xc000000000000004, 0x4000000000000003, 0xbcc0000000000000);
+  status |=
+      test__adddf3(0xc008000000000000, 0x4008000000000000, 0x0000000000000000);
+  status |=
+      test__adddf3(0xc00fffffffffffff, 0x400ffffffffffffe, 0xbcc0000000000000);
+  status |=
+      test__adddf3(0xc00fffffffffffff, 0x4010000000000002, 0x3ce4000000000000);
+  status |=
+      test__adddf3(0xc00fffffffffffff, 0xbcafffffffffffff, 0xc00fffffffffffff);
+  status |=
+      test__adddf3(0xc00fffffffffffff, 0xbcb0000000000000, 0xc010000000000000);
+  status |=
+      test__adddf3(0xc010000000000001, 0x400fffffffffffff, 0xbcd8000000000000);
+  status |=
+      test__adddf3(0xffb0000000000001, 0x7fafffffffffffff, 0xfc78000000000000);
+  status |=
+      test__adddf3(0xffcfffffffffffff, 0x7fcffffffffffffe, 0xfc80000000000000);
+  status |=
+      test__adddf3(0xffcfffffffffffff, 0x7fd0000000000002, 0x7ca4000000000000);
+  status |=
+      test__adddf3(0xffd0000000000000, 0x7fcfffffffffffff, 0xfc80000000000000);
+  status |=
+      test__adddf3(0xffd0000000000000, 0x7fd0000000000001, 0x7c90000000000000);
+  status |=
+      test__adddf3(0xffd0000000000001, 0x7fe0000000000001, 0x7fd0000000000001);
+  status |=
+      test__adddf3(0xffd0000000000001, 0xffd0000000000000, 0xffe0000000000000);
+  status |=
+      test__adddf3(0xffd0000000000002, 0x7fc0000000000003, 0xffc0000000000001);
+  status |=
+      test__adddf3(0xffd0000000000004, 0x7fd0000000000003, 0xfc90000000000000);
+  status |=
+      test__adddf3(0xffdffffffffffffe, 0x7fdffffffffffffe, 0x0000000000000000);
+  status |=
+      test__adddf3(0xffdffffffffffffe, 0xffdffffffffffffe, 0xffeffffffffffffe);
+  status |=
+      test__adddf3(0xffdffffffffffffe, 0xffdfffffffffffff, 0xffeffffffffffffe);
+  status |=
+      test__adddf3(0xffdfffffffffffff, 0x3ff0000000000000, 0xffdfffffffffffff);
+  status |=
+      test__adddf3(0xffdfffffffffffff, 0x7fe0000000000000, 0x7c90000000000000);
+  status |=
+      test__adddf3(0xffdfffffffffffff, 0xbff0000000000000, 0xffdfffffffffffff);
+  status |=
+      test__adddf3(0xffdfffffffffffff, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000000, 0x0000000000000000, 0xffe0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000000, 0x3ff0000000000000, 0xffe0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000000, 0x8000000000000000, 0xffe0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000000, 0xbff0000000000000, 0xffe0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000001, 0x7fe0000000000000, 0xfca0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000001, 0x7fe0000000000002, 0x7ca0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000001, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xffe0000000000002, 0x7fd0000000000001, 0xffd0000000000003);
+  status |=
+      test__adddf3(0xffeffffffffffffe, 0x3ff0000000000000, 0xffeffffffffffffe);
+  status |=
+      test__adddf3(0xffeffffffffffffe, 0x7fefffffffffffff, 0x7ca0000000000000);
+  status |=
+      test__adddf3(0xffeffffffffffffe, 0xbff0000000000000, 0xffeffffffffffffe);
+  status |=
+      test__adddf3(0xffeffffffffffffe, 0xffeffffffffffffe, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xffeffffffffffffe, 0xffefffffffffffff, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xffefffffffffffff, 0x0000000000000001, 0xffefffffffffffff);
+  status |=
+      test__adddf3(0xffefffffffffffff, 0x3ff0000000000000, 0xffefffffffffffff);
+  status |=
+      test__adddf3(0xffefffffffffffff, 0xbff0000000000000, 0xffefffffffffffff);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xfff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0xfff0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__adddf3(0x3de3a83a83a83a83, 0xbff0000000000000, 0xbfefffffffec57c5);
+  status |=
+      test__adddf3(0x0000000007ffffff, 0x0010000000010000, 0x001000000800ffff);
+  status |=
+      test__adddf3(0x001effffffffffff, 0x0000000000400000, 0x001f0000003fffff);
+  status |=
+      test__adddf3(0x80000000000003ff, 0x801ffffbffffffff, 0x801ffffc000003fe);
+  status |=
+      test__adddf3(0x80003fffffffffff, 0x8010000000100000, 0x80104000000fffff);
 
   // Test that the result of an operation is a NaN at all when it should be.
   //
@@ -299,11 +544,16 @@ int main(void) {
   // encoding. We also use the same value as the input NaN in tests that have
   // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
   // because 0x7ff8000000000000 is still the exact expected NaN.
-  status |= test__adddf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
-  status |= test__adddf3(0xfff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
-  status |= test__adddf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
-  status |= test__adddf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
-  status |= test__adddf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__adddf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__adddf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
 
 #ifdef ARM_NAN_HANDLING
   // Tests specific to the NaN handling of Arm hardware, mimicked by
@@ -323,58 +573,110 @@ int main(void) {
   //
   //  - invalid operations not involving an input NaN return the quiet
   //    NaN with fewest bits set, 0x7ff8000000000000.
-  status |= test__adddf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
-  status |= test__adddf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
-  status |= test__adddf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
-  status |= test__adddf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
-  status |= test__adddf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
-  status |= test__adddf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
-  status |= test__adddf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
-  status |= test__adddf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
-  status |= test__adddf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
-  status |= test__adddf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
-  status |= test__adddf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
-  status |= test__adddf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
-  status |= test__adddf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
-  status |= test__adddf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
-  status |= test__adddf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
-  status |= test__adddf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
-  status |= test__adddf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
-  status |= test__adddf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
-  status |= test__adddf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
-  status |= test__adddf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
-  status |= test__adddf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
-  status |= test__adddf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
-  status |= test__adddf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
-  status |= test__adddf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
-  status |= test__adddf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
-  status |= test__adddf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
-  status |= test__adddf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
-  status |= test__adddf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
-  status |= test__adddf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
-  status |= test__adddf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
-  status |= test__adddf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
-  status |= test__adddf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
-  status |= test__adddf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
-  status |= test__adddf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
-  status |= test__adddf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
-  status |= test__adddf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
-  status |= test__adddf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
-  status |= test__adddf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
-  status |= test__adddf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
-  status |= test__adddf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
-  status |= test__adddf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
-  status |= test__adddf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
-  status |= test__adddf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
-  status |= test__adddf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
-  status |= test__adddf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
-  status |= test__adddf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
-  status |= test__adddf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
-  status |= test__adddf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
-  status |= test__adddf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
-  status |= test__adddf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
-  status |= test__adddf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
-  status |= test__adddf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+  status |=
+      test__adddf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |=
+      test__adddf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |=
+      test__adddf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |=
+      test__adddf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |=
+      test__adddf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |=
+      test__adddf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |=
+      test__adddf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |=
+      test__adddf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |=
+      test__adddf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |=
+      test__adddf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |=
+      test__adddf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |=
+      test__adddf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |=
+      test__adddf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |=
+      test__adddf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |=
+      test__adddf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |=
+      test__adddf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |=
+      test__adddf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |=
+      test__adddf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |=
+      test__adddf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |=
+      test__adddf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |=
+      test__adddf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |=
+      test__adddf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |=
+      test__adddf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |=
+      test__adddf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |=
+      test__adddf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |=
+      test__adddf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |=
+      test__adddf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |=
+      test__adddf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |=
+      test__adddf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |=
+      test__adddf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |=
+      test__adddf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |=
+      test__adddf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |=
+      test__adddf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |=
+      test__adddf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |=
+      test__adddf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |=
+      test__adddf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |=
+      test__adddf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |=
+      test__adddf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |=
+      test__adddf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |=
+      test__adddf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |=
+      test__adddf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |=
+      test__adddf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |=
+      test__adddf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |=
+      test__adddf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |=
+      test__adddf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |=
+      test__adddf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |=
+      test__adddf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |=
+      test__adddf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |=
+      test__adddf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
 
 #endif // ARM_NAN_HANDLING
 
diff --git a/compiler-rt/test/builtins/Unit/subdf3new_test.c b/compiler-rt/test/builtins/Unit/subdf3new_test.c
index 5ed19d4c85847..16132ea920a88 100644
--- a/compiler-rt/test/builtins/Unit/subdf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/subdf3new_test.c
@@ -24,7 +24,8 @@
 // Returns: a - b
 COMPILER_RT_ABI double __subdf3(double a, double b);
 
-int test__subdf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+int test__subdf3(int line, uint64_t a_rep, uint64_t b_rep,
+                 uint64_t expected_rep) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __subdf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -34,273 +35,528 @@ int test__subdf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep
 #endif
 
   if (ret) {
-    printf("error at line %d: __subdf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
-           ", expected %016" PRIx64 "\n",
+    printf("error at line %d: __subdf3(%016" PRIx64 ", %016" PRIx64
+           ") = %016" PRIx64 ", expected %016" PRIx64 "\n",
            line, a_rep, b_rep, toRep64(x), expected_rep);
   }
   return ret;
 }
 
-#define test__subdf3(a,b,x) test__subdf3(__LINE__,a,b,x)
+#define test__subdf3(a, b, x) test__subdf3(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;
 
-  status |= test__subdf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x0000000000000000, 0x000fffffffffffff, 0x800fffffffffffff);
-  status |= test__subdf3(0x0000000000000000, 0x0010000000000000, 0x8010000000000000);
-  status |= test__subdf3(0x0000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0x0000000000000000, 0x8000000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x0000000000000000, 0x800fffffffffffff, 0x000fffffffffffff);
-  status |= test__subdf3(0x0000000000000000, 0xbff0000000000000, 0x3ff0000000000000);
-  status |= test__subdf3(0x0000000000000000, 0xffe0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x0000000000000000, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000000);
-  status |= test__subdf3(0x0000000000000001, 0x8000000000000001, 0x0000000000000002);
-  status |= test__subdf3(0x0000000000000001, 0xbfefffffffffffff, 0x3fefffffffffffff);
-  status |= test__subdf3(0x0000000000000001, 0xbff0000000000000, 0x3ff0000000000000);
-  status |= test__subdf3(0x0000000000000001, 0xbffffffffffffffe, 0x3ffffffffffffffe);
-  status |= test__subdf3(0x0000000000000001, 0xbfffffffffffffff, 0x3fffffffffffffff);
-  status |= test__subdf3(0x0000000000000001, 0xffdfffffffffffff, 0x7fdfffffffffffff);
-  status |= test__subdf3(0x0000000000000001, 0xffe0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x0000000000000001, 0xffeffffffffffffe, 0x7feffffffffffffe);
-  status |= test__subdf3(0x0000000000000001, 0xffefffffffffffff, 0x7fefffffffffffff);
-  status |= test__subdf3(0x0000000000000002, 0x0000000000000001, 0x0000000000000001);
-  status |= test__subdf3(0x0000000000000003, 0x0000000000000000, 0x0000000000000003);
-  status |= test__subdf3(0x0000000000000003, 0x0000000000000002, 0x0000000000000001);
-  status |= test__subdf3(0x0000000000000003, 0x4014000000000000, 0xc014000000000000);
-  status |= test__subdf3(0x0000000000000003, 0x7fe0000000000000, 0xffe0000000000000);
-  status |= test__subdf3(0x0000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0x0000000000000003, 0x8000000000000000, 0x0000000000000003);
-  status |= test__subdf3(0x0000000000000003, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x0000000000000004, 0x8000000000000004, 0x0000000000000008);
-  status |= test__subdf3(0x000ffffffffffffc, 0x000ffffffffffffc, 0x0000000000000000);
-  status |= test__subdf3(0x000ffffffffffffd, 0x000ffffffffffffe, 0x8000000000000001);
-  status |= test__subdf3(0x000fffffffffffff, 0x000ffffffffffffe, 0x0000000000000001);
-  status |= test__subdf3(0x000fffffffffffff, 0x0010000000000000, 0x8000000000000001);
-  status |= test__subdf3(0x000fffffffffffff, 0x800fffffffffffff, 0x001ffffffffffffe);
-  status |= test__subdf3(0x0010000000000000, 0x0010000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x0010000000000000, 0x8000000000000000, 0x0010000000000000);
-  status |= test__subdf3(0x0010000000000000, 0x8010000000000000, 0x0020000000000000);
-  status |= test__subdf3(0x0010000000000001, 0x0010000000000000, 0x0000000000000001);
-  status |= test__subdf3(0x0010000000000001, 0x0010000000000002, 0x8000000000000001);
-  status |= test__subdf3(0x001fffffffffffff, 0x0020000000000000, 0x8000000000000001);
-  status |= test__subdf3(0x001fffffffffffff, 0x0020000000000002, 0x8000000000000005);
-  status |= test__subdf3(0x001fffffffffffff, 0x0020000000000004, 0x8000000000000009);
-  status |= test__subdf3(0x0020000000000000, 0x001fffffffffffff, 0x0000000000000001);
-  status |= test__subdf3(0x0020000000000001, 0x0010000000000001, 0x0010000000000001);
-  status |= test__subdf3(0x0020000000000001, 0x001fffffffffffff, 0x0000000000000003);
-  status |= test__subdf3(0x0020000000000002, 0x0010000000000001, 0x0010000000000003);
-  status |= test__subdf3(0x002fffffffffffff, 0x0030000000000000, 0x8000000000000002);
-  status |= test__subdf3(0x0030000000000000, 0x002fffffffffffff, 0x0000000000000002);
-  status |= test__subdf3(0x0030000000000001, 0x002fffffffffffff, 0x0000000000000006);
-  status |= test__subdf3(0x0030000000000002, 0x0020000000000003, 0x0020000000000001);
-  status |= test__subdf3(0x3fefffffffffffff, 0x0000000000000001, 0x3fefffffffffffff);
-  status |= test__subdf3(0x3ff0000000000000, 0x0000000000000000, 0x3ff0000000000000);
-  status |= test__subdf3(0x3ff0000000000000, 0x3ff0000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x3ff0000000000000, 0xbff0000000000000, 0x4000000000000000);
-  status |= test__subdf3(0x3ff0000000000000, 0xbff0000000000003, 0x4000000000000002);
-  status |= test__subdf3(0x3ff0000000000000, 0xc000000000000000, 0x4008000000000000);
-  status |= test__subdf3(0x3ff0000000000000, 0xc01c000000000000, 0x4020000000000000);
-  status |= test__subdf3(0x3ff0000000000001, 0x3ff0000000000000, 0x3cb0000000000000);
-  status |= test__subdf3(0x3ff0000000000001, 0x3ff0000000000002, 0xbcb0000000000000);
-  status |= test__subdf3(0x3ff0000000000001, 0xbff0000000000000, 0x4000000000000000);
-  status |= test__subdf3(0x3ffffffffffffffc, 0x3ffffffffffffffd, 0xbcb0000000000000);
-  status |= test__subdf3(0x3fffffffffffffff, 0x4000000000000000, 0xbcb0000000000000);
-  status |= test__subdf3(0x4000000000000000, 0x3fffffffffffffff, 0x3cb0000000000000);
-  status |= test__subdf3(0x4000000000000000, 0x4000000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x4000000000000000, 0x4000000000000001, 0xbcc0000000000000);
-  status |= test__subdf3(0x4000000000000000, 0x4014000000000000, 0xc008000000000000);
-  status |= test__subdf3(0x4000000000000000, 0xbcb0000000000000, 0x4000000000000000);
-  status |= test__subdf3(0x4000000000000000, 0xbff0000000000000, 0x4008000000000000);
-  status |= test__subdf3(0x4000000000000000, 0xc000000000000000, 0x4010000000000000);
-  status |= test__subdf3(0x4000000000000000, 0xc000000000000001, 0x4010000000000000);
-  status |= test__subdf3(0x4000000000000001, 0x3ff0000000000001, 0x3ff0000000000001);
-  status |= test__subdf3(0x4000000000000001, 0xbcb0000000000000, 0x4000000000000002);
-  status |= test__subdf3(0x4000000000000001, 0xc000000000000002, 0x4010000000000002);
-  status |= test__subdf3(0x4000000000000002, 0x3ff0000000000001, 0x3ff0000000000003);
-  status |= test__subdf3(0x4000000000000002, 0x3ff0000000000003, 0x3ff0000000000001);
-  status |= test__subdf3(0x4000000000000004, 0x4000000000000003, 0x3cc0000000000000);
-  status |= test__subdf3(0x4008000000000000, 0xc008000000000000, 0x4018000000000000);
-  status |= test__subdf3(0x400fffffffffffff, 0x400ffffffffffffe, 0x3cc0000000000000);
-  status |= test__subdf3(0x400fffffffffffff, 0x4010000000000002, 0xbce4000000000000);
-  status |= test__subdf3(0x400fffffffffffff, 0xbcafffffffffffff, 0x400fffffffffffff);
-  status |= test__subdf3(0x400fffffffffffff, 0xbcb0000000000000, 0x4010000000000000);
-  status |= test__subdf3(0x4010000000000001, 0x400fffffffffffff, 0x3cd8000000000000);
-  status |= test__subdf3(0x4014000000000000, 0x0000000000000000, 0x4014000000000000);
-  status |= test__subdf3(0x4014000000000000, 0x3ff0000000000000, 0x4010000000000000);
-  status |= test__subdf3(0x4014000000000000, 0x4014000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x4014000000000000, 0x8000000000000000, 0x4014000000000000);
-  status |= test__subdf3(0x4280000000000001, 0x3ff0017fffffffff, 0x427ffffffffff001);
-  status |= test__subdf3(0x7fb0000000000001, 0x7fafffffffffffff, 0x7c78000000000000);
-  status |= test__subdf3(0x7fcfffffffffffff, 0x7fcffffffffffffe, 0x7c80000000000000);
-  status |= test__subdf3(0x7fcfffffffffffff, 0x7fd0000000000002, 0xfca4000000000000);
-  status |= test__subdf3(0x7fd0000000000000, 0x7fcfffffffffffff, 0x7c80000000000000);
-  status |= test__subdf3(0x7fd0000000000000, 0x7fd0000000000001, 0xfc90000000000000);
-  status |= test__subdf3(0x7fd0000000000000, 0xffd0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x7fd0000000000001, 0x7fe0000000000001, 0xffd0000000000001);
-  status |= test__subdf3(0x7fd0000000000001, 0xffd0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x7fd0000000000002, 0x7fc0000000000003, 0x7fc0000000000001);
-  status |= test__subdf3(0x7fd0000000000004, 0x7fd0000000000003, 0x7c90000000000000);
-  status |= test__subdf3(0x7fdffffffffffffe, 0xffdffffffffffffe, 0x7feffffffffffffe);
-  status |= test__subdf3(0x7fdffffffffffffe, 0xffdfffffffffffff, 0x7feffffffffffffe);
-  status |= test__subdf3(0x7fdfffffffffffff, 0x3ff0000000000000, 0x7fdfffffffffffff);
-  status |= test__subdf3(0x7fdfffffffffffff, 0x7fe0000000000000, 0xfc90000000000000);
-  status |= test__subdf3(0x7fdfffffffffffff, 0xbff0000000000000, 0x7fdfffffffffffff);
-  status |= test__subdf3(0x7fdfffffffffffff, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7fe0000000000000, 0x3ff0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x7fe0000000000000, 0x7fe0000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x7fe0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0x7fe0000000000000, 0xbff0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x7fe0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7fe0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7fe0000000000001, 0x7fe0000000000000, 0x7ca0000000000000);
-  status |= test__subdf3(0x7fe0000000000001, 0x7fe0000000000002, 0xfca0000000000000);
-  status |= test__subdf3(0x7fe0000000000001, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7fe0000000000002, 0x7fd0000000000001, 0x7fd0000000000003);
-  status |= test__subdf3(0x7feffffffffffffe, 0x3ff0000000000000, 0x7feffffffffffffe);
-  status |= test__subdf3(0x7feffffffffffffe, 0x7fefffffffffffff, 0xfca0000000000000);
-  status |= test__subdf3(0x7feffffffffffffe, 0xbff0000000000000, 0x7feffffffffffffe);
-  status |= test__subdf3(0x7feffffffffffffe, 0xffeffffffffffffe, 0x7ff0000000000000);
-  status |= test__subdf3(0x7feffffffffffffe, 0xffefffffffffffff, 0x7ff0000000000000);
-  status |= test__subdf3(0x7fefffffffffffff, 0x0000000000000001, 0x7fefffffffffffff);
-  status |= test__subdf3(0x7fefffffffffffff, 0x3ff0000000000000, 0x7fefffffffffffff);
-  status |= test__subdf3(0x7fefffffffffffff, 0x7fefffffffffffff, 0x0000000000000000);
-  status |= test__subdf3(0x7fefffffffffffff, 0xbff0000000000000, 0x7fefffffffffffff);
-  status |= test__subdf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
-  status |= test__subdf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7ff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
-  status |= test__subdf3(0x7ff0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x8000000000000000, 0x0000000000000000, 0x8000000000000000);
-  status |= test__subdf3(0x8000000000000000, 0x000fffffffffffff, 0x800fffffffffffff);
-  status |= test__subdf3(0x8000000000000000, 0x0010000000000000, 0x8010000000000000);
-  status |= test__subdf3(0x8000000000000000, 0x3ff0000000000000, 0xbff0000000000000);
-  status |= test__subdf3(0x8000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0x8000000000000000, 0x8000000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x8000000000000000, 0x800fffffffffffff, 0x000fffffffffffff);
-  status |= test__subdf3(0x8000000000000000, 0xffe0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x8000000000000000, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x8000000000000001, 0x0000000000000001, 0x8000000000000002);
-  status |= test__subdf3(0x8000000000000001, 0x3fefffffffffffff, 0xbfefffffffffffff);
-  status |= test__subdf3(0x8000000000000001, 0x3ff0000000000000, 0xbff0000000000000);
-  status |= test__subdf3(0x8000000000000001, 0x3ffffffffffffffe, 0xbffffffffffffffe);
-  status |= test__subdf3(0x8000000000000001, 0x3fffffffffffffff, 0xbfffffffffffffff);
-  status |= test__subdf3(0x8000000000000001, 0x7fdfffffffffffff, 0xffdfffffffffffff);
-  status |= test__subdf3(0x8000000000000001, 0x7fe0000000000000, 0xffe0000000000000);
-  status |= test__subdf3(0x8000000000000001, 0x7feffffffffffffe, 0xffeffffffffffffe);
-  status |= test__subdf3(0x8000000000000001, 0x7fefffffffffffff, 0xffefffffffffffff);
-  status |= test__subdf3(0x8000000000000001, 0x8000000000000001, 0x0000000000000000);
-  status |= test__subdf3(0x8000000000000002, 0x8000000000000001, 0x8000000000000001);
-  status |= test__subdf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000003);
-  status |= test__subdf3(0x8000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0x8000000000000003, 0x8000000000000000, 0x8000000000000003);
-  status |= test__subdf3(0x8000000000000003, 0x8000000000000002, 0x8000000000000001);
-  status |= test__subdf3(0x8000000000000003, 0xc008000000000000, 0x4008000000000000);
-  status |= test__subdf3(0x8000000000000003, 0xffe0000000000000, 0x7fe0000000000000);
-  status |= test__subdf3(0x8000000000000003, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0x8000000000000004, 0x0000000000000004, 0x8000000000000008);
-  status |= test__subdf3(0x800ffffffffffffd, 0x800ffffffffffffe, 0x0000000000000001);
-  status |= test__subdf3(0x800fffffffffffff, 0x000fffffffffffff, 0x801ffffffffffffe);
-  status |= test__subdf3(0x800fffffffffffff, 0x800ffffffffffffe, 0x8000000000000001);
-  status |= test__subdf3(0x800fffffffffffff, 0x800fffffffffffff, 0x0000000000000000);
-  status |= test__subdf3(0x800fffffffffffff, 0x8010000000000000, 0x0000000000000001);
-  status |= test__subdf3(0x8010000000000000, 0x8000000000000000, 0x8010000000000000);
-  status |= test__subdf3(0x8010000000000000, 0x8010000000000000, 0x0000000000000000);
-  status |= test__subdf3(0x8010000000000001, 0x8010000000000000, 0x8000000000000001);
-  status |= test__subdf3(0x8010000000000001, 0x8010000000000002, 0x0000000000000001);
-  status |= test__subdf3(0x801fffffffffffff, 0x8020000000000000, 0x0000000000000001);
-  status |= test__subdf3(0x801fffffffffffff, 0x8020000000000002, 0x0000000000000005);
-  status |= test__subdf3(0x801fffffffffffff, 0x8020000000000004, 0x0000000000000009);
-  status |= test__subdf3(0x8020000000000000, 0x801fffffffffffff, 0x8000000000000001);
-  status |= test__subdf3(0x8020000000000001, 0x8010000000000001, 0x8010000000000001);
-  status |= test__subdf3(0x8020000000000001, 0x801fffffffffffff, 0x8000000000000003);
-  status |= test__subdf3(0x8020000000000002, 0x8010000000000001, 0x8010000000000003);
-  status |= test__subdf3(0x802fffffffffffff, 0x8030000000000000, 0x0000000000000002);
-  status |= test__subdf3(0x8030000000000000, 0x802fffffffffffff, 0x8000000000000002);
-  status |= test__subdf3(0x8030000000000001, 0x802fffffffffffff, 0x8000000000000006);
-  status |= test__subdf3(0x8030000000000002, 0x8020000000000003, 0x8020000000000001);
-  status |= test__subdf3(0xbff0000000000000, 0x0000000000000000, 0xbff0000000000000);
-  status |= test__subdf3(0xbff0000000000000, 0x3ff0000000000003, 0xc000000000000002);
-  status |= test__subdf3(0xbff0000000000001, 0x3ff0000000000000, 0xc000000000000000);
-  status |= test__subdf3(0xbff0000000000001, 0xbff0000000000000, 0xbcb0000000000000);
-  status |= test__subdf3(0xbff0000000000001, 0xbff0000000000002, 0x3cb0000000000000);
-  status |= test__subdf3(0xbffffffffffffffc, 0xbffffffffffffffd, 0x3cb0000000000000);
-  status |= test__subdf3(0xbfffffffffffffff, 0x8000000000000001, 0xbfffffffffffffff);
-  status |= test__subdf3(0xbfffffffffffffff, 0xc000000000000000, 0x3cb0000000000000);
-  status |= test__subdf3(0xc000000000000000, 0x4000000000000001, 0xc010000000000000);
-  status |= test__subdf3(0xc000000000000000, 0xbfffffffffffffff, 0xbcb0000000000000);
-  status |= test__subdf3(0xc000000000000000, 0xc000000000000001, 0x3cc0000000000000);
-  status |= test__subdf3(0xc000000000000001, 0x4000000000000002, 0xc010000000000002);
-  status |= test__subdf3(0xc000000000000001, 0xbff0000000000001, 0xbff0000000000001);
-  status |= test__subdf3(0xc000000000000002, 0xbff0000000000001, 0xbff0000000000003);
-  status |= test__subdf3(0xc000000000000002, 0xbff0000000000003, 0xbff0000000000001);
-  status |= test__subdf3(0xc000000000000004, 0xc000000000000003, 0xbcc0000000000000);
-  status |= test__subdf3(0xc008000000000000, 0xc008000000000000, 0x0000000000000000);
-  status |= test__subdf3(0xc00fffffffffffff, 0x3cafffffffffffff, 0xc00fffffffffffff);
-  status |= test__subdf3(0xc00fffffffffffff, 0x3cb0000000000000, 0xc010000000000000);
-  status |= test__subdf3(0xc00fffffffffffff, 0xc00ffffffffffffe, 0xbcc0000000000000);
-  status |= test__subdf3(0xc00fffffffffffff, 0xc010000000000002, 0x3ce4000000000000);
-  status |= test__subdf3(0xc010000000000001, 0xc00fffffffffffff, 0xbcd8000000000000);
-  status |= test__subdf3(0xffb0000000000001, 0xffafffffffffffff, 0xfc78000000000000);
-  status |= test__subdf3(0xffcfffffffffffff, 0xffcffffffffffffe, 0xfc80000000000000);
-  status |= test__subdf3(0xffcfffffffffffff, 0xffd0000000000002, 0x7ca4000000000000);
-  status |= test__subdf3(0xffd0000000000000, 0xffcfffffffffffff, 0xfc80000000000000);
-  status |= test__subdf3(0xffd0000000000000, 0xffd0000000000001, 0x7c90000000000000);
-  status |= test__subdf3(0xffd0000000000001, 0x7fd0000000000000, 0xffe0000000000000);
-  status |= test__subdf3(0xffd0000000000001, 0xffe0000000000001, 0x7fd0000000000001);
-  status |= test__subdf3(0xffd0000000000002, 0xffc0000000000003, 0xffc0000000000001);
-  status |= test__subdf3(0xffd0000000000004, 0xffd0000000000003, 0xfc90000000000000);
-  status |= test__subdf3(0xffdffffffffffffe, 0x7fdffffffffffffe, 0xffeffffffffffffe);
-  status |= test__subdf3(0xffdffffffffffffe, 0x7fdfffffffffffff, 0xffeffffffffffffe);
-  status |= test__subdf3(0xffdffffffffffffe, 0xffdffffffffffffe, 0x0000000000000000);
-  status |= test__subdf3(0xffdfffffffffffff, 0x3ff0000000000000, 0xffdfffffffffffff);
-  status |= test__subdf3(0xffdfffffffffffff, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xffdfffffffffffff, 0xbff0000000000000, 0xffdfffffffffffff);
-  status |= test__subdf3(0xffdfffffffffffff, 0xffe0000000000000, 0x7c90000000000000);
-  status |= test__subdf3(0xffe0000000000000, 0x0000000000000000, 0xffe0000000000000);
-  status |= test__subdf3(0xffe0000000000000, 0x3ff0000000000000, 0xffe0000000000000);
-  status |= test__subdf3(0xffe0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xffe0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xffe0000000000000, 0x8000000000000000, 0xffe0000000000000);
-  status |= test__subdf3(0xffe0000000000000, 0xbff0000000000000, 0xffe0000000000000);
-  status |= test__subdf3(0xffe0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__subdf3(0xffe0000000000001, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xffe0000000000001, 0xffe0000000000000, 0xfca0000000000000);
-  status |= test__subdf3(0xffe0000000000001, 0xffe0000000000002, 0x7ca0000000000000);
-  status |= test__subdf3(0xffe0000000000002, 0xffd0000000000001, 0xffd0000000000003);
-  status |= test__subdf3(0xffeffffffffffffe, 0x3ff0000000000000, 0xffeffffffffffffe);
-  status |= test__subdf3(0xffeffffffffffffe, 0x7feffffffffffffe, 0xfff0000000000000);
-  status |= test__subdf3(0xffeffffffffffffe, 0x7fefffffffffffff, 0xfff0000000000000);
-  status |= test__subdf3(0xffeffffffffffffe, 0xbff0000000000000, 0xffeffffffffffffe);
-  status |= test__subdf3(0xffeffffffffffffe, 0xffefffffffffffff, 0x7ca0000000000000);
-  status |= test__subdf3(0xffefffffffffffff, 0x3ff0000000000000, 0xffefffffffffffff);
-  status |= test__subdf3(0xffefffffffffffff, 0x8000000000000001, 0xffefffffffffffff);
-  status |= test__subdf3(0xffefffffffffffff, 0xbff0000000000000, 0xffefffffffffffff);
-  status |= test__subdf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
-  status |= test__subdf3(0xfff0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xfff0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xfff0000000000000, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0xfff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
-  status |= test__subdf3(0xfff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__subdf3(0x004caed458edc883, 0x004f7fc23eeef153, 0x8016876f30094680);
-  status |= test__subdf3(0x0028000000000000, 0x0010000000000001, 0x001fffffffffffff);
-  status |= test__subdf3(0x0028000000000000, 0x0010000000000000, 0x0020000000000000);
-  status |= test__subdf3(0x001fffffffffffff, 0x0010000000000000, 0x000fffffffffffff);
-  status |= test__subdf3(0x001fffffffffffff, 0x000fffffffffffff, 0x0010000000000000);
-  status |= test__subdf3(0x0020000000000000, 0x0010000000000000, 0x0010000000000000);
-  status |= test__subdf3(0x0038000000000000, 0x0034000000000001, 0x000ffffffffffffc);
-  status |= test__subdf3(0x0038000000000000, 0x0034000000000000, 0x0010000000000000);
-  status |= test__subdf3(0x0038000000000000, 0x0030000000000001, 0x001ffffffffffffc);
-  status |= test__subdf3(0x0038000000000000, 0x0030000000000000, 0x0020000000000000);
-  status |= test__subdf3(0x000fffffffe00000, 0x801000000007ffff, 0x001fffffffe7ffff);
-  status |= test__subdf3(0x0010000000004000, 0x800effffffffffff, 0x001f000000003fff);
-  status |= test__subdf3(0x800000000fffffff, 0x001ffff000000000, 0x801ffff00fffffff);
-  status |= test__subdf3(0x800fffff80000000, 0x001000000fffffff, 0x801fffff8fffffff);
-  status |= test__subdf3(0x80100000001fffff, 0x000ffffeffffffff, 0x801fffff001ffffe);
+  status |=
+      test__subdf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x0000000000000000, 0x000fffffffffffff, 0x800fffffffffffff);
+  status |=
+      test__subdf3(0x0000000000000000, 0x0010000000000000, 0x8010000000000000);
+  status |=
+      test__subdf3(0x0000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0x0000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x0000000000000000, 0x800fffffffffffff, 0x000fffffffffffff);
+  status |=
+      test__subdf3(0x0000000000000000, 0xbff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__subdf3(0x0000000000000000, 0xffe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x0000000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000000);
+  status |=
+      test__subdf3(0x0000000000000001, 0x8000000000000001, 0x0000000000000002);
+  status |=
+      test__subdf3(0x0000000000000001, 0xbfefffffffffffff, 0x3fefffffffffffff);
+  status |=
+      test__subdf3(0x0000000000000001, 0xbff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__subdf3(0x0000000000000001, 0xbffffffffffffffe, 0x3ffffffffffffffe);
+  status |=
+      test__subdf3(0x0000000000000001, 0xbfffffffffffffff, 0x3fffffffffffffff);
+  status |=
+      test__subdf3(0x0000000000000001, 0xffdfffffffffffff, 0x7fdfffffffffffff);
+  status |=
+      test__subdf3(0x0000000000000001, 0xffe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x0000000000000001, 0xffeffffffffffffe, 0x7feffffffffffffe);
+  status |=
+      test__subdf3(0x0000000000000001, 0xffefffffffffffff, 0x7fefffffffffffff);
+  status |=
+      test__subdf3(0x0000000000000002, 0x0000000000000001, 0x0000000000000001);
+  status |=
+      test__subdf3(0x0000000000000003, 0x0000000000000000, 0x0000000000000003);
+  status |=
+      test__subdf3(0x0000000000000003, 0x0000000000000002, 0x0000000000000001);
+  status |=
+      test__subdf3(0x0000000000000003, 0x4014000000000000, 0xc014000000000000);
+  status |=
+      test__subdf3(0x0000000000000003, 0x7fe0000000000000, 0xffe0000000000000);
+  status |=
+      test__subdf3(0x0000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0x0000000000000003, 0x8000000000000000, 0x0000000000000003);
+  status |=
+      test__subdf3(0x0000000000000003, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x0000000000000004, 0x8000000000000004, 0x0000000000000008);
+  status |=
+      test__subdf3(0x000ffffffffffffc, 0x000ffffffffffffc, 0x0000000000000000);
+  status |=
+      test__subdf3(0x000ffffffffffffd, 0x000ffffffffffffe, 0x8000000000000001);
+  status |=
+      test__subdf3(0x000fffffffffffff, 0x000ffffffffffffe, 0x0000000000000001);
+  status |=
+      test__subdf3(0x000fffffffffffff, 0x0010000000000000, 0x8000000000000001);
+  status |=
+      test__subdf3(0x000fffffffffffff, 0x800fffffffffffff, 0x001ffffffffffffe);
+  status |=
+      test__subdf3(0x0010000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x0010000000000000, 0x8000000000000000, 0x0010000000000000);
+  status |=
+      test__subdf3(0x0010000000000000, 0x8010000000000000, 0x0020000000000000);
+  status |=
+      test__subdf3(0x0010000000000001, 0x0010000000000000, 0x0000000000000001);
+  status |=
+      test__subdf3(0x0010000000000001, 0x0010000000000002, 0x8000000000000001);
+  status |=
+      test__subdf3(0x001fffffffffffff, 0x0020000000000000, 0x8000000000000001);
+  status |=
+      test__subdf3(0x001fffffffffffff, 0x0020000000000002, 0x8000000000000005);
+  status |=
+      test__subdf3(0x001fffffffffffff, 0x0020000000000004, 0x8000000000000009);
+  status |=
+      test__subdf3(0x0020000000000000, 0x001fffffffffffff, 0x0000000000000001);
+  status |=
+      test__subdf3(0x0020000000000001, 0x0010000000000001, 0x0010000000000001);
+  status |=
+      test__subdf3(0x0020000000000001, 0x001fffffffffffff, 0x0000000000000003);
+  status |=
+      test__subdf3(0x0020000000000002, 0x0010000000000001, 0x0010000000000003);
+  status |=
+      test__subdf3(0x002fffffffffffff, 0x0030000000000000, 0x8000000000000002);
+  status |=
+      test__subdf3(0x0030000000000000, 0x002fffffffffffff, 0x0000000000000002);
+  status |=
+      test__subdf3(0x0030000000000001, 0x002fffffffffffff, 0x0000000000000006);
+  status |=
+      test__subdf3(0x0030000000000002, 0x0020000000000003, 0x0020000000000001);
+  status |=
+      test__subdf3(0x3fefffffffffffff, 0x0000000000000001, 0x3fefffffffffffff);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0x0000000000000000, 0x3ff0000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0x3ff0000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0xbff0000000000000, 0x4000000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0xbff0000000000003, 0x4000000000000002);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0xc000000000000000, 0x4008000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0xc01c000000000000, 0x4020000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000001, 0x3ff0000000000000, 0x3cb0000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000001, 0x3ff0000000000002, 0xbcb0000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000001, 0xbff0000000000000, 0x4000000000000000);
+  status |=
+      test__subdf3(0x3ffffffffffffffc, 0x3ffffffffffffffd, 0xbcb0000000000000);
+  status |=
+      test__subdf3(0x3fffffffffffffff, 0x4000000000000000, 0xbcb0000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0x3fffffffffffffff, 0x3cb0000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0x4000000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0x4000000000000001, 0xbcc0000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0x4014000000000000, 0xc008000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0xbcb0000000000000, 0x4000000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0xbff0000000000000, 0x4008000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0xc000000000000000, 0x4010000000000000);
+  status |=
+      test__subdf3(0x4000000000000000, 0xc000000000000001, 0x4010000000000000);
+  status |=
+      test__subdf3(0x4000000000000001, 0x3ff0000000000001, 0x3ff0000000000001);
+  status |=
+      test__subdf3(0x4000000000000001, 0xbcb0000000000000, 0x4000000000000002);
+  status |=
+      test__subdf3(0x4000000000000001, 0xc000000000000002, 0x4010000000000002);
+  status |=
+      test__subdf3(0x4000000000000002, 0x3ff0000000000001, 0x3ff0000000000003);
+  status |=
+      test__subdf3(0x4000000000000002, 0x3ff0000000000003, 0x3ff0000000000001);
+  status |=
+      test__subdf3(0x4000000000000004, 0x4000000000000003, 0x3cc0000000000000);
+  status |=
+      test__subdf3(0x4008000000000000, 0xc008000000000000, 0x4018000000000000);
+  status |=
+      test__subdf3(0x400fffffffffffff, 0x400ffffffffffffe, 0x3cc0000000000000);
+  status |=
+      test__subdf3(0x400fffffffffffff, 0x4010000000000002, 0xbce4000000000000);
+  status |=
+      test__subdf3(0x400fffffffffffff, 0xbcafffffffffffff, 0x400fffffffffffff);
+  status |=
+      test__subdf3(0x400fffffffffffff, 0xbcb0000000000000, 0x4010000000000000);
+  status |=
+      test__subdf3(0x4010000000000001, 0x400fffffffffffff, 0x3cd8000000000000);
+  status |=
+      test__subdf3(0x4014000000000000, 0x0000000000000000, 0x4014000000000000);
+  status |=
+      test__subdf3(0x4014000000000000, 0x3ff0000000000000, 0x4010000000000000);
+  status |=
+      test__subdf3(0x4014000000000000, 0x4014000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x4014000000000000, 0x8000000000000000, 0x4014000000000000);
+  status |=
+      test__subdf3(0x4280000000000001, 0x3ff0017fffffffff, 0x427ffffffffff001);
+  status |=
+      test__subdf3(0x7fb0000000000001, 0x7fafffffffffffff, 0x7c78000000000000);
+  status |=
+      test__subdf3(0x7fcfffffffffffff, 0x7fcffffffffffffe, 0x7c80000000000000);
+  status |=
+      test__subdf3(0x7fcfffffffffffff, 0x7fd0000000000002, 0xfca4000000000000);
+  status |=
+      test__subdf3(0x7fd0000000000000, 0x7fcfffffffffffff, 0x7c80000000000000);
+  status |=
+      test__subdf3(0x7fd0000000000000, 0x7fd0000000000001, 0xfc90000000000000);
+  status |=
+      test__subdf3(0x7fd0000000000000, 0xffd0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x7fd0000000000001, 0x7fe0000000000001, 0xffd0000000000001);
+  status |=
+      test__subdf3(0x7fd0000000000001, 0xffd0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x7fd0000000000002, 0x7fc0000000000003, 0x7fc0000000000001);
+  status |=
+      test__subdf3(0x7fd0000000000004, 0x7fd0000000000003, 0x7c90000000000000);
+  status |=
+      test__subdf3(0x7fdffffffffffffe, 0xffdffffffffffffe, 0x7feffffffffffffe);
+  status |=
+      test__subdf3(0x7fdffffffffffffe, 0xffdfffffffffffff, 0x7feffffffffffffe);
+  status |=
+      test__subdf3(0x7fdfffffffffffff, 0x3ff0000000000000, 0x7fdfffffffffffff);
+  status |=
+      test__subdf3(0x7fdfffffffffffff, 0x7fe0000000000000, 0xfc90000000000000);
+  status |=
+      test__subdf3(0x7fdfffffffffffff, 0xbff0000000000000, 0x7fdfffffffffffff);
+  status |=
+      test__subdf3(0x7fdfffffffffffff, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000000, 0x3ff0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000000, 0x7fe0000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000000, 0xbff0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000001, 0x7fe0000000000000, 0x7ca0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000001, 0x7fe0000000000002, 0xfca0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000001, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7fe0000000000002, 0x7fd0000000000001, 0x7fd0000000000003);
+  status |=
+      test__subdf3(0x7feffffffffffffe, 0x3ff0000000000000, 0x7feffffffffffffe);
+  status |=
+      test__subdf3(0x7feffffffffffffe, 0x7fefffffffffffff, 0xfca0000000000000);
+  status |=
+      test__subdf3(0x7feffffffffffffe, 0xbff0000000000000, 0x7feffffffffffffe);
+  status |=
+      test__subdf3(0x7feffffffffffffe, 0xffeffffffffffffe, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7feffffffffffffe, 0xffefffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7fefffffffffffff, 0x0000000000000001, 0x7fefffffffffffff);
+  status |=
+      test__subdf3(0x7fefffffffffffff, 0x3ff0000000000000, 0x7fefffffffffffff);
+  status |=
+      test__subdf3(0x7fefffffffffffff, 0x7fefffffffffffff, 0x0000000000000000);
+  status |=
+      test__subdf3(0x7fefffffffffffff, 0xbff0000000000000, 0x7fefffffffffffff);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x8000000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__subdf3(0x8000000000000000, 0x000fffffffffffff, 0x800fffffffffffff);
+  status |=
+      test__subdf3(0x8000000000000000, 0x0010000000000000, 0x8010000000000000);
+  status |=
+      test__subdf3(0x8000000000000000, 0x3ff0000000000000, 0xbff0000000000000);
+  status |=
+      test__subdf3(0x8000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0x8000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x8000000000000000, 0x800fffffffffffff, 0x000fffffffffffff);
+  status |=
+      test__subdf3(0x8000000000000000, 0xffe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x8000000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x8000000000000001, 0x0000000000000001, 0x8000000000000002);
+  status |=
+      test__subdf3(0x8000000000000001, 0x3fefffffffffffff, 0xbfefffffffffffff);
+  status |=
+      test__subdf3(0x8000000000000001, 0x3ff0000000000000, 0xbff0000000000000);
+  status |=
+      test__subdf3(0x8000000000000001, 0x3ffffffffffffffe, 0xbffffffffffffffe);
+  status |=
+      test__subdf3(0x8000000000000001, 0x3fffffffffffffff, 0xbfffffffffffffff);
+  status |=
+      test__subdf3(0x8000000000000001, 0x7fdfffffffffffff, 0xffdfffffffffffff);
+  status |=
+      test__subdf3(0x8000000000000001, 0x7fe0000000000000, 0xffe0000000000000);
+  status |=
+      test__subdf3(0x8000000000000001, 0x7feffffffffffffe, 0xffeffffffffffffe);
+  status |=
+      test__subdf3(0x8000000000000001, 0x7fefffffffffffff, 0xffefffffffffffff);
+  status |=
+      test__subdf3(0x8000000000000001, 0x8000000000000001, 0x0000000000000000);
+  status |=
+      test__subdf3(0x8000000000000002, 0x8000000000000001, 0x8000000000000001);
+  status |=
+      test__subdf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000003);
+  status |=
+      test__subdf3(0x8000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0x8000000000000003, 0x8000000000000000, 0x8000000000000003);
+  status |=
+      test__subdf3(0x8000000000000003, 0x8000000000000002, 0x8000000000000001);
+  status |=
+      test__subdf3(0x8000000000000003, 0xc008000000000000, 0x4008000000000000);
+  status |=
+      test__subdf3(0x8000000000000003, 0xffe0000000000000, 0x7fe0000000000000);
+  status |=
+      test__subdf3(0x8000000000000003, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0x8000000000000004, 0x0000000000000004, 0x8000000000000008);
+  status |=
+      test__subdf3(0x800ffffffffffffd, 0x800ffffffffffffe, 0x0000000000000001);
+  status |=
+      test__subdf3(0x800fffffffffffff, 0x000fffffffffffff, 0x801ffffffffffffe);
+  status |=
+      test__subdf3(0x800fffffffffffff, 0x800ffffffffffffe, 0x8000000000000001);
+  status |=
+      test__subdf3(0x800fffffffffffff, 0x800fffffffffffff, 0x0000000000000000);
+  status |=
+      test__subdf3(0x800fffffffffffff, 0x8010000000000000, 0x0000000000000001);
+  status |=
+      test__subdf3(0x8010000000000000, 0x8000000000000000, 0x8010000000000000);
+  status |=
+      test__subdf3(0x8010000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0x8010000000000001, 0x8010000000000000, 0x8000000000000001);
+  status |=
+      test__subdf3(0x8010000000000001, 0x8010000000000002, 0x0000000000000001);
+  status |=
+      test__subdf3(0x801fffffffffffff, 0x8020000000000000, 0x0000000000000001);
+  status |=
+      test__subdf3(0x801fffffffffffff, 0x8020000000000002, 0x0000000000000005);
+  status |=
+      test__subdf3(0x801fffffffffffff, 0x8020000000000004, 0x0000000000000009);
+  status |=
+      test__subdf3(0x8020000000000000, 0x801fffffffffffff, 0x8000000000000001);
+  status |=
+      test__subdf3(0x8020000000000001, 0x8010000000000001, 0x8010000000000001);
+  status |=
+      test__subdf3(0x8020000000000001, 0x801fffffffffffff, 0x8000000000000003);
+  status |=
+      test__subdf3(0x8020000000000002, 0x8010000000000001, 0x8010000000000003);
+  status |=
+      test__subdf3(0x802fffffffffffff, 0x8030000000000000, 0x0000000000000002);
+  status |=
+      test__subdf3(0x8030000000000000, 0x802fffffffffffff, 0x8000000000000002);
+  status |=
+      test__subdf3(0x8030000000000001, 0x802fffffffffffff, 0x8000000000000006);
+  status |=
+      test__subdf3(0x8030000000000002, 0x8020000000000003, 0x8020000000000001);
+  status |=
+      test__subdf3(0xbff0000000000000, 0x0000000000000000, 0xbff0000000000000);
+  status |=
+      test__subdf3(0xbff0000000000000, 0x3ff0000000000003, 0xc000000000000002);
+  status |=
+      test__subdf3(0xbff0000000000001, 0x3ff0000000000000, 0xc000000000000000);
+  status |=
+      test__subdf3(0xbff0000000000001, 0xbff0000000000000, 0xbcb0000000000000);
+  status |=
+      test__subdf3(0xbff0000000000001, 0xbff0000000000002, 0x3cb0000000000000);
+  status |=
+      test__subdf3(0xbffffffffffffffc, 0xbffffffffffffffd, 0x3cb0000000000000);
+  status |=
+      test__subdf3(0xbfffffffffffffff, 0x8000000000000001, 0xbfffffffffffffff);
+  status |=
+      test__subdf3(0xbfffffffffffffff, 0xc000000000000000, 0x3cb0000000000000);
+  status |=
+      test__subdf3(0xc000000000000000, 0x4000000000000001, 0xc010000000000000);
+  status |=
+      test__subdf3(0xc000000000000000, 0xbfffffffffffffff, 0xbcb0000000000000);
+  status |=
+      test__subdf3(0xc000000000000000, 0xc000000000000001, 0x3cc0000000000000);
+  status |=
+      test__subdf3(0xc000000000000001, 0x4000000000000002, 0xc010000000000002);
+  status |=
+      test__subdf3(0xc000000000000001, 0xbff0000000000001, 0xbff0000000000001);
+  status |=
+      test__subdf3(0xc000000000000002, 0xbff0000000000001, 0xbff0000000000003);
+  status |=
+      test__subdf3(0xc000000000000002, 0xbff0000000000003, 0xbff0000000000001);
+  status |=
+      test__subdf3(0xc000000000000004, 0xc000000000000003, 0xbcc0000000000000);
+  status |=
+      test__subdf3(0xc008000000000000, 0xc008000000000000, 0x0000000000000000);
+  status |=
+      test__subdf3(0xc00fffffffffffff, 0x3cafffffffffffff, 0xc00fffffffffffff);
+  status |=
+      test__subdf3(0xc00fffffffffffff, 0x3cb0000000000000, 0xc010000000000000);
+  status |=
+      test__subdf3(0xc00fffffffffffff, 0xc00ffffffffffffe, 0xbcc0000000000000);
+  status |=
+      test__subdf3(0xc00fffffffffffff, 0xc010000000000002, 0x3ce4000000000000);
+  status |=
+      test__subdf3(0xc010000000000001, 0xc00fffffffffffff, 0xbcd8000000000000);
+  status |=
+      test__subdf3(0xffb0000000000001, 0xffafffffffffffff, 0xfc78000000000000);
+  status |=
+      test__subdf3(0xffcfffffffffffff, 0xffcffffffffffffe, 0xfc80000000000000);
+  status |=
+      test__subdf3(0xffcfffffffffffff, 0xffd0000000000002, 0x7ca4000000000000);
+  status |=
+      test__subdf3(0xffd0000000000000, 0xffcfffffffffffff, 0xfc80000000000000);
+  status |=
+      test__subdf3(0xffd0000000000000, 0xffd0000000000001, 0x7c90000000000000);
+  status |=
+      test__subdf3(0xffd0000000000001, 0x7fd0000000000000, 0xffe0000000000000);
+  status |=
+      test__subdf3(0xffd0000000000001, 0xffe0000000000001, 0x7fd0000000000001);
+  status |=
+      test__subdf3(0xffd0000000000002, 0xffc0000000000003, 0xffc0000000000001);
+  status |=
+      test__subdf3(0xffd0000000000004, 0xffd0000000000003, 0xfc90000000000000);
+  status |=
+      test__subdf3(0xffdffffffffffffe, 0x7fdffffffffffffe, 0xffeffffffffffffe);
+  status |=
+      test__subdf3(0xffdffffffffffffe, 0x7fdfffffffffffff, 0xffeffffffffffffe);
+  status |=
+      test__subdf3(0xffdffffffffffffe, 0xffdffffffffffffe, 0x0000000000000000);
+  status |=
+      test__subdf3(0xffdfffffffffffff, 0x3ff0000000000000, 0xffdfffffffffffff);
+  status |=
+      test__subdf3(0xffdfffffffffffff, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xffdfffffffffffff, 0xbff0000000000000, 0xffdfffffffffffff);
+  status |=
+      test__subdf3(0xffdfffffffffffff, 0xffe0000000000000, 0x7c90000000000000);
+  status |=
+      test__subdf3(0xffe0000000000000, 0x0000000000000000, 0xffe0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000000, 0x3ff0000000000000, 0xffe0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000000, 0x8000000000000000, 0xffe0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000000, 0xbff0000000000000, 0xffe0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000001, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000001, 0xffe0000000000000, 0xfca0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000001, 0xffe0000000000002, 0x7ca0000000000000);
+  status |=
+      test__subdf3(0xffe0000000000002, 0xffd0000000000001, 0xffd0000000000003);
+  status |=
+      test__subdf3(0xffeffffffffffffe, 0x3ff0000000000000, 0xffeffffffffffffe);
+  status |=
+      test__subdf3(0xffeffffffffffffe, 0x7feffffffffffffe, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xffeffffffffffffe, 0x7fefffffffffffff, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xffeffffffffffffe, 0xbff0000000000000, 0xffeffffffffffffe);
+  status |=
+      test__subdf3(0xffeffffffffffffe, 0xffefffffffffffff, 0x7ca0000000000000);
+  status |=
+      test__subdf3(0xffefffffffffffff, 0x3ff0000000000000, 0xffefffffffffffff);
+  status |=
+      test__subdf3(0xffefffffffffffff, 0x8000000000000001, 0xffefffffffffffff);
+  status |=
+      test__subdf3(0xffefffffffffffff, 0xbff0000000000000, 0xffefffffffffffff);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |=
+      test__subdf3(0xfff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__subdf3(0x004caed458edc883, 0x004f7fc23eeef153, 0x8016876f30094680);
+  status |=
+      test__subdf3(0x0028000000000000, 0x0010000000000001, 0x001fffffffffffff);
+  status |=
+      test__subdf3(0x0028000000000000, 0x0010000000000000, 0x0020000000000000);
+  status |=
+      test__subdf3(0x001fffffffffffff, 0x0010000000000000, 0x000fffffffffffff);
+  status |=
+      test__subdf3(0x001fffffffffffff, 0x000fffffffffffff, 0x0010000000000000);
+  status |=
+      test__subdf3(0x0020000000000000, 0x0010000000000000, 0x0010000000000000);
+  status |=
+      test__subdf3(0x0038000000000000, 0x0034000000000001, 0x000ffffffffffffc);
+  status |=
+      test__subdf3(0x0038000000000000, 0x0034000000000000, 0x0010000000000000);
+  status |=
+      test__subdf3(0x0038000000000000, 0x0030000000000001, 0x001ffffffffffffc);
+  status |=
+      test__subdf3(0x0038000000000000, 0x0030000000000000, 0x0020000000000000);
+  status |=
+      test__subdf3(0x000fffffffe00000, 0x801000000007ffff, 0x001fffffffe7ffff);
+  status |=
+      test__subdf3(0x0010000000004000, 0x800effffffffffff, 0x001f000000003fff);
+  status |=
+      test__subdf3(0x800000000fffffff, 0x001ffff000000000, 0x801ffff00fffffff);
+  status |=
+      test__subdf3(0x800fffff80000000, 0x001000000fffffff, 0x801fffff8fffffff);
+  status |=
+      test__subdf3(0x80100000001fffff, 0x000ffffeffffffff, 0x801fffff001ffffe);
 
   // Test that the result of an operation is a NaN at all when it should be.
   //
@@ -310,11 +566,16 @@ int main(void) {
   // encoding. We also use the same value as the input NaN in tests that have
   // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
   // because 0x7ff8000000000000 is still the exact expected NaN.
-  status |= test__subdf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
-  status |= test__subdf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
-  status |= test__subdf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
-  status |= test__subdf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
-  status |= test__subdf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__subdf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__subdf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__subdf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
 
 #ifdef ARM_NAN_HANDLING
   // Tests specific to the NaN handling of Arm hardware, mimicked by
@@ -334,58 +595,110 @@ int main(void) {
   //
   //  - invalid operations not involving an input NaN return the quiet
   //    NaN with fewest bits set, 0x7ff8000000000000.
-  status |= test__subdf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
-  status |= test__subdf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
-  status |= test__subdf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
-  status |= test__subdf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
-  status |= test__subdf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
-  status |= test__subdf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
-  status |= test__subdf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
-  status |= test__subdf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
-  status |= test__subdf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
-  status |= test__subdf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
-  status |= test__subdf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
-  status |= test__subdf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
-  status |= test__subdf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
-  status |= test__subdf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
-  status |= test__subdf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
-  status |= test__subdf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
-  status |= test__subdf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
-  status |= test__subdf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
-  status |= test__subdf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
-  status |= test__subdf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
-  status |= test__subdf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
-  status |= test__subdf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
-  status |= test__subdf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
-  status |= test__subdf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
-  status |= test__subdf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
-  status |= test__subdf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
-  status |= test__subdf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
-  status |= test__subdf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
-  status |= test__subdf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
-  status |= test__subdf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
-  status |= test__subdf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
-  status |= test__subdf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
-  status |= test__subdf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
-  status |= test__subdf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
-  status |= test__subdf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
-  status |= test__subdf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
-  status |= test__subdf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
-  status |= test__subdf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
-  status |= test__subdf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
-  status |= test__subdf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
-  status |= test__subdf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
-  status |= test__subdf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
-  status |= test__subdf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
-  status |= test__subdf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
-  status |= test__subdf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
-  status |= test__subdf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
-  status |= test__subdf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
-  status |= test__subdf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
-  status |= test__subdf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
-  status |= test__subdf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
-  status |= test__subdf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
-  status |= test__subdf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+  status |=
+      test__subdf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |=
+      test__subdf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |=
+      test__subdf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |=
+      test__subdf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |=
+      test__subdf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |=
+      test__subdf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |=
+      test__subdf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |=
+      test__subdf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |=
+      test__subdf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |=
+      test__subdf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |=
+      test__subdf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |=
+      test__subdf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |=
+      test__subdf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |=
+      test__subdf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |=
+      test__subdf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |=
+      test__subdf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |=
+      test__subdf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |=
+      test__subdf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |=
+      test__subdf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |=
+      test__subdf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |=
+      test__subdf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |=
+      test__subdf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |=
+      test__subdf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |=
+      test__subdf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |=
+      test__subdf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |=
+      test__subdf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |=
+      test__subdf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |=
+      test__subdf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |=
+      test__subdf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |=
+      test__subdf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |=
+      test__subdf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |=
+      test__subdf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |=
+      test__subdf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |=
+      test__subdf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |=
+      test__subdf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |=
+      test__subdf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |=
+      test__subdf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |=
+      test__subdf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |=
+      test__subdf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |=
+      test__subdf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |=
+      test__subdf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |=
+      test__subdf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |=
+      test__subdf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |=
+      test__subdf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |=
+      test__subdf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |=
+      test__subdf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |=
+      test__subdf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |=
+      test__subdf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |=
+      test__subdf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
 
 #endif // ARM_NAN_HANDLING
 

>From e281d470c8c60f06946623d8171a15dca15c7b73 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:09:29 +0000
Subject: [PATCH 13/33] Update to use set_special_properties

---
 compiler-rt/lib/builtins/CMakeLists.txt | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 47cc090acddda..a5e7ae8e19704 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -508,8 +508,7 @@ set(thumb1_base_SOURCES
   arm/addsf3.S
   ${GENERIC_SOURCES}
 )
-set_property(SOURCE arm/adddf3.S PROPERTY crt_supersedes subdf3.c)
-set_property(SOURCE arm/adddf3.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY crt_provides subdf3)
+set_special_properties(arm/adddf3.S SUPERSEDES subdf3.c PROVIDES subdf3)
 
 if(COMPILER_RT_ARM_OPTIMIZED_FP)
   set(thumb1_base_SOURCES

>From 9b5d3184fbbb66eb2934a02c164f36bc3c2540fe Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:19:47 +0000
Subject: [PATCH 14/33] clang-format

---
 .../test/builtins/Unit/divdf3new_test.c       | 1179 +++++++++++------
 .../test/builtins/Unit/muldf3new_test.c       | 1134 ++++++++++------
 2 files changed, 1540 insertions(+), 773 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/divdf3new_test.c b/compiler-rt/test/builtins/Unit/divdf3new_test.c
index b756acf2dfeb0..ca33e00a8741d 100644
--- a/compiler-rt/test/builtins/Unit/divdf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/divdf3new_test.c
@@ -24,7 +24,8 @@
 // Returns: a / b
 COMPILER_RT_ABI double __divdf3(double a, double b);
 
-int test__divdf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+int test__divdf3(int line, uint64_t a_rep, uint64_t b_rep,
+                 uint64_t expected_rep) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __divdf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -34,345 +35,672 @@ int test__divdf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep
 #endif
 
   if (ret) {
-    printf("error at line %d: __divdf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
-           ", expected %016" PRIx64 "\n",
+    printf("error at line %d: __divdf3(%016" PRIx64 ", %016" PRIx64
+           ") = %016" PRIx64 ", expected %016" PRIx64 "\n",
            line, a_rep, b_rep, toRep64(x), expected_rep);
   }
   return ret;
 }
 
-#define test__divdf3(a,b,x) test__divdf3(__LINE__,a,b,x)
+#define test__divdf3(a, b, x) test__divdf3(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;
 
-  status |= test__divdf3(0x0000000000000000, 0x0000000000000001, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x000fffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x0010000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x001fffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x3ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x4014000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x7fdfffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x7fe0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x8000000000000002, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x800fffffffffffff, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x8010000000000001, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x8020000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0xc008000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0xc01c000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0xffcfffffffffffff, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0xffe0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000000, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000001, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x0000000000000001, 0x3fc0000000000000, 0x0000000000000008);
-  status |= test__divdf3(0x0000000000000001, 0x3fe0000000000000, 0x0000000000000002);
-  status |= test__divdf3(0x0000000000000001, 0x4000000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000001, 0x7fefffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000001, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0000000000000001, 0xc000000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000001, 0xffefffffffffffff, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000002, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x0000000000000002, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0000000000000009, 0x4022000000000000, 0x0000000000000001);
-  status |= test__divdf3(0x0000000000000009, 0xc022000000000000, 0x8000000000000001);
-  status |= test__divdf3(0x000ffffffffffff7, 0x3feffffffffffffe, 0x000ffffffffffff8);
-  status |= test__divdf3(0x000ffffffffffffe, 0x3feffffffffffffe, 0x000fffffffffffff);
-  status |= test__divdf3(0x000fffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x000fffffffffffff, 0x3f60000000000000, 0x009ffffffffffffe);
-  status |= test__divdf3(0x000fffffffffffff, 0x3fe0000000000000, 0x001ffffffffffffe);
-  status |= test__divdf3(0x000fffffffffffff, 0x3ff0000000000000, 0x000fffffffffffff);
-  status |= test__divdf3(0x000fffffffffffff, 0x3ff0000000000002, 0x000ffffffffffffd);
-  status |= test__divdf3(0x000fffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x000fffffffffffff, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x000fffffffffffff, 0xbff0000000000000, 0x800fffffffffffff);
-  status |= test__divdf3(0x000fffffffffffff, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0010000000000000, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x0010000000000000, 0x3ff0000000000001, 0x000fffffffffffff);
-  status |= test__divdf3(0x0010000000000000, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0010000000000001, 0x3ff0000000000002, 0x000fffffffffffff);
-  status |= test__divdf3(0x0010000000000001, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x0010000000000001, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0010000000000002, 0x3ff0000000000006, 0x000ffffffffffffc);
-  status |= test__divdf3(0x001ffffffffffffe, 0x4000000000000000, 0x000fffffffffffff);
-  status |= test__divdf3(0x001fffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x001fffffffffffff, 0x4000000000000000, 0x0010000000000000);
-  status |= test__divdf3(0x001fffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x0020000000000000, 0x0010000000000000, 0x4000000000000000);
-  status |= test__divdf3(0x0020000000000000, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x0020000000000000, 0xc000000000000000, 0x8010000000000000);
-  status |= test__divdf3(0x0020000000000000, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x0020000000000001, 0x0010000000000001, 0x4000000000000000);
-  status |= test__divdf3(0x0020000000000001, 0xc000000000000000, 0x8010000000000001);
-  status |= test__divdf3(0x0020000000000003, 0x8010000000000003, 0xc000000000000000);
-  status |= test__divdf3(0x0020000000000003, 0xc000000000000000, 0x8010000000000003);
-  status |= test__divdf3(0x3feffffffffffff7, 0x3feffffffffffffb, 0x3feffffffffffffc);
-  status |= test__divdf3(0x3feffffffffffff7, 0x3feffffffffffffe, 0x3feffffffffffff9);
-  status |= test__divdf3(0x3feffffffffffff8, 0x3feffffffffffffc, 0x3feffffffffffffc);
-  status |= test__divdf3(0x3feffffffffffff8, 0x3feffffffffffffd, 0x3feffffffffffffb);
-  status |= test__divdf3(0x3feffffffffffffa, 0x3feffffffffffff9, 0x3ff0000000000001);
-  status |= test__divdf3(0x3feffffffffffffb, 0x3feffffffffffff9, 0x3ff0000000000001);
-  status |= test__divdf3(0x3feffffffffffffc, 0x3feffffffffffff9, 0x3ff0000000000002);
-  status |= test__divdf3(0x3feffffffffffffc, 0x3feffffffffffffd, 0x3fefffffffffffff);
-  status |= test__divdf3(0x3feffffffffffffc, 0x3feffffffffffffe, 0x3feffffffffffffe);
-  status |= test__divdf3(0x3feffffffffffffc, 0x3fefffffffffffff, 0x3feffffffffffffd);
-  status |= test__divdf3(0x3feffffffffffffc, 0x3ff0000000000001, 0x3feffffffffffffa);
-  status |= test__divdf3(0x3feffffffffffffd, 0x3feffffffffffff9, 0x3ff0000000000002);
-  status |= test__divdf3(0x3feffffffffffffd, 0x3feffffffffffffc, 0x3ff0000000000001);
-  status |= test__divdf3(0x3feffffffffffffd, 0x3feffffffffffffe, 0x3fefffffffffffff);
-  status |= test__divdf3(0x3feffffffffffffd, 0x3fefffffffffffff, 0x3feffffffffffffe);
-  status |= test__divdf3(0x3feffffffffffffd, 0x3ff0000000000001, 0x3feffffffffffffb);
-  status |= test__divdf3(0x3feffffffffffffd, 0x3ff0000000000002, 0x3feffffffffffff9);
-  status |= test__divdf3(0x3feffffffffffffe, 0x3feffffffffffff9, 0x3ff0000000000003);
-  status |= test__divdf3(0x3feffffffffffffe, 0x3feffffffffffffc, 0x3ff0000000000001);
-  status |= test__divdf3(0x3feffffffffffffe, 0x3feffffffffffffd, 0x3ff0000000000001);
-  status |= test__divdf3(0x3feffffffffffffe, 0x3fefffffffffffff, 0x3fefffffffffffff);
-  status |= test__divdf3(0x3feffffffffffffe, 0x3ff0000000000001, 0x3feffffffffffffc);
-  status |= test__divdf3(0x3feffffffffffffe, 0x3ff0000000000002, 0x3feffffffffffffa);
-  status |= test__divdf3(0x3feffffffffffffe, 0x3ff0000000000003, 0x3feffffffffffff8);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffff9, 0x3ff0000000000003);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffc, 0x3ff0000000000002);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffd, 0x3ff0000000000001);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffe, 0x3ff0000000000001);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000001, 0x3feffffffffffffd);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000002, 0x3feffffffffffffb);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000003, 0x3feffffffffffff9);
-  status |= test__divdf3(0x3fefffffffffffff, 0x3ff0000000000004, 0x3feffffffffffff7);
-  status |= test__divdf3(0x3ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffff7, 0x3ff0000000000005);
-  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffff8, 0x3ff0000000000004);
-  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffb, 0x3ff0000000000003);
-  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffc, 0x3ff0000000000002);
-  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffd, 0x3ff0000000000002);
-  status |= test__divdf3(0x3ff0000000000000, 0x3feffffffffffffe, 0x3ff0000000000001);
-  status |= test__divdf3(0x3ff0000000000000, 0x3fefffffffffffff, 0x3ff0000000000001);
-  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
-  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000001, 0x3feffffffffffffe);
-  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000002, 0x3feffffffffffffc);
-  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000003, 0x3feffffffffffffa);
-  status |= test__divdf3(0x3ff0000000000000, 0x3ff0000000000004, 0x3feffffffffffff8);
-  status |= test__divdf3(0x3ff0000000000000, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x3ff0000000000001, 0x3feffffffffffffb, 0x3ff0000000000004);
-  status |= test__divdf3(0x3ff0000000000001, 0x3feffffffffffffd, 0x3ff0000000000003);
-  status |= test__divdf3(0x3ff0000000000001, 0x3feffffffffffffe, 0x3ff0000000000002);
-  status |= test__divdf3(0x3ff0000000000001, 0x3fefffffffffffff, 0x3ff0000000000002);
-  status |= test__divdf3(0x3ff0000000000001, 0x3ff0000000000002, 0x3feffffffffffffe);
-  status |= test__divdf3(0x3ff0000000000001, 0x3ff0000000000003, 0x3feffffffffffffc);
-  status |= test__divdf3(0x3ff0000000000002, 0x3feffffffffffffc, 0x3ff0000000000004);
-  status |= test__divdf3(0x3ff0000000000002, 0x3feffffffffffffd, 0x3ff0000000000004);
-  status |= test__divdf3(0x3ff0000000000002, 0x3feffffffffffffe, 0x3ff0000000000003);
-  status |= test__divdf3(0x3ff0000000000002, 0x3fefffffffffffff, 0x3ff0000000000003);
-  status |= test__divdf3(0x3ff0000000000002, 0x3ff0000000000001, 0x3ff0000000000001);
-  status |= test__divdf3(0x3ff0000000000002, 0x3ff0000000000003, 0x3feffffffffffffe);
-  status |= test__divdf3(0x3ff0000000000003, 0x3feffffffffffffd, 0x3ff0000000000005);
-  status |= test__divdf3(0x3ff0000000000003, 0x3feffffffffffffe, 0x3ff0000000000004);
-  status |= test__divdf3(0x3ff0000000000003, 0x3fefffffffffffff, 0x3ff0000000000004);
-  status |= test__divdf3(0x3ff0000000000003, 0x3ff0000000000001, 0x3ff0000000000002);
-  status |= test__divdf3(0x3ff0000000000004, 0x3feffffffffffffe, 0x3ff0000000000005);
-  status |= test__divdf3(0x3ff0000000000004, 0x3ff0000000000001, 0x3ff0000000000003);
-  status |= test__divdf3(0x3ff0000000000004, 0x3ff0000000000007, 0x3feffffffffffffa);
-  status |= test__divdf3(0x3ff0000000000005, 0x3fefffffffffffff, 0x3ff0000000000006);
-  status |= test__divdf3(0x3ff0000000000006, 0x3ff0000000000008, 0x3feffffffffffffc);
-  status |= test__divdf3(0x3ff0000000000007, 0x3ff0000000000002, 0x3ff0000000000005);
-  status |= test__divdf3(0x3ff0000000000009, 0x3ff0000000000008, 0x3ff0000000000001);
-  status |= test__divdf3(0x3ff199999999999a, 0x3ff3333333333333, 0x3fed555555555556);
-  status |= test__divdf3(0x4000000000000000, 0x3ff0000000000000, 0x4000000000000000);
-  status |= test__divdf3(0x4000000000000000, 0xbff0000000000000, 0xc000000000000000);
-  status |= test__divdf3(0x4008000000000000, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x4008000000000000, 0xc008000000000000, 0xbff0000000000000);
-  status |= test__divdf3(0x4008000000000000, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x4014000000000000, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x4014000000000000, 0x4014000000000000, 0x3ff0000000000000);
-  status |= test__divdf3(0x4014000000000000, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x401c000000000000, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x401c000000000000, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x4020000000000000, 0x4000000000000000, 0x4010000000000000);
-  status |= test__divdf3(0x4022000000000000, 0x4008000000000000, 0x4008000000000000);
-  status |= test__divdf3(0x7f60000000000000, 0x00a0000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7fcfffffffffffff, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7fdffffffffffffd, 0xc000000000000000, 0xffcffffffffffffd);
-  status |= test__divdf3(0x7fdfffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7fdfffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0x3fe0000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0x4000000000000000, 0x7fd0000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0x7ff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0xbfe0000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0xc000000000000000, 0xffd0000000000000);
-  status |= test__divdf3(0x7fe0000000000000, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x7fe0000000000003, 0xffd0000000000003, 0xc000000000000000);
-  status |= test__divdf3(0x7feffffffffffffd, 0x4010000000000000, 0x7fcffffffffffffd);
-  status |= test__divdf3(0x7feffffffffffffd, 0xc010000000000000, 0xffcffffffffffffd);
-  status |= test__divdf3(0x7fefffffffffffff, 0x0000000000000001, 0x7ff0000000000000);
-  status |= test__divdf3(0x7fefffffffffffff, 0x3fefffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0x7fefffffffffffff, 0x7fcfffffffffffff, 0x4010000000000000);
-  status |= test__divdf3(0x7fefffffffffffff, 0x7fdfffffffffffff, 0x4000000000000000);
-  status |= test__divdf3(0x7fefffffffffffff, 0xc000000000000000, 0xffdfffffffffffff);
-  status |= test__divdf3(0x7fefffffffffffff, 0xffcfffffffffffff, 0xc010000000000000);
-  status |= test__divdf3(0x7fefffffffffffff, 0xfff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x0000000000000001, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x0010000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x001fffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x4014000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x7fdfffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x8000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x8000000000000002, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x8010000000000001, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x8020000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0xc008000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0xc01c000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0xffcfffffffffffff, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0xffefffffffffffff, 0xfff0000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x0000000000000003, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x000fffffffffffff, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x0010000000000001, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x0020000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x4000000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x4018000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x7fcfffffffffffff, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x7fd0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x8000000000000004, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x800fffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x8010000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x801fffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0xc010000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0xc020000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0xffd0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0xffdfffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000000, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000001, 0x3fe0000000000000, 0x8000000000000002);
-  status |= test__divdf3(0x8000000000000001, 0x4000000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000001, 0x7fefffffffffffff, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000001, 0xc000000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000001, 0xffefffffffffffff, 0x0000000000000000);
-  status |= test__divdf3(0x8000000000000003, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x8000000000000003, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8000000000000004, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x8000000000000004, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x800ffffffffffff8, 0x3feffffffffffffe, 0x800ffffffffffff9);
-  status |= test__divdf3(0x800fffffffffffff, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x800fffffffffffff, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x800fffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x800fffffffffffff, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8010000000000000, 0x3ff0000000000001, 0x800fffffffffffff);
-  status |= test__divdf3(0x8010000000000000, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x8010000000000000, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8010000000000001, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x8010000000000001, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x801fffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0x801fffffffffffff, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0x8020000000000000, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0x8020000000000000, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0x8020000000000001, 0x0010000000000001, 0xc000000000000000);
-  status |= test__divdf3(0x8020000000000005, 0x0010000000000005, 0xc000000000000000);
-  status |= test__divdf3(0xbff0000000000000, 0x3ff0000000000000, 0xbff0000000000000);
-  status |= test__divdf3(0xbff0000000000000, 0xbff0000000000000, 0x3ff0000000000000);
-  status |= test__divdf3(0xc000000000000000, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xc000000000000000, 0x3ff0000000000000, 0xc000000000000000);
-  status |= test__divdf3(0xc000000000000000, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0xc000000000000000, 0xbff0000000000000, 0x4000000000000000);
-  status |= test__divdf3(0xc010000000000000, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xc010000000000000, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0xc018000000000000, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xc018000000000000, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0xc018000000000000, 0xc008000000000000, 0x4000000000000000);
-  status |= test__divdf3(0xc01c000000000000, 0x401c000000000000, 0xbff0000000000000);
-  status |= test__divdf3(0xc020000000000000, 0x4000000000000000, 0xc010000000000000);
-  status |= test__divdf3(0xc020000000000000, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xc020000000000000, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0xc022000000000000, 0xc008000000000000, 0x4008000000000000);
-  status |= test__divdf3(0xffcfffffffffffff, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xffcfffffffffffff, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0xffd0000000000000, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xffd0000000000000, 0x7ff0000000000000, 0x8000000000000000);
-  status |= test__divdf3(0xffd0000000000000, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xffd0000000000000, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0xffdfffffffffffff, 0x4000000000000000, 0xffcfffffffffffff);
-  status |= test__divdf3(0xffdfffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xffe0000000000000, 0x3fe0000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xffe0000000000000, 0xbfe0000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xffe0000000000001, 0x7fd0000000000001, 0xc000000000000000);
-  status |= test__divdf3(0xffeffffffffffffd, 0x4010000000000000, 0xffcffffffffffffd);
-  status |= test__divdf3(0xffeffffffffffffd, 0xc010000000000000, 0x7fcffffffffffffd);
-  status |= test__divdf3(0xffefffffffffffff, 0x7fcfffffffffffff, 0xc010000000000000);
-  status |= test__divdf3(0xffefffffffffffff, 0xffcfffffffffffff, 0x4010000000000000);
-  status |= test__divdf3(0xffefffffffffffff, 0xfff0000000000000, 0x0000000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x0000000000000003, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x0010000000000001, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x0020000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x4000000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x4018000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x7fd0000000000000, 0xfff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x8000000000000004, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x8010000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x801fffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0xc010000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0xc020000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0xffd0000000000000, 0x7ff0000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0xffefffffffffffff, 0x7ff0000000000000);
-  status |= test__divdf3(0x800ffffffdffffff, 0xc00fff8000000000, 0x0004000fffbfff00);
-  status |= test__divdf3(0xb7fbffffffffffff, 0xffe0000000000007, 0x0000000000000000);
-  status |= test__divdf3(0x3ff660beb3029ffd, 0x3ff52e22fb7ace43, 0x3ff0e79e59ccb735);
-  status |= test__divdf3(0x3ff73ddbc621eb00, 0x3ffb8224c030d747, 0x3feb095d4073d13b);
-  status |= test__divdf3(0x3ff9a3b1ff2bf973, 0x3ff42fdf35d2d3bd, 0x3ff452508f203fca);
-  status |= test__divdf3(0x3ffa2f42f2a01655, 0x3ff01310ba9f33d1, 0x3ffa103474220298);
-  status |= test__divdf3(0x3ffa6b3e65d68478, 0x3ff773ca580800a9, 0x3ff206204bf651cc);
-  status |= test__divdf3(0x3ffae840ed05aaad, 0x3ff374c8afa6bd73, 0x3ff620a0b38357dd);
-  status |= test__divdf3(0x3ffc9bff90e124f7, 0x3ff19678d03f31b9, 0x3ffa06ce5731c244);
-  status |= test__divdf3(0x3ff716518068f63e, 0x3ffea080001fffff, 0x3fe81f4927e2f813);
-  status |= test__divdf3(0x3ff30b70c9e177b3, 0x3ffdc1dbcddeaaf7, 0x3fe47ae453d79b63);
-  status |= test__divdf3(0x3ff690a0c1cf289e, 0x3ffdd0e4ec596ead, 0x3fe837c35c721292);
-  status |= test__divdf3(0x3ff9a9f18698d1c5, 0x3ffdcf214b672807, 0x3feb8cd196d1e2db);
-  status |= test__divdf3(0x3ffc412def95e9f2, 0x3ffe09fd73e44afb, 0x3fee195e4c411819);
-  status |= test__divdf3(0x3ffab674f26df917, 0x3ffe55a80dfd623d, 0x3fec2de561fb628a);
-  status |= test__divdf3(0x3ff15bb10851a33b, 0x3ffe770229894d4f, 0x3fe23b9bdf3ad4d7);
-  status |= test__divdf3(0x3ff6ce035de00c24, 0x3fff04076d288c95, 0x3fe7874738e5ef5e);
-  status |= test__divdf3(0x3ffb0e73f83fd2b4, 0x3fff01150ca4f6e3, 0x3febece97e64ff65);
-  status |= test__divdf3(0x3ff53fff6c6d7043, 0x3fffb55c0bf15be1, 0x3fe57204f8441410);
-  status |= test__divdf3(0x3ffa8aa3bbff7c4b, 0x3fffd530fa74cc5f, 0x3feaae55281a47cf);
-  status |= test__divdf3(0x3ff3004b0d901379, 0x3ffe470662686931, 0x3fe41508eef9d818);
-  status |= test__divdf3(0x3ffac10f29e80b25, 0x3ffe2fba9d423c9d, 0x3fec5c8a8148eb26);
-  status |= test__divdf3(0x3ff8a3e14fe0651f, 0x3ffdeeae50e07679, 0x3fea579ce7a3f61c);
-  status |= test__divdf3(0x3ff168321760dd0d, 0x3ffd382a2b3c2c27, 0x3fe31042c5fcbe35);
-  status |= test__divdf3(0x3ff208350f930e99, 0x3ffc80beeab6d9ed, 0x3fe43e9486314a0e);
-  status |= test__divdf3(0x3ff46a9470b46af6, 0x3ffc2e13c9335b3f, 0x3fe72f150e86f5a1);
-  status |= test__divdf3(0x3ffaf26f45d21562, 0x3ffbe6d631b290e7, 0x3feee7b30b353e95);
-  status |= test__divdf3(0x3ff5cda6f52381df, 0x3ffbe2a5bce4483f, 0x3fe90542a0e62c21);
-  status |= test__divdf3(0x3ff92aeb8209bb69, 0x3ffb57a0bdf7af6f, 0x3fed74754022b839);
-  status |= test__divdf3(0x3ff627c9c1a1903d, 0x3ffb3c161457a7e1, 0x3fea082feee891f0);
-  status |= test__divdf3(0x3ffa5fef91208fd5, 0x3ff68928392cf5e7, 0x3ff2b9c16cd0a6eb);
-  status |= test__divdf3(0x3ffdc6825d6a2ad2, 0x3ff69bb9ca89cd3f, 0x3ff5127c1399515f);
-  status |= test__divdf3(0x3ffd62dbb1150699, 0x3ff6e12d3daf7823, 0x3ff48cd52e787bc5);
-  status |= test__divdf3(0x3ffb9f0e3f946dd2, 0x3ff75a51f01f688b, 0x3ff2ecadebdfdf91);
-  status |= test__divdf3(0x3ffdf21fc13ef609, 0x3ff77a80c8098ae1, 0x3ff46843217c9c90);
-  status |= test__divdf3(0x3ff83f6d28924d31, 0x3ff7cb607bcc758f, 0x3ff04e08e26c84b7);
-  status |= test__divdf3(0x3ffef8774307cea5, 0x3ff849124d13461d, 0x3ff467851369d61a);
-  status |= test__divdf3(0x3ffd7c2259068fa2, 0x3ffa9e9faf8d6845, 0x3ff1b8e24ddeb546);
-  status |= test__divdf3(0x3fffb10b35d3977b, 0x3ffb57a0bdf7af6f, 0x3ff28b8abfdd47c7);
-  status |= test__divdf3(0x3ffdcfa4097387f1, 0x3ffbe6d631b290e7, 0x3ff1184cf4cac16b);
-  status |= test__divdf3(0x3ffcb6231a615d02, 0x3ffb98faef6f9417, 0x3ff0a552a67a8e2d);
-  status |= test__divdf3(0x3ffba5443a5d0a42, 0x3ffb3a5c10922a9d, 0x3ff03ed2622d2a26);
-  status |= test__divdf3(0x3fff3144ae86b33e, 0x3ffa58948417f235, 0x3ff2f17912d557f2);
-  status |= test__divdf3(0x3ffd68635bf6605a, 0x3ff945fce3a79f3f, 0x3ff29e0c7d6617a1);
-  status |= test__divdf3(0x3ff97e6030354676, 0x3ff906f78f460697, 0x3ff04c56a5f3136d);
-  status |= test__divdf3(0x3ffe86f743594e95, 0x3ff8444d7946422d, 0x3ff420b1e63f512e);
-  status |= test__divdf3(0x3fff12a6c5539a9a, 0x3ff7cad48079af09, 0x3ff4e564f736b864);
-  status |= test__divdf3(0x3ffa5371fe989251, 0x3ff6fc5272dc36d1, 0x3ff2533d7a4d0ee8);
-  status |= test__divdf3(0x3ffe18c0547f65d2, 0x3ff6fc9e8dd915ed, 0x3ff4f2e7f917b80e);
-  status |= test__divdf3(0x3ffd7aea8a297055, 0x3ff64eb95d608cd9, 0x3ff52500dc28664c);
+  status |=
+      test__divdf3(0x0000000000000000, 0x0000000000000001, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x000fffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x001fffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x3ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x4014000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x7fdfffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x7fe0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x8000000000000002, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x800fffffffffffff, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x8010000000000001, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x8020000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0xc008000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0xc01c000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0xffcfffffffffffff, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0xffe0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000001, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x0000000000000001, 0x3fc0000000000000, 0x0000000000000008);
+  status |=
+      test__divdf3(0x0000000000000001, 0x3fe0000000000000, 0x0000000000000002);
+  status |=
+      test__divdf3(0x0000000000000001, 0x4000000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000001, 0x7fefffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000001, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0000000000000001, 0xc000000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000001, 0xffefffffffffffff, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000002, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x0000000000000002, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0000000000000009, 0x4022000000000000, 0x0000000000000001);
+  status |=
+      test__divdf3(0x0000000000000009, 0xc022000000000000, 0x8000000000000001);
+  status |=
+      test__divdf3(0x000ffffffffffff7, 0x3feffffffffffffe, 0x000ffffffffffff8);
+  status |=
+      test__divdf3(0x000ffffffffffffe, 0x3feffffffffffffe, 0x000fffffffffffff);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x3f60000000000000, 0x009ffffffffffffe);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x3fe0000000000000, 0x001ffffffffffffe);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x3ff0000000000000, 0x000fffffffffffff);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x3ff0000000000002, 0x000ffffffffffffd);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0xbff0000000000000, 0x800fffffffffffff);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0010000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x0010000000000000, 0x3ff0000000000001, 0x000fffffffffffff);
+  status |=
+      test__divdf3(0x0010000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0010000000000001, 0x3ff0000000000002, 0x000fffffffffffff);
+  status |=
+      test__divdf3(0x0010000000000001, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x0010000000000001, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0010000000000002, 0x3ff0000000000006, 0x000ffffffffffffc);
+  status |=
+      test__divdf3(0x001ffffffffffffe, 0x4000000000000000, 0x000fffffffffffff);
+  status |=
+      test__divdf3(0x001fffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x001fffffffffffff, 0x4000000000000000, 0x0010000000000000);
+  status |=
+      test__divdf3(0x001fffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x0020000000000000, 0x0010000000000000, 0x4000000000000000);
+  status |=
+      test__divdf3(0x0020000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x0020000000000000, 0xc000000000000000, 0x8010000000000000);
+  status |=
+      test__divdf3(0x0020000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x0020000000000001, 0x0010000000000001, 0x4000000000000000);
+  status |=
+      test__divdf3(0x0020000000000001, 0xc000000000000000, 0x8010000000000001);
+  status |=
+      test__divdf3(0x0020000000000003, 0x8010000000000003, 0xc000000000000000);
+  status |=
+      test__divdf3(0x0020000000000003, 0xc000000000000000, 0x8010000000000003);
+  status |=
+      test__divdf3(0x3feffffffffffff7, 0x3feffffffffffffb, 0x3feffffffffffffc);
+  status |=
+      test__divdf3(0x3feffffffffffff7, 0x3feffffffffffffe, 0x3feffffffffffff9);
+  status |=
+      test__divdf3(0x3feffffffffffff8, 0x3feffffffffffffc, 0x3feffffffffffffc);
+  status |=
+      test__divdf3(0x3feffffffffffff8, 0x3feffffffffffffd, 0x3feffffffffffffb);
+  status |=
+      test__divdf3(0x3feffffffffffffa, 0x3feffffffffffff9, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3feffffffffffffb, 0x3feffffffffffff9, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3feffffffffffffc, 0x3feffffffffffff9, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3feffffffffffffc, 0x3feffffffffffffd, 0x3fefffffffffffff);
+  status |=
+      test__divdf3(0x3feffffffffffffc, 0x3feffffffffffffe, 0x3feffffffffffffe);
+  status |=
+      test__divdf3(0x3feffffffffffffc, 0x3fefffffffffffff, 0x3feffffffffffffd);
+  status |=
+      test__divdf3(0x3feffffffffffffc, 0x3ff0000000000001, 0x3feffffffffffffa);
+  status |=
+      test__divdf3(0x3feffffffffffffd, 0x3feffffffffffff9, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3feffffffffffffd, 0x3feffffffffffffc, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3feffffffffffffd, 0x3feffffffffffffe, 0x3fefffffffffffff);
+  status |=
+      test__divdf3(0x3feffffffffffffd, 0x3fefffffffffffff, 0x3feffffffffffffe);
+  status |=
+      test__divdf3(0x3feffffffffffffd, 0x3ff0000000000001, 0x3feffffffffffffb);
+  status |=
+      test__divdf3(0x3feffffffffffffd, 0x3ff0000000000002, 0x3feffffffffffff9);
+  status |=
+      test__divdf3(0x3feffffffffffffe, 0x3feffffffffffff9, 0x3ff0000000000003);
+  status |=
+      test__divdf3(0x3feffffffffffffe, 0x3feffffffffffffc, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3feffffffffffffe, 0x3feffffffffffffd, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3feffffffffffffe, 0x3fefffffffffffff, 0x3fefffffffffffff);
+  status |=
+      test__divdf3(0x3feffffffffffffe, 0x3ff0000000000001, 0x3feffffffffffffc);
+  status |=
+      test__divdf3(0x3feffffffffffffe, 0x3ff0000000000002, 0x3feffffffffffffa);
+  status |=
+      test__divdf3(0x3feffffffffffffe, 0x3ff0000000000003, 0x3feffffffffffff8);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3feffffffffffff9, 0x3ff0000000000003);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffc, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffd, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3feffffffffffffe, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3ff0000000000001, 0x3feffffffffffffd);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3ff0000000000002, 0x3feffffffffffffb);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3ff0000000000003, 0x3feffffffffffff9);
+  status |=
+      test__divdf3(0x3fefffffffffffff, 0x3ff0000000000004, 0x3feffffffffffff7);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3feffffffffffff7, 0x3ff0000000000005);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3feffffffffffff8, 0x3ff0000000000004);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3feffffffffffffb, 0x3ff0000000000003);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3feffffffffffffc, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3feffffffffffffd, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3feffffffffffffe, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3fefffffffffffff, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3ff0000000000001, 0x3feffffffffffffe);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3ff0000000000002, 0x3feffffffffffffc);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3ff0000000000003, 0x3feffffffffffffa);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x3ff0000000000004, 0x3feffffffffffff8);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x3ff0000000000001, 0x3feffffffffffffb, 0x3ff0000000000004);
+  status |=
+      test__divdf3(0x3ff0000000000001, 0x3feffffffffffffd, 0x3ff0000000000003);
+  status |=
+      test__divdf3(0x3ff0000000000001, 0x3feffffffffffffe, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3ff0000000000001, 0x3fefffffffffffff, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3ff0000000000001, 0x3ff0000000000002, 0x3feffffffffffffe);
+  status |=
+      test__divdf3(0x3ff0000000000001, 0x3ff0000000000003, 0x3feffffffffffffc);
+  status |=
+      test__divdf3(0x3ff0000000000002, 0x3feffffffffffffc, 0x3ff0000000000004);
+  status |=
+      test__divdf3(0x3ff0000000000002, 0x3feffffffffffffd, 0x3ff0000000000004);
+  status |=
+      test__divdf3(0x3ff0000000000002, 0x3feffffffffffffe, 0x3ff0000000000003);
+  status |=
+      test__divdf3(0x3ff0000000000002, 0x3fefffffffffffff, 0x3ff0000000000003);
+  status |=
+      test__divdf3(0x3ff0000000000002, 0x3ff0000000000001, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3ff0000000000002, 0x3ff0000000000003, 0x3feffffffffffffe);
+  status |=
+      test__divdf3(0x3ff0000000000003, 0x3feffffffffffffd, 0x3ff0000000000005);
+  status |=
+      test__divdf3(0x3ff0000000000003, 0x3feffffffffffffe, 0x3ff0000000000004);
+  status |=
+      test__divdf3(0x3ff0000000000003, 0x3fefffffffffffff, 0x3ff0000000000004);
+  status |=
+      test__divdf3(0x3ff0000000000003, 0x3ff0000000000001, 0x3ff0000000000002);
+  status |=
+      test__divdf3(0x3ff0000000000004, 0x3feffffffffffffe, 0x3ff0000000000005);
+  status |=
+      test__divdf3(0x3ff0000000000004, 0x3ff0000000000001, 0x3ff0000000000003);
+  status |=
+      test__divdf3(0x3ff0000000000004, 0x3ff0000000000007, 0x3feffffffffffffa);
+  status |=
+      test__divdf3(0x3ff0000000000005, 0x3fefffffffffffff, 0x3ff0000000000006);
+  status |=
+      test__divdf3(0x3ff0000000000006, 0x3ff0000000000008, 0x3feffffffffffffc);
+  status |=
+      test__divdf3(0x3ff0000000000007, 0x3ff0000000000002, 0x3ff0000000000005);
+  status |=
+      test__divdf3(0x3ff0000000000009, 0x3ff0000000000008, 0x3ff0000000000001);
+  status |=
+      test__divdf3(0x3ff199999999999a, 0x3ff3333333333333, 0x3fed555555555556);
+  status |=
+      test__divdf3(0x4000000000000000, 0x3ff0000000000000, 0x4000000000000000);
+  status |=
+      test__divdf3(0x4000000000000000, 0xbff0000000000000, 0xc000000000000000);
+  status |=
+      test__divdf3(0x4008000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x4008000000000000, 0xc008000000000000, 0xbff0000000000000);
+  status |=
+      test__divdf3(0x4008000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x4014000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x4014000000000000, 0x4014000000000000, 0x3ff0000000000000);
+  status |=
+      test__divdf3(0x4014000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x401c000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x401c000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x4020000000000000, 0x4000000000000000, 0x4010000000000000);
+  status |=
+      test__divdf3(0x4022000000000000, 0x4008000000000000, 0x4008000000000000);
+  status |=
+      test__divdf3(0x7f60000000000000, 0x00a0000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7fcfffffffffffff, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7fdffffffffffffd, 0xc000000000000000, 0xffcffffffffffffd);
+  status |=
+      test__divdf3(0x7fdfffffffffffff, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7fdfffffffffffff, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0x3fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0x4000000000000000, 0x7fd0000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0x7ff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0xbfe0000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0xc000000000000000, 0xffd0000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000000, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x7fe0000000000003, 0xffd0000000000003, 0xc000000000000000);
+  status |=
+      test__divdf3(0x7feffffffffffffd, 0x4010000000000000, 0x7fcffffffffffffd);
+  status |=
+      test__divdf3(0x7feffffffffffffd, 0xc010000000000000, 0xffcffffffffffffd);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0x0000000000000001, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0x3fefffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0x7fcfffffffffffff, 0x4010000000000000);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0x7fdfffffffffffff, 0x4000000000000000);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0xc000000000000000, 0xffdfffffffffffff);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0xffcfffffffffffff, 0xc010000000000000);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0xfff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x0000000000000001, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x0010000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x001fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x4014000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x7fdfffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x8000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x8000000000000002, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x8010000000000001, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x8020000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0xc008000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0xc01c000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0xffcfffffffffffff, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0xffefffffffffffff, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x0000000000000003, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x000fffffffffffff, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x0010000000000001, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x0020000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x4000000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x4018000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x7fcfffffffffffff, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x7fd0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x8000000000000004, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x800fffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x801fffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0xc010000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0xc020000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0xffd0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0xffdfffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000001, 0x3fe0000000000000, 0x8000000000000002);
+  status |=
+      test__divdf3(0x8000000000000001, 0x4000000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000001, 0x7fefffffffffffff, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000001, 0xc000000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000001, 0xffefffffffffffff, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8000000000000003, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x8000000000000003, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8000000000000004, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x8000000000000004, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x800ffffffffffff8, 0x3feffffffffffffe, 0x800ffffffffffff9);
+  status |=
+      test__divdf3(0x800fffffffffffff, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x800fffffffffffff, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x800fffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x800fffffffffffff, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8010000000000000, 0x3ff0000000000001, 0x800fffffffffffff);
+  status |=
+      test__divdf3(0x8010000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x8010000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8010000000000001, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x8010000000000001, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x801fffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x801fffffffffffff, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0x8020000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0x8020000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0x8020000000000001, 0x0010000000000001, 0xc000000000000000);
+  status |=
+      test__divdf3(0x8020000000000005, 0x0010000000000005, 0xc000000000000000);
+  status |=
+      test__divdf3(0xbff0000000000000, 0x3ff0000000000000, 0xbff0000000000000);
+  status |=
+      test__divdf3(0xbff0000000000000, 0xbff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__divdf3(0xc000000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xc000000000000000, 0x3ff0000000000000, 0xc000000000000000);
+  status |=
+      test__divdf3(0xc000000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0xc000000000000000, 0xbff0000000000000, 0x4000000000000000);
+  status |=
+      test__divdf3(0xc010000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xc010000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0xc018000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xc018000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0xc018000000000000, 0xc008000000000000, 0x4000000000000000);
+  status |=
+      test__divdf3(0xc01c000000000000, 0x401c000000000000, 0xbff0000000000000);
+  status |=
+      test__divdf3(0xc020000000000000, 0x4000000000000000, 0xc010000000000000);
+  status |=
+      test__divdf3(0xc020000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xc020000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0xc022000000000000, 0xc008000000000000, 0x4008000000000000);
+  status |=
+      test__divdf3(0xffcfffffffffffff, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xffcfffffffffffff, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0xffd0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xffd0000000000000, 0x7ff0000000000000, 0x8000000000000000);
+  status |=
+      test__divdf3(0xffd0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xffd0000000000000, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0xffdfffffffffffff, 0x4000000000000000, 0xffcfffffffffffff);
+  status |=
+      test__divdf3(0xffdfffffffffffff, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xffe0000000000000, 0x3fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xffe0000000000000, 0xbfe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xffe0000000000001, 0x7fd0000000000001, 0xc000000000000000);
+  status |=
+      test__divdf3(0xffeffffffffffffd, 0x4010000000000000, 0xffcffffffffffffd);
+  status |=
+      test__divdf3(0xffeffffffffffffd, 0xc010000000000000, 0x7fcffffffffffffd);
+  status |=
+      test__divdf3(0xffefffffffffffff, 0x7fcfffffffffffff, 0xc010000000000000);
+  status |=
+      test__divdf3(0xffefffffffffffff, 0xffcfffffffffffff, 0x4010000000000000);
+  status |=
+      test__divdf3(0xffefffffffffffff, 0xfff0000000000000, 0x0000000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x0000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x0000000000000003, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x000fffffffffffff, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x0010000000000001, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x0020000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x4000000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x4018000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x7fd0000000000000, 0xfff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x8000000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x8000000000000004, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x800fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x8010000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x801fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0xc010000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0xc020000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0xffd0000000000000, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0xffefffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__divdf3(0x800ffffffdffffff, 0xc00fff8000000000, 0x0004000fffbfff00);
+  status |=
+      test__divdf3(0xb7fbffffffffffff, 0xffe0000000000007, 0x0000000000000000);
+  status |=
+      test__divdf3(0x3ff660beb3029ffd, 0x3ff52e22fb7ace43, 0x3ff0e79e59ccb735);
+  status |=
+      test__divdf3(0x3ff73ddbc621eb00, 0x3ffb8224c030d747, 0x3feb095d4073d13b);
+  status |=
+      test__divdf3(0x3ff9a3b1ff2bf973, 0x3ff42fdf35d2d3bd, 0x3ff452508f203fca);
+  status |=
+      test__divdf3(0x3ffa2f42f2a01655, 0x3ff01310ba9f33d1, 0x3ffa103474220298);
+  status |=
+      test__divdf3(0x3ffa6b3e65d68478, 0x3ff773ca580800a9, 0x3ff206204bf651cc);
+  status |=
+      test__divdf3(0x3ffae840ed05aaad, 0x3ff374c8afa6bd73, 0x3ff620a0b38357dd);
+  status |=
+      test__divdf3(0x3ffc9bff90e124f7, 0x3ff19678d03f31b9, 0x3ffa06ce5731c244);
+  status |=
+      test__divdf3(0x3ff716518068f63e, 0x3ffea080001fffff, 0x3fe81f4927e2f813);
+  status |=
+      test__divdf3(0x3ff30b70c9e177b3, 0x3ffdc1dbcddeaaf7, 0x3fe47ae453d79b63);
+  status |=
+      test__divdf3(0x3ff690a0c1cf289e, 0x3ffdd0e4ec596ead, 0x3fe837c35c721292);
+  status |=
+      test__divdf3(0x3ff9a9f18698d1c5, 0x3ffdcf214b672807, 0x3feb8cd196d1e2db);
+  status |=
+      test__divdf3(0x3ffc412def95e9f2, 0x3ffe09fd73e44afb, 0x3fee195e4c411819);
+  status |=
+      test__divdf3(0x3ffab674f26df917, 0x3ffe55a80dfd623d, 0x3fec2de561fb628a);
+  status |=
+      test__divdf3(0x3ff15bb10851a33b, 0x3ffe770229894d4f, 0x3fe23b9bdf3ad4d7);
+  status |=
+      test__divdf3(0x3ff6ce035de00c24, 0x3fff04076d288c95, 0x3fe7874738e5ef5e);
+  status |=
+      test__divdf3(0x3ffb0e73f83fd2b4, 0x3fff01150ca4f6e3, 0x3febece97e64ff65);
+  status |=
+      test__divdf3(0x3ff53fff6c6d7043, 0x3fffb55c0bf15be1, 0x3fe57204f8441410);
+  status |=
+      test__divdf3(0x3ffa8aa3bbff7c4b, 0x3fffd530fa74cc5f, 0x3feaae55281a47cf);
+  status |=
+      test__divdf3(0x3ff3004b0d901379, 0x3ffe470662686931, 0x3fe41508eef9d818);
+  status |=
+      test__divdf3(0x3ffac10f29e80b25, 0x3ffe2fba9d423c9d, 0x3fec5c8a8148eb26);
+  status |=
+      test__divdf3(0x3ff8a3e14fe0651f, 0x3ffdeeae50e07679, 0x3fea579ce7a3f61c);
+  status |=
+      test__divdf3(0x3ff168321760dd0d, 0x3ffd382a2b3c2c27, 0x3fe31042c5fcbe35);
+  status |=
+      test__divdf3(0x3ff208350f930e99, 0x3ffc80beeab6d9ed, 0x3fe43e9486314a0e);
+  status |=
+      test__divdf3(0x3ff46a9470b46af6, 0x3ffc2e13c9335b3f, 0x3fe72f150e86f5a1);
+  status |=
+      test__divdf3(0x3ffaf26f45d21562, 0x3ffbe6d631b290e7, 0x3feee7b30b353e95);
+  status |=
+      test__divdf3(0x3ff5cda6f52381df, 0x3ffbe2a5bce4483f, 0x3fe90542a0e62c21);
+  status |=
+      test__divdf3(0x3ff92aeb8209bb69, 0x3ffb57a0bdf7af6f, 0x3fed74754022b839);
+  status |=
+      test__divdf3(0x3ff627c9c1a1903d, 0x3ffb3c161457a7e1, 0x3fea082feee891f0);
+  status |=
+      test__divdf3(0x3ffa5fef91208fd5, 0x3ff68928392cf5e7, 0x3ff2b9c16cd0a6eb);
+  status |=
+      test__divdf3(0x3ffdc6825d6a2ad2, 0x3ff69bb9ca89cd3f, 0x3ff5127c1399515f);
+  status |=
+      test__divdf3(0x3ffd62dbb1150699, 0x3ff6e12d3daf7823, 0x3ff48cd52e787bc5);
+  status |=
+      test__divdf3(0x3ffb9f0e3f946dd2, 0x3ff75a51f01f688b, 0x3ff2ecadebdfdf91);
+  status |=
+      test__divdf3(0x3ffdf21fc13ef609, 0x3ff77a80c8098ae1, 0x3ff46843217c9c90);
+  status |=
+      test__divdf3(0x3ff83f6d28924d31, 0x3ff7cb607bcc758f, 0x3ff04e08e26c84b7);
+  status |=
+      test__divdf3(0x3ffef8774307cea5, 0x3ff849124d13461d, 0x3ff467851369d61a);
+  status |=
+      test__divdf3(0x3ffd7c2259068fa2, 0x3ffa9e9faf8d6845, 0x3ff1b8e24ddeb546);
+  status |=
+      test__divdf3(0x3fffb10b35d3977b, 0x3ffb57a0bdf7af6f, 0x3ff28b8abfdd47c7);
+  status |=
+      test__divdf3(0x3ffdcfa4097387f1, 0x3ffbe6d631b290e7, 0x3ff1184cf4cac16b);
+  status |=
+      test__divdf3(0x3ffcb6231a615d02, 0x3ffb98faef6f9417, 0x3ff0a552a67a8e2d);
+  status |=
+      test__divdf3(0x3ffba5443a5d0a42, 0x3ffb3a5c10922a9d, 0x3ff03ed2622d2a26);
+  status |=
+      test__divdf3(0x3fff3144ae86b33e, 0x3ffa58948417f235, 0x3ff2f17912d557f2);
+  status |=
+      test__divdf3(0x3ffd68635bf6605a, 0x3ff945fce3a79f3f, 0x3ff29e0c7d6617a1);
+  status |=
+      test__divdf3(0x3ff97e6030354676, 0x3ff906f78f460697, 0x3ff04c56a5f3136d);
+  status |=
+      test__divdf3(0x3ffe86f743594e95, 0x3ff8444d7946422d, 0x3ff420b1e63f512e);
+  status |=
+      test__divdf3(0x3fff12a6c5539a9a, 0x3ff7cad48079af09, 0x3ff4e564f736b864);
+  status |=
+      test__divdf3(0x3ffa5371fe989251, 0x3ff6fc5272dc36d1, 0x3ff2533d7a4d0ee8);
+  status |=
+      test__divdf3(0x3ffe18c0547f65d2, 0x3ff6fc9e8dd915ed, 0x3ff4f2e7f917b80e);
+  status |=
+      test__divdf3(0x3ffd7aea8a297055, 0x3ff64eb95d608cd9, 0x3ff52500dc28664c);
 
   // Test that the result of an operation is a NaN at all when it should be.
   //
@@ -382,17 +710,28 @@ int main(void) {
   // encoding. We also use the same value as the input NaN in tests that have
   // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
   // because 0x7ff8000000000000 is still the exact expected NaN.
-  status |= test__divdf3(0x0000000000000000, 0x0000000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x0000000000000000, 0x8000000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x0000000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x8000000000000000, 0x8000000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
-  status |= test__divdf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x0000000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x0000000000000000, 0x8000000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x0000000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x8000000000000000, 0x8000000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__divdf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
 
 #ifdef ARM_NAN_HANDLING
   // Tests specific to the NaN handling of Arm hardware, mimicked by
@@ -412,58 +751,110 @@ int main(void) {
   //
   //  - invalid operations not involving an input NaN return the quiet
   //    NaN with fewest bits set, 0x7ff8000000000000.
-  status |= test__divdf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
-  status |= test__divdf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
-  status |= test__divdf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
-  status |= test__divdf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
-  status |= test__divdf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
-  status |= test__divdf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
-  status |= test__divdf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
-  status |= test__divdf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
-  status |= test__divdf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
-  status |= test__divdf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
-  status |= test__divdf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
-  status |= test__divdf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
-  status |= test__divdf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
-  status |= test__divdf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
-  status |= test__divdf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
-  status |= test__divdf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
-  status |= test__divdf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
-  status |= test__divdf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
-  status |= test__divdf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
-  status |= test__divdf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
-  status |= test__divdf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
-  status |= test__divdf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
-  status |= test__divdf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
-  status |= test__divdf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
-  status |= test__divdf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
-  status |= test__divdf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
-  status |= test__divdf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
-  status |= test__divdf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
-  status |= test__divdf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
-  status |= test__divdf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
-  status |= test__divdf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
-  status |= test__divdf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
-  status |= test__divdf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
-  status |= test__divdf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
-  status |= test__divdf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
-  status |= test__divdf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
-  status |= test__divdf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
-  status |= test__divdf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
-  status |= test__divdf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
-  status |= test__divdf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
-  status |= test__divdf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
-  status |= test__divdf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
-  status |= test__divdf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
-  status |= test__divdf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
-  status |= test__divdf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
-  status |= test__divdf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
-  status |= test__divdf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
-  status |= test__divdf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
-  status |= test__divdf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
-  status |= test__divdf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
-  status |= test__divdf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
-  status |= test__divdf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+  status |=
+      test__divdf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |=
+      test__divdf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |=
+      test__divdf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |=
+      test__divdf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |=
+      test__divdf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |=
+      test__divdf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |=
+      test__divdf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |=
+      test__divdf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |=
+      test__divdf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |=
+      test__divdf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |=
+      test__divdf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |=
+      test__divdf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |=
+      test__divdf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |=
+      test__divdf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |=
+      test__divdf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |=
+      test__divdf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |=
+      test__divdf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |=
+      test__divdf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |=
+      test__divdf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |=
+      test__divdf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |=
+      test__divdf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |=
+      test__divdf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |=
+      test__divdf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |=
+      test__divdf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |=
+      test__divdf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |=
+      test__divdf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |=
+      test__divdf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |=
+      test__divdf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |=
+      test__divdf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |=
+      test__divdf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |=
+      test__divdf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |=
+      test__divdf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |=
+      test__divdf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |=
+      test__divdf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |=
+      test__divdf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |=
+      test__divdf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |=
+      test__divdf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |=
+      test__divdf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |=
+      test__divdf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |=
+      test__divdf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |=
+      test__divdf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |=
+      test__divdf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |=
+      test__divdf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |=
+      test__divdf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |=
+      test__divdf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |=
+      test__divdf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |=
+      test__divdf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
 
 #endif // ARM_NAN_HANDLING
 
diff --git a/compiler-rt/test/builtins/Unit/muldf3new_test.c b/compiler-rt/test/builtins/Unit/muldf3new_test.c
index 809f40a95b95a..c2e39254fbc46 100644
--- a/compiler-rt/test/builtins/Unit/muldf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/muldf3new_test.c
@@ -24,7 +24,8 @@
 // Returns: a * b
 COMPILER_RT_ABI double __muldf3(double a, double b);
 
-int test__muldf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep) {
+int test__muldf3(int line, uint64_t a_rep, uint64_t b_rep,
+                 uint64_t expected_rep) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __muldf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -34,334 +35,650 @@ int test__muldf3(int line, uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep
 #endif
 
   if (ret) {
-    printf("error at line %d: __muldf3(%016" PRIx64 ", %016" PRIx64 ") = %016" PRIx64
-           ", expected %016" PRIx64 "\n",
+    printf("error at line %d: __muldf3(%016" PRIx64 ", %016" PRIx64
+           ") = %016" PRIx64 ", expected %016" PRIx64 "\n",
            line, a_rep, b_rep, toRep64(x), expected_rep);
   }
   return ret;
 }
 
-#define test__muldf3(a,b,x) test__muldf3(__LINE__,a,b,x)
+#define test__muldf3(a, b, x) test__muldf3(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;
 
-  status |= test__muldf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x000fffffffffffff, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x001fffffffffffff, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x3ff0000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x7fdfffffffffffff, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x8000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x8000000000000002, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x800fffffffffffff, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x8010000000000001, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0x8020000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0xc008000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0xffcfffffffffffff, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0xffe0000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000000, 0xffefffffffffffff, 0x8000000000000000);
-  status |= test__muldf3(0x0000000000000001, 0x0000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000001, 0x3fe0000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x0000000000000001, 0x3fefffffffffffff, 0x0000000000000001);
-  status |= test__muldf3(0x0000000000000001, 0x3ff0000000000000, 0x0000000000000001);
-  status |= test__muldf3(0x0000000000000001, 0x4000000000000000, 0x0000000000000002);
-  status |= test__muldf3(0x0000000000000001, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x0000000000000001, 0xbfefffffffffffff, 0x8000000000000001);
-  status |= test__muldf3(0x0000000000000006, 0x3fe0000000000000, 0x0000000000000003);
-  status |= test__muldf3(0x0000000000000006, 0xbfe0000000000000, 0x8000000000000003);
-  status |= test__muldf3(0x0000000000000008, 0x3fc0000000000000, 0x0000000000000001);
-  status |= test__muldf3(0x000ffffffffffff7, 0x8020000000000003, 0x8000000000000000);
-  status |= test__muldf3(0x000ffffffffffff8, 0x3ff0000000000001, 0x000ffffffffffff9);
-  status |= test__muldf3(0x000ffffffffffff8, 0x3ff0000000000008, 0x0010000000000000);
-  status |= test__muldf3(0x000ffffffffffff8, 0xbff0000000000001, 0x800ffffffffffff9);
-  status |= test__muldf3(0x000ffffffffffff8, 0xbff0000000000008, 0x8010000000000000);
-  status |= test__muldf3(0x000ffffffffffffc, 0x4000000000000000, 0x001ffffffffffff8);
-  status |= test__muldf3(0x000ffffffffffffe, 0x3feffffffffffffc, 0x000ffffffffffffc);
-  status |= test__muldf3(0x000ffffffffffffe, 0x3ff0000000000001, 0x000fffffffffffff);
-  status |= test__muldf3(0x000ffffffffffffe, 0xbff0000000000001, 0x800fffffffffffff);
-  status |= test__muldf3(0x000fffffffffffff, 0x000ffffffffffffe, 0x0000000000000000);
-  status |= test__muldf3(0x000fffffffffffff, 0x3cb0000000000001, 0x0000000000000001);
-  status |= test__muldf3(0x000fffffffffffff, 0x3fe0000000000001, 0x0008000000000000);
-  status |= test__muldf3(0x000fffffffffffff, 0x3ff0000000000001, 0x0010000000000000);
-  status |= test__muldf3(0x000fffffffffffff, 0x4000000000000000, 0x001ffffffffffffe);
-  status |= test__muldf3(0x0010000000000000, 0x0000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x0010000000000000, 0x0010000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x0010000000000000, 0x3feffffffffffffe, 0x000fffffffffffff);
-  status |= test__muldf3(0x0010000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x0010000000000000, 0x8010000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x0010000000000000, 0xc000000000000000, 0x8020000000000000);
-  status |= test__muldf3(0x0010000000000001, 0x3feffffffffffffa, 0x000ffffffffffffe);
-  status |= test__muldf3(0x0010000000000001, 0x3feffffffffffffe, 0x0010000000000000);
-  status |= test__muldf3(0x0010000000000001, 0xc000000000000000, 0x8020000000000001);
-  status |= test__muldf3(0x0010000000000002, 0x3feffffffffffffc, 0x0010000000000000);
-  status |= test__muldf3(0x001ffffffffffff8, 0x3fe0000000000000, 0x000ffffffffffffc);
-  status |= test__muldf3(0x001ffffffffffffe, 0x3fe0000000000000, 0x000fffffffffffff);
-  status |= test__muldf3(0x001ffffffffffffe, 0xbfe0000000000000, 0x800fffffffffffff);
-  status |= test__muldf3(0x001fffffffffffff, 0x3fe0000000000000, 0x0010000000000000);
-  status |= test__muldf3(0x001fffffffffffff, 0xbfe0000000000000, 0x8010000000000000);
-  status |= test__muldf3(0x3fe0000000000000, 0x8000000000000001, 0x8000000000000000);
-  status |= test__muldf3(0x3ff0000000000000, 0x000ffffffffffffd, 0x000ffffffffffffd);
-  status |= test__muldf3(0x3ff0000000000000, 0x0020000000000003, 0x0020000000000003);
-  status |= test__muldf3(0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
-  status |= test__muldf3(0x3ff0000000000000, 0x4000000000000000, 0x4000000000000000);
-  status |= test__muldf3(0x3ff0000000000000, 0x8000000000000001, 0x8000000000000001);
-  status |= test__muldf3(0x3ff0000000000000, 0x8000000000000009, 0x8000000000000009);
-  status |= test__muldf3(0x3ff0000000000001, 0x3ff0000000000001, 0x3ff0000000000002);
-  status |= test__muldf3(0x3ff0000000000001, 0xbff0000000000001, 0xbff0000000000002);
-  status |= test__muldf3(0x3ff0000000000001, 0xbff0000000000002, 0xbff0000000000003);
-  status |= test__muldf3(0x3ff0000000000002, 0x3ff0000000000001, 0x3ff0000000000003);
-  status |= test__muldf3(0x3ff0000000000002, 0x7feffffffffffffe, 0x7ff0000000000000);
-  status |= test__muldf3(0x3ff0000000000001, 0x7feffffffffffffe, 0x7ff0000000000000);
-  status |= test__muldf3(0x4000000000000000, 0x0010000000000000, 0x0020000000000000);
-  status |= test__muldf3(0x4000000000000000, 0x0010000000000001, 0x0020000000000001);
-  status |= test__muldf3(0x4000000000000000, 0x3ff0000000000000, 0x4000000000000000);
-  status |= test__muldf3(0x4000000000000000, 0x4008000000000000, 0x4018000000000000);
-  status |= test__muldf3(0x4000000000000000, 0x7fd0000000000000, 0x7fe0000000000000);
-  status |= test__muldf3(0x4000000000000000, 0x7fdfffffffffffff, 0x7fefffffffffffff);
-  status |= test__muldf3(0x4000000000000000, 0x800ffffffffffffd, 0x801ffffffffffffa);
-  status |= test__muldf3(0x4000000000000000, 0x8010000000000003, 0x8020000000000003);
-  status |= test__muldf3(0x4000000000000000, 0x8010000000000005, 0x8020000000000005);
-  status |= test__muldf3(0x4000000000000000, 0xbff0000000000000, 0xc000000000000000);
-  status |= test__muldf3(0x4000000000000000, 0xffcffffffffffffd, 0xffdffffffffffffd);
-  status |= test__muldf3(0x4000000000000000, 0xffd0000000000003, 0xffe0000000000003);
-  status |= test__muldf3(0x4007ffffffffffff, 0x3feffffffffffffd, 0x4007fffffffffffd);
-  status |= test__muldf3(0x4007ffffffffffff, 0x3feffffffffffffe, 0x4007fffffffffffe);
-  status |= test__muldf3(0x4007ffffffffffff, 0x3fefffffffffffff, 0x4007fffffffffffe);
-  status |= test__muldf3(0x4007ffffffffffff, 0xbfeffffffffffffd, 0xc007fffffffffffd);
-  status |= test__muldf3(0x4008000000000000, 0x0000000000000002, 0x0000000000000006);
-  status |= test__muldf3(0x4008000000000000, 0x4000000000000000, 0x4018000000000000);
-  status |= test__muldf3(0x4008000000000000, 0x4008000000000000, 0x4022000000000000);
-  status |= test__muldf3(0x4008000000000000, 0xc000000000000000, 0xc018000000000000);
-  status |= test__muldf3(0x4008000000000001, 0x3ff0000000000001, 0x4008000000000003);
-  status |= test__muldf3(0x4008000000000001, 0x3ff0000000000003, 0x4008000000000006);
-  status |= test__muldf3(0x4008000000000001, 0xbff0000000000003, 0xc008000000000006);
-  status |= test__muldf3(0x4010000000000000, 0x0000000000000002, 0x0000000000000008);
-  status |= test__muldf3(0x4010000000000000, 0x7fcfffffffffffff, 0x7fefffffffffffff);
-  status |= test__muldf3(0x4010000000000000, 0xffcfffffffffffff, 0xffefffffffffffff);
-  status |= test__muldf3(0x4013ffffffffffff, 0x3fefffffffffffff, 0x4013fffffffffffe);
-  status |= test__muldf3(0x4014000000000000, 0x0000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x4014000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x4014000000000001, 0x3ff0000000000001, 0x4014000000000002);
-  status |= test__muldf3(0x401bffffffffffff, 0x3feffffffffffffc, 0x401bfffffffffffc);
-  status |= test__muldf3(0x401bffffffffffff, 0x3fefffffffffffff, 0x401bfffffffffffe);
-  status |= test__muldf3(0x401c000000000000, 0x8000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x401c000000000000, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x401c000000000001, 0x3ff0000000000001, 0x401c000000000003);
-  status |= test__muldf3(0x7fcffffffffffffd, 0x4010000000000000, 0x7feffffffffffffd);
-  status |= test__muldf3(0x7fcffffffffffffd, 0xc010000000000000, 0xffeffffffffffffd);
-  status |= test__muldf3(0x7fd0000000000000, 0xc000000000000000, 0xffe0000000000000);
-  status |= test__muldf3(0x7fdffffffffffffd, 0xc000000000000008, 0xfff0000000000000);
-  status |= test__muldf3(0x7fdfffffffffffff, 0xc000000000000000, 0xffefffffffffffff);
-  status |= test__muldf3(0x7fe0000000000000, 0x0000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x7fe0000000000000, 0x4000000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x7fe0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x7fe0000000000000, 0x7feffffffffffffe, 0x7ff0000000000000);
-  status |= test__muldf3(0x7fe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x7fe0000000000000, 0xffd0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x7fe0000000000000, 0xffd0000000000004, 0xfff0000000000000);
-  status |= test__muldf3(0x7fe0000000000000, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x7fe0000000000009, 0x7feffffffffffffa, 0x7ff0000000000000);
-  status |= test__muldf3(0x7fe0000000000009, 0xc018000000000002, 0xfff0000000000000);
-  status |= test__muldf3(0x7fefffffffffffff, 0x0000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x001fffffffffffff, 0x7ff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x7fdfffffffffffff, 0x7ff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x8000000000000002, 0xfff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x8010000000000001, 0xfff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x8020000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0xc008000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0xffefffffffffffff, 0xfff0000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0xfff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x8000000000000000, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x8000000000000000, 0x4018000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x8000000000000000, 0x7fefffffffffffff, 0x8000000000000000);
-  status |= test__muldf3(0x8000000000000000, 0x8000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x8000000000000000, 0x8000000000000004, 0x0000000000000000);
-  status |= test__muldf3(0x8000000000000000, 0x8010000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x8000000000000000, 0xc020000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x8000000000000000, 0xffd0000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x8000000000000001, 0x0000000000000001, 0x8000000000000000);
-  status |= test__muldf3(0x8000000000000001, 0x4014000000000000, 0x8000000000000005);
-  status |= test__muldf3(0x8000000000000002, 0x3ff0000000000000, 0x8000000000000002);
-  status |= test__muldf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x8000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x8000000000000004, 0xbff0000000000000, 0x0000000000000004);
-  status |= test__muldf3(0x8000000000000008, 0x3fc0000000000000, 0x8000000000000001);
-  status |= test__muldf3(0x800ffffffffffff7, 0x0020000000000003, 0x8000000000000000);
-  status |= test__muldf3(0x800ffffffffffff7, 0x3ff0000000000001, 0x800ffffffffffff8);
-  status |= test__muldf3(0x800ffffffffffffd, 0xc000000000000000, 0x001ffffffffffffa);
-  status |= test__muldf3(0x800fffffffffffff, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x800fffffffffffff, 0x3ff0000000000001, 0x8010000000000000);
-  status |= test__muldf3(0x800fffffffffffff, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x800fffffffffffff, 0x8000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x800fffffffffffff, 0x800ffffffffffffe, 0x0000000000000000);
-  status |= test__muldf3(0x800fffffffffffff, 0xbff0000000000000, 0x000fffffffffffff);
-  status |= test__muldf3(0x800fffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x8010000000000000, 0x0010000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x8010000000000000, 0x8010000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x8010000000000001, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x8010000000000001, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0x8010000000000001, 0xbff0000000000000, 0x0010000000000001);
-  status |= test__muldf3(0x801ffffffffffffc, 0x3fe0000000000000, 0x800ffffffffffffe);
-  status |= test__muldf3(0x801ffffffffffffc, 0xbfe0000000000000, 0x000ffffffffffffe);
-  status |= test__muldf3(0x801ffffffffffffe, 0x3ff0000000000000, 0x801ffffffffffffe);
-  status |= test__muldf3(0x801fffffffffffff, 0x8000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0x801fffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x8020000000000000, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0x8020000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xbfefffffffffffff, 0xffefffffffffffff, 0x7feffffffffffffe);
-  status |= test__muldf3(0xbff0000000000000, 0x0000000000000009, 0x8000000000000009);
-  status |= test__muldf3(0xbff0000000000000, 0x0010000000000009, 0x8010000000000009);
-  status |= test__muldf3(0xbff0000000000000, 0x3ff0000000000000, 0xbff0000000000000);
-  status |= test__muldf3(0xbff0000000000000, 0x4000000000000000, 0xc000000000000000);
-  status |= test__muldf3(0xbff0000000000000, 0xbff0000000000000, 0x3ff0000000000000);
-  status |= test__muldf3(0xbff0000000000000, 0xc000000000000000, 0x4000000000000000);
-  status |= test__muldf3(0xbff0000000000001, 0x3ff0000000000001, 0xbff0000000000002);
-  status |= test__muldf3(0xbff0000000000001, 0xbff0000000000001, 0x3ff0000000000002);
-  status |= test__muldf3(0xbff0000000000001, 0xbff0000000000002, 0x3ff0000000000003);
-  status |= test__muldf3(0xbff0000000000002, 0x3ff0000000000001, 0xbff0000000000003);
-  status |= test__muldf3(0xbff0000000000002, 0xbff0000000000001, 0x3ff0000000000003);
-  status |= test__muldf3(0xc000000000000000, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0xc000000000000000, 0x000ffffffffffffd, 0x801ffffffffffffa);
-  status |= test__muldf3(0xc000000000000000, 0x0010000000000001, 0x8020000000000001);
-  status |= test__muldf3(0xc000000000000000, 0x0010000000000005, 0x8020000000000005);
-  status |= test__muldf3(0xc000000000000000, 0x0010000000000009, 0x8020000000000009);
-  status |= test__muldf3(0xc000000000000000, 0x4008000000000000, 0xc018000000000000);
-  status |= test__muldf3(0xc000000000000000, 0x7fcfffffffffffff, 0xffdfffffffffffff);
-  status |= test__muldf3(0xc000000000000000, 0x7fd0000000000001, 0xffe0000000000001);
-  status |= test__muldf3(0xc000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xc000000000000000, 0xbff0000000000000, 0x4000000000000000);
-  status |= test__muldf3(0xc000000000000000, 0xc008000000000000, 0x4018000000000000);
-  status |= test__muldf3(0xc007fffffffffffe, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xc007ffffffffffff, 0x3fefffffffffffff, 0xc007fffffffffffe);
-  status |= test__muldf3(0xc008000000000000, 0x4008000000000000, 0xc022000000000000);
-  status |= test__muldf3(0xc008000000000000, 0xc000000000000000, 0x4018000000000000);
-  status |= test__muldf3(0xc008000000000000, 0xc008000000000000, 0x4022000000000000);
-  status |= test__muldf3(0xc008000000000000, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xc008000000000001, 0x3ff0000000000001, 0xc008000000000003);
-  status |= test__muldf3(0xc010000000000000, 0x7fcfffffffffffff, 0xffefffffffffffff);
-  status |= test__muldf3(0xc010000000000000, 0x8000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0xc010000000000000, 0xffcfffffffffffff, 0x7fefffffffffffff);
-  status |= test__muldf3(0xc010000000000000, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xc013fffffffffffe, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xc013ffffffffffff, 0xbfefffffffffffff, 0x4013fffffffffffe);
-  status |= test__muldf3(0xc014000000000001, 0xbff0000000000001, 0x4014000000000002);
-  status |= test__muldf3(0xc01bfffffffffff9, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xc022000000000000, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xc022000000000001, 0xffe0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xffcffffffffffff9, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xffcffffffffffff9, 0xc00fffffffffffff, 0x7feffffffffffff8);
-  status |= test__muldf3(0xffcffffffffffffd, 0x4010000000000000, 0xffeffffffffffffd);
-  status |= test__muldf3(0xffcffffffffffffd, 0xc010000000000000, 0x7feffffffffffffd);
-  status |= test__muldf3(0xffcfffffffffffff, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0xffcfffffffffffff, 0x4000000000000001, 0xffe0000000000000);
-  status |= test__muldf3(0xffcfffffffffffff, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xffd0000000000000, 0x0000000000000000, 0x8000000000000000);
-  status |= test__muldf3(0xffd0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xffdffffffffffff7, 0x7fd0000000000001, 0xfff0000000000000);
-  status |= test__muldf3(0xffdfffffffffffff, 0x3ff0000000000001, 0xffe0000000000000);
-  status |= test__muldf3(0xffdfffffffffffff, 0x8000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0xffe0000000000005, 0xffe0000000000001, 0x7ff0000000000000);
-  status |= test__muldf3(0xffeffffffffffffd, 0x7fe0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xffeffffffffffffd, 0xc008000000000001, 0x7ff0000000000000);
-  status |= test__muldf3(0xffeffffffffffffd, 0xffe0000000000001, 0x7ff0000000000000);
-  status |= test__muldf3(0xffefffffffffffff, 0x8000000000000000, 0x0000000000000000);
-  status |= test__muldf3(0xffefffffffffffff, 0xffefffffffffffff, 0x7ff0000000000000);
-  status |= test__muldf3(0xffefffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xfff0000000000000, 0x4018000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xfff0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
-  status |= test__muldf3(0xfff0000000000000, 0x8000000000000004, 0x7ff0000000000000);
-  status |= test__muldf3(0xfff0000000000000, 0x8010000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xfff0000000000000, 0xc020000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xfff0000000000000, 0xffd0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x002ffffffe000000, 0x3fcffffffffffffd, 0x000ffffffeffffff);
-  status |= test__muldf3(0xbfeffeffffffffff, 0x8010000000000100, 0x000fff80000000ff);
-  status |= test__muldf3(0x802ffffffe000000, 0x3fcffffffffffffd, 0x800ffffffeffffff);
-  status |= test__muldf3(0xbfeffeffffffffff, 0x0010000000000100, 0x800fff80000000ff);
-  status |= test__muldf3(0xbf9e8325a5aa6c8d, 0xbf9e8325a5aa6c8d, 0x3f4d180013083955);
-  status |= test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fe4000000000000, 0x3ff237a6f271c5c4);
-  status |= test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fe4000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x201d25d7ea4fa2d4, 0x1fd4000000000000, 0x00091bd37938e2e2);
-  status |= test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fe8000000000000, 0x3ff5dc61efbbba1f);
-  status |= test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fe8000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x201d25d7ea4fa2d4, 0x1fd8000000000000, 0x000aee30f7dddd10);
-  status |= test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fec000000000000, 0x3ff9811ced05ae7a);
-  status |= test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fec000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x201d25d7ea4fa2d4, 0x1fdc000000000000, 0x000cc08e7682d73d);
-  status |= test__muldf3(0x3ff265f139b6c87c, 0x3ff7000000000000, 0x3ffa728ac2f6c032);
-  status |= test__muldf3(0x6ff265f139b6c87c, 0x4ff7000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x201265f139b6c87c, 0x1fe7000000000000, 0x000d3945617b6019);
-  status |= test__muldf3(0x3ff265f139b6c87c, 0x3ff5000000000000, 0x3ff825cc9bbfe723);
-  status |= test__muldf3(0x6ff265f139b6c87c, 0x4ff5000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x201265f139b6c87c, 0x1fe5000000000000, 0x000c12e64ddff391);
-  status |= test__muldf3(0x3ffe5ab1dc9f12f9, 0x3ff0c1a10c80f0b7, 0x3fffca09666ab16e);
-  status |= test__muldf3(0x6ffe5ab1dc9f12f9, 0x4ff0c1a10c80f0b7, 0x7ff0000000000000);
-  status |= test__muldf3(0x201e5ab1dc9f12f9, 0x1fe0c1a10c80f0b7, 0x000fe504b33558b7);
-  status |= test__muldf3(0x3ffe5ab1dc9f12f9, 0x3fe73e5ef37f0f49, 0x3ff60c59a0917f00);
-  status |= test__muldf3(0x6ffe5ab1dc9f12f9, 0x4fe73e5ef37f0f49, 0x7ff0000000000000);
-  status |= test__muldf3(0x201e5ab1dc9f12f9, 0x1fd73e5ef37f0f49, 0x000b062cd048bf80);
-  status |= test__muldf3(0x3ffe5ab1dc9f12f9, 0x3fe8c1a10c80f0b7, 0x3ff77bb12a5d1d75);
-  status |= test__muldf3(0x6ffe5ab1dc9f12f9, 0x4fe8c1a10c80f0b7, 0x7ff0000000000000);
-  status |= test__muldf3(0x201e5ab1dc9f12f9, 0x1fd8c1a10c80f0b7, 0x000bbdd8952e8ebb);
-  status |= test__muldf3(0x3ffc6be665de3b1d, 0x3fe52d156619a0cb, 0x3ff2ced9f056fba8);
-  status |= test__muldf3(0x6ffc6be665de3b1d, 0x4fe52d156619a0cb, 0x7ff0000000000000);
-  status |= test__muldf3(0x201c6be665de3b1d, 0x1fd52d156619a0cb, 0x0009676cf82b7dd4);
-  status |= test__muldf3(0x3ffc6be665de3b1d, 0x3fead2ea99e65f35, 0x3ff7d2ffa8765d03);
-  status |= test__muldf3(0x6ffc6be665de3b1d, 0x4fead2ea99e65f35, 0x7ff0000000000000);
-  status |= test__muldf3(0x201c6be665de3b1d, 0x1fdad2ea99e65f35, 0x000be97fd43b2e82);
-  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ff5c9b956d0b54b, 0x3ff82c50eb71ac34);
-  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ff5c9b956d0b54b, 0x7ff0000000000000);
-  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fe5c9b956d0b54b, 0x000c162875b8d61a);
-  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ff23646a92f4ab5, 0x3ff434a77da664d4);
-  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ff23646a92f4ab5, 0x7ff0000000000000);
-  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fe23646a92f4ab5, 0x000a1a53bed3326a);
-  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ffa3646a92f4ab5, 0x3ffd14d92c44cea3);
-  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ffa3646a92f4ab5, 0x7ff0000000000000);
-  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fea3646a92f4ab5, 0x000e8a6c96226751);
-  status |= test__muldf3(0x3ff1c0635d3cd39d, 0x3ff1c9b956d0b54b, 0x3ff3bc381422774d);
-  status |= test__muldf3(0x6ff1c0635d3cd39d, 0x4ff1c9b956d0b54b, 0x7ff0000000000000);
-  status |= test__muldf3(0x2011c0635d3cd39d, 0x1fe1c9b956d0b54b, 0x0009de1c0a113ba6);
-  status |= test__muldf3(0x3ff907065fd11389, 0x3fe46bad37af52b9, 0x3feff135e5756ec7);
-  status |= test__muldf3(0x6ff907065fd11389, 0x4fe46bad37af52b9, 0x7feff135e5756ec7);
-  status |= test__muldf3(0x201907065fd11389, 0x1fd46bad37af52b9, 0x0007fc4d795d5bb2);
-  status |= test__muldf3(0x3ff907065fd11389, 0x3feb9452c850ad47, 0x3ff591ee9cfee5ea);
-  status |= test__muldf3(0x6ff907065fd11389, 0x4feb9452c850ad47, 0x7ff0000000000000);
-  status |= test__muldf3(0x201907065fd11389, 0x1fdb9452c850ad47, 0x000ac8f74e7f72f5);
-  status |= test__muldf3(0x3ff761c03e198df7, 0x3fe7f47c731d43c7, 0x3ff180e675617e83);
-  status |= test__muldf3(0x6ff761c03e198df7, 0x4fe7f47c731d43c7, 0x7ff0000000000000);
-  status |= test__muldf3(0x201761c03e198df7, 0x1fd7f47c731d43c7, 0x0008c0733ab0bf41);
-  status |= test__muldf3(0x3ffce6d1246c46fb, 0x3ff0b3469ded2bcd, 0x3ffe2aa6f74c0ffd);
-  status |= test__muldf3(0x6ffce6d1246c46fb, 0x4ff0b3469ded2bcd, 0x7ff0000000000000);
-  status |= test__muldf3(0x201ce6d1246c46fb, 0x1fe0b3469ded2bcd, 0x000f15537ba607fe);
-  status |= test__muldf3(0x3ffd5701100ec79d, 0x3fee654fee13094b, 0x3ffbde74e37bb583);
-  status |= test__muldf3(0x6ffd5701100ec79d, 0x4fee654fee13094b, 0x7ff0000000000000);
-  status |= test__muldf3(0x201d5701100ec79d, 0x1fde654fee13094b, 0x000def3a71bddac1);
-  status |= test__muldf3(0x3ffce1a06e8bcfd3, 0x3ff01c54436a605b, 0x3ffd14c361885d61);
-  status |= test__muldf3(0x6ffce1a06e8bcfd3, 0x4ff01c54436a605b, 0x7ff0000000000000);
-  status |= test__muldf3(0x201ce1a06e8bcfd3, 0x1fe01c54436a605b, 0x000e8a61b0c42eb0);
-  status |= test__muldf3(0x3ff21d1a5ca518a5, 0x3ff29f0ce1150f2d, 0x3ff514cd72d743f2);
-  status |= test__muldf3(0x6ff21d1a5ca518a5, 0x4ff29f0ce1150f2d, 0x7ff0000000000000);
-  status |= test__muldf3(0x20121d1a5ca518a5, 0x1fe29f0ce1150f2d, 0x000a8a66b96ba1f9);
-  status |= test__muldf3(0x3ff031a98dbf97ba, 0x3ff4000000000000, 0x3ff43e13f12f7da8);
-  status |= test__muldf3(0x6ff031a98dbf97ba, 0x4ff4000000000000, 0x7ff0000000000000);
-  status |= test__muldf3(0x201031a98dbf97ba, 0x1fe4000000000000, 0x000a1f09f897bed4);
-  status |= test__muldf3(0x0000000000000003, 0xc00fffffffffffff, 0x800000000000000c);
-  status |= test__muldf3(0x0000000000000003, 0x400fffffffffffff, 0x000000000000000c);
-  status |= test__muldf3(0x8000000000000003, 0xc00fffffffffffff, 0x000000000000000c);
-  status |= test__muldf3(0x8000000000000003, 0x400fffffffffffff, 0x800000000000000c);
-  status |= test__muldf3(0x0000000000000003, 0xc00ffffffffffffd, 0x800000000000000c);
-  status |= test__muldf3(0x0000000000000003, 0x400ffffffffffffd, 0x000000000000000c);
-  status |= test__muldf3(0x8000000000000003, 0xc00ffffffffffffd, 0x000000000000000c);
-  status |= test__muldf3(0x8000000000000003, 0x400ffffffffffffd, 0x800000000000000c);
-  status |= test__muldf3(0x1e51f703ee090000, 0x1e5c8000e4000000, 0x0000000000000001);
-  status |= test__muldf3(0x1e561ed9745fdb21, 0x1e57255ca25b68e1, 0x0000000000000001);
-  status |= test__muldf3(0x7feffffffff00000, 0xc000000000080000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x000fffffffffffff, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x001fffffffffffff, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x3ff0000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x7fdfffffffffffff, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x8000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x8000000000000002, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x800fffffffffffff, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x8010000000000001, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0x8020000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0xc008000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0xffcfffffffffffff, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0xffe0000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000000, 0xffefffffffffffff, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0000000000000001, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000001, 0x0000000000000001, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000001, 0x3fe0000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0000000000000001, 0x3fefffffffffffff, 0x0000000000000001);
+  status |=
+      test__muldf3(0x0000000000000001, 0x3ff0000000000000, 0x0000000000000001);
+  status |=
+      test__muldf3(0x0000000000000001, 0x4000000000000000, 0x0000000000000002);
+  status |=
+      test__muldf3(0x0000000000000001, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x0000000000000001, 0xbfefffffffffffff, 0x8000000000000001);
+  status |=
+      test__muldf3(0x0000000000000006, 0x3fe0000000000000, 0x0000000000000003);
+  status |=
+      test__muldf3(0x0000000000000006, 0xbfe0000000000000, 0x8000000000000003);
+  status |=
+      test__muldf3(0x0000000000000008, 0x3fc0000000000000, 0x0000000000000001);
+  status |=
+      test__muldf3(0x000ffffffffffff7, 0x8020000000000003, 0x8000000000000000);
+  status |=
+      test__muldf3(0x000ffffffffffff8, 0x3ff0000000000001, 0x000ffffffffffff9);
+  status |=
+      test__muldf3(0x000ffffffffffff8, 0x3ff0000000000008, 0x0010000000000000);
+  status |=
+      test__muldf3(0x000ffffffffffff8, 0xbff0000000000001, 0x800ffffffffffff9);
+  status |=
+      test__muldf3(0x000ffffffffffff8, 0xbff0000000000008, 0x8010000000000000);
+  status |=
+      test__muldf3(0x000ffffffffffffc, 0x4000000000000000, 0x001ffffffffffff8);
+  status |=
+      test__muldf3(0x000ffffffffffffe, 0x3feffffffffffffc, 0x000ffffffffffffc);
+  status |=
+      test__muldf3(0x000ffffffffffffe, 0x3ff0000000000001, 0x000fffffffffffff);
+  status |=
+      test__muldf3(0x000ffffffffffffe, 0xbff0000000000001, 0x800fffffffffffff);
+  status |=
+      test__muldf3(0x000fffffffffffff, 0x000ffffffffffffe, 0x0000000000000000);
+  status |=
+      test__muldf3(0x000fffffffffffff, 0x3cb0000000000001, 0x0000000000000001);
+  status |=
+      test__muldf3(0x000fffffffffffff, 0x3fe0000000000001, 0x0008000000000000);
+  status |=
+      test__muldf3(0x000fffffffffffff, 0x3ff0000000000001, 0x0010000000000000);
+  status |=
+      test__muldf3(0x000fffffffffffff, 0x4000000000000000, 0x001ffffffffffffe);
+  status |=
+      test__muldf3(0x0010000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0010000000000000, 0x0010000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x0010000000000000, 0x3feffffffffffffe, 0x000fffffffffffff);
+  status |=
+      test__muldf3(0x0010000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x0010000000000000, 0x8010000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x0010000000000000, 0xc000000000000000, 0x8020000000000000);
+  status |=
+      test__muldf3(0x0010000000000001, 0x3feffffffffffffa, 0x000ffffffffffffe);
+  status |=
+      test__muldf3(0x0010000000000001, 0x3feffffffffffffe, 0x0010000000000000);
+  status |=
+      test__muldf3(0x0010000000000001, 0xc000000000000000, 0x8020000000000001);
+  status |=
+      test__muldf3(0x0010000000000002, 0x3feffffffffffffc, 0x0010000000000000);
+  status |=
+      test__muldf3(0x001ffffffffffff8, 0x3fe0000000000000, 0x000ffffffffffffc);
+  status |=
+      test__muldf3(0x001ffffffffffffe, 0x3fe0000000000000, 0x000fffffffffffff);
+  status |=
+      test__muldf3(0x001ffffffffffffe, 0xbfe0000000000000, 0x800fffffffffffff);
+  status |=
+      test__muldf3(0x001fffffffffffff, 0x3fe0000000000000, 0x0010000000000000);
+  status |=
+      test__muldf3(0x001fffffffffffff, 0xbfe0000000000000, 0x8010000000000000);
+  status |=
+      test__muldf3(0x3fe0000000000000, 0x8000000000000001, 0x8000000000000000);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x000ffffffffffffd, 0x000ffffffffffffd);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x0020000000000003, 0x0020000000000003);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x4000000000000000, 0x4000000000000000);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x8000000000000001, 0x8000000000000001);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x8000000000000009, 0x8000000000000009);
+  status |=
+      test__muldf3(0x3ff0000000000001, 0x3ff0000000000001, 0x3ff0000000000002);
+  status |=
+      test__muldf3(0x3ff0000000000001, 0xbff0000000000001, 0xbff0000000000002);
+  status |=
+      test__muldf3(0x3ff0000000000001, 0xbff0000000000002, 0xbff0000000000003);
+  status |=
+      test__muldf3(0x3ff0000000000002, 0x3ff0000000000001, 0x3ff0000000000003);
+  status |=
+      test__muldf3(0x3ff0000000000002, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x3ff0000000000001, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x4000000000000000, 0x0010000000000000, 0x0020000000000000);
+  status |=
+      test__muldf3(0x4000000000000000, 0x0010000000000001, 0x0020000000000001);
+  status |=
+      test__muldf3(0x4000000000000000, 0x3ff0000000000000, 0x4000000000000000);
+  status |=
+      test__muldf3(0x4000000000000000, 0x4008000000000000, 0x4018000000000000);
+  status |=
+      test__muldf3(0x4000000000000000, 0x7fd0000000000000, 0x7fe0000000000000);
+  status |=
+      test__muldf3(0x4000000000000000, 0x7fdfffffffffffff, 0x7fefffffffffffff);
+  status |=
+      test__muldf3(0x4000000000000000, 0x800ffffffffffffd, 0x801ffffffffffffa);
+  status |=
+      test__muldf3(0x4000000000000000, 0x8010000000000003, 0x8020000000000003);
+  status |=
+      test__muldf3(0x4000000000000000, 0x8010000000000005, 0x8020000000000005);
+  status |=
+      test__muldf3(0x4000000000000000, 0xbff0000000000000, 0xc000000000000000);
+  status |=
+      test__muldf3(0x4000000000000000, 0xffcffffffffffffd, 0xffdffffffffffffd);
+  status |=
+      test__muldf3(0x4000000000000000, 0xffd0000000000003, 0xffe0000000000003);
+  status |=
+      test__muldf3(0x4007ffffffffffff, 0x3feffffffffffffd, 0x4007fffffffffffd);
+  status |=
+      test__muldf3(0x4007ffffffffffff, 0x3feffffffffffffe, 0x4007fffffffffffe);
+  status |=
+      test__muldf3(0x4007ffffffffffff, 0x3fefffffffffffff, 0x4007fffffffffffe);
+  status |=
+      test__muldf3(0x4007ffffffffffff, 0xbfeffffffffffffd, 0xc007fffffffffffd);
+  status |=
+      test__muldf3(0x4008000000000000, 0x0000000000000002, 0x0000000000000006);
+  status |=
+      test__muldf3(0x4008000000000000, 0x4000000000000000, 0x4018000000000000);
+  status |=
+      test__muldf3(0x4008000000000000, 0x4008000000000000, 0x4022000000000000);
+  status |=
+      test__muldf3(0x4008000000000000, 0xc000000000000000, 0xc018000000000000);
+  status |=
+      test__muldf3(0x4008000000000001, 0x3ff0000000000001, 0x4008000000000003);
+  status |=
+      test__muldf3(0x4008000000000001, 0x3ff0000000000003, 0x4008000000000006);
+  status |=
+      test__muldf3(0x4008000000000001, 0xbff0000000000003, 0xc008000000000006);
+  status |=
+      test__muldf3(0x4010000000000000, 0x0000000000000002, 0x0000000000000008);
+  status |=
+      test__muldf3(0x4010000000000000, 0x7fcfffffffffffff, 0x7fefffffffffffff);
+  status |=
+      test__muldf3(0x4010000000000000, 0xffcfffffffffffff, 0xffefffffffffffff);
+  status |=
+      test__muldf3(0x4013ffffffffffff, 0x3fefffffffffffff, 0x4013fffffffffffe);
+  status |=
+      test__muldf3(0x4014000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x4014000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x4014000000000001, 0x3ff0000000000001, 0x4014000000000002);
+  status |=
+      test__muldf3(0x401bffffffffffff, 0x3feffffffffffffc, 0x401bfffffffffffc);
+  status |=
+      test__muldf3(0x401bffffffffffff, 0x3fefffffffffffff, 0x401bfffffffffffe);
+  status |=
+      test__muldf3(0x401c000000000000, 0x8000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x401c000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x401c000000000001, 0x3ff0000000000001, 0x401c000000000003);
+  status |=
+      test__muldf3(0x7fcffffffffffffd, 0x4010000000000000, 0x7feffffffffffffd);
+  status |=
+      test__muldf3(0x7fcffffffffffffd, 0xc010000000000000, 0xffeffffffffffffd);
+  status |=
+      test__muldf3(0x7fd0000000000000, 0xc000000000000000, 0xffe0000000000000);
+  status |=
+      test__muldf3(0x7fdffffffffffffd, 0xc000000000000008, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7fdfffffffffffff, 0xc000000000000000, 0xffefffffffffffff);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0x4000000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0x7fe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0x7feffffffffffffe, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0xffd0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0xffd0000000000004, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000009, 0x7feffffffffffffa, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7fe0000000000009, 0xc018000000000002, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7fefffffffffffff, 0x0000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x000fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x001fffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x7fdfffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x8000000000000002, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x800fffffffffffff, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x8010000000000001, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x8020000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0xc008000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0xffe0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0xffefffffffffffff, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0xfff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0x4018000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0x7fefffffffffffff, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0x8000000000000004, 0x0000000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0xc020000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0xffd0000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x8000000000000001, 0x0000000000000001, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8000000000000001, 0x4014000000000000, 0x8000000000000005);
+  status |=
+      test__muldf3(0x8000000000000002, 0x3ff0000000000000, 0x8000000000000002);
+  status |=
+      test__muldf3(0x8000000000000003, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8000000000000003, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x8000000000000004, 0xbff0000000000000, 0x0000000000000004);
+  status |=
+      test__muldf3(0x8000000000000008, 0x3fc0000000000000, 0x8000000000000001);
+  status |=
+      test__muldf3(0x800ffffffffffff7, 0x0020000000000003, 0x8000000000000000);
+  status |=
+      test__muldf3(0x800ffffffffffff7, 0x3ff0000000000001, 0x800ffffffffffff8);
+  status |=
+      test__muldf3(0x800ffffffffffffd, 0xc000000000000000, 0x001ffffffffffffa);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0x3ff0000000000001, 0x8010000000000000);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0x800ffffffffffffe, 0x0000000000000000);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0xbff0000000000000, 0x000fffffffffffff);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x8010000000000000, 0x0010000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8010000000000000, 0x8010000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x8010000000000001, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8010000000000001, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0x8010000000000001, 0xbff0000000000000, 0x0010000000000001);
+  status |=
+      test__muldf3(0x801ffffffffffffc, 0x3fe0000000000000, 0x800ffffffffffffe);
+  status |=
+      test__muldf3(0x801ffffffffffffc, 0xbfe0000000000000, 0x000ffffffffffffe);
+  status |=
+      test__muldf3(0x801ffffffffffffe, 0x3ff0000000000000, 0x801ffffffffffffe);
+  status |=
+      test__muldf3(0x801fffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0x801fffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x8020000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0x8020000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xbfefffffffffffff, 0xffefffffffffffff, 0x7feffffffffffffe);
+  status |=
+      test__muldf3(0xbff0000000000000, 0x0000000000000009, 0x8000000000000009);
+  status |=
+      test__muldf3(0xbff0000000000000, 0x0010000000000009, 0x8010000000000009);
+  status |=
+      test__muldf3(0xbff0000000000000, 0x3ff0000000000000, 0xbff0000000000000);
+  status |=
+      test__muldf3(0xbff0000000000000, 0x4000000000000000, 0xc000000000000000);
+  status |=
+      test__muldf3(0xbff0000000000000, 0xbff0000000000000, 0x3ff0000000000000);
+  status |=
+      test__muldf3(0xbff0000000000000, 0xc000000000000000, 0x4000000000000000);
+  status |=
+      test__muldf3(0xbff0000000000001, 0x3ff0000000000001, 0xbff0000000000002);
+  status |=
+      test__muldf3(0xbff0000000000001, 0xbff0000000000001, 0x3ff0000000000002);
+  status |=
+      test__muldf3(0xbff0000000000001, 0xbff0000000000002, 0x3ff0000000000003);
+  status |=
+      test__muldf3(0xbff0000000000002, 0x3ff0000000000001, 0xbff0000000000003);
+  status |=
+      test__muldf3(0xbff0000000000002, 0xbff0000000000001, 0x3ff0000000000003);
+  status |=
+      test__muldf3(0xc000000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0xc000000000000000, 0x000ffffffffffffd, 0x801ffffffffffffa);
+  status |=
+      test__muldf3(0xc000000000000000, 0x0010000000000001, 0x8020000000000001);
+  status |=
+      test__muldf3(0xc000000000000000, 0x0010000000000005, 0x8020000000000005);
+  status |=
+      test__muldf3(0xc000000000000000, 0x0010000000000009, 0x8020000000000009);
+  status |=
+      test__muldf3(0xc000000000000000, 0x4008000000000000, 0xc018000000000000);
+  status |=
+      test__muldf3(0xc000000000000000, 0x7fcfffffffffffff, 0xffdfffffffffffff);
+  status |=
+      test__muldf3(0xc000000000000000, 0x7fd0000000000001, 0xffe0000000000001);
+  status |=
+      test__muldf3(0xc000000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xc000000000000000, 0xbff0000000000000, 0x4000000000000000);
+  status |=
+      test__muldf3(0xc000000000000000, 0xc008000000000000, 0x4018000000000000);
+  status |=
+      test__muldf3(0xc007fffffffffffe, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xc007ffffffffffff, 0x3fefffffffffffff, 0xc007fffffffffffe);
+  status |=
+      test__muldf3(0xc008000000000000, 0x4008000000000000, 0xc022000000000000);
+  status |=
+      test__muldf3(0xc008000000000000, 0xc000000000000000, 0x4018000000000000);
+  status |=
+      test__muldf3(0xc008000000000000, 0xc008000000000000, 0x4022000000000000);
+  status |=
+      test__muldf3(0xc008000000000000, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xc008000000000001, 0x3ff0000000000001, 0xc008000000000003);
+  status |=
+      test__muldf3(0xc010000000000000, 0x7fcfffffffffffff, 0xffefffffffffffff);
+  status |=
+      test__muldf3(0xc010000000000000, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0xc010000000000000, 0xffcfffffffffffff, 0x7fefffffffffffff);
+  status |=
+      test__muldf3(0xc010000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xc013fffffffffffe, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xc013ffffffffffff, 0xbfefffffffffffff, 0x4013fffffffffffe);
+  status |=
+      test__muldf3(0xc014000000000001, 0xbff0000000000001, 0x4014000000000002);
+  status |=
+      test__muldf3(0xc01bfffffffffff9, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xc022000000000000, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xc022000000000001, 0xffe0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xffcffffffffffff9, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xffcffffffffffff9, 0xc00fffffffffffff, 0x7feffffffffffff8);
+  status |=
+      test__muldf3(0xffcffffffffffffd, 0x4010000000000000, 0xffeffffffffffffd);
+  status |=
+      test__muldf3(0xffcffffffffffffd, 0xc010000000000000, 0x7feffffffffffffd);
+  status |=
+      test__muldf3(0xffcfffffffffffff, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0xffcfffffffffffff, 0x4000000000000001, 0xffe0000000000000);
+  status |=
+      test__muldf3(0xffcfffffffffffff, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xffd0000000000000, 0x0000000000000000, 0x8000000000000000);
+  status |=
+      test__muldf3(0xffd0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xffdffffffffffff7, 0x7fd0000000000001, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xffdfffffffffffff, 0x3ff0000000000001, 0xffe0000000000000);
+  status |=
+      test__muldf3(0xffdfffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0xffe0000000000005, 0xffe0000000000001, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xffeffffffffffffd, 0x7fe0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xffeffffffffffffd, 0xc008000000000001, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xffeffffffffffffd, 0xffe0000000000001, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xffefffffffffffff, 0x8000000000000000, 0x0000000000000000);
+  status |=
+      test__muldf3(0xffefffffffffffff, 0xffefffffffffffff, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xffefffffffffffff, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xfff0000000000000, 0x4018000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xfff0000000000000, 0x7ff0000000000000, 0xfff0000000000000);
+  status |=
+      test__muldf3(0xfff0000000000000, 0x8000000000000004, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xfff0000000000000, 0x8010000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xfff0000000000000, 0xc020000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xfff0000000000000, 0xffd0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0xfff0000000000000, 0xfff0000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x002ffffffe000000, 0x3fcffffffffffffd, 0x000ffffffeffffff);
+  status |=
+      test__muldf3(0xbfeffeffffffffff, 0x8010000000000100, 0x000fff80000000ff);
+  status |=
+      test__muldf3(0x802ffffffe000000, 0x3fcffffffffffffd, 0x800ffffffeffffff);
+  status |=
+      test__muldf3(0xbfeffeffffffffff, 0x0010000000000100, 0x800fff80000000ff);
+  status |=
+      test__muldf3(0xbf9e8325a5aa6c8d, 0xbf9e8325a5aa6c8d, 0x3f4d180013083955);
+  status |=
+      test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fe4000000000000, 0x3ff237a6f271c5c4);
+  status |=
+      test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fe4000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201d25d7ea4fa2d4, 0x1fd4000000000000, 0x00091bd37938e2e2);
+  status |=
+      test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fe8000000000000, 0x3ff5dc61efbbba1f);
+  status |=
+      test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fe8000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201d25d7ea4fa2d4, 0x1fd8000000000000, 0x000aee30f7dddd10);
+  status |=
+      test__muldf3(0x3ffd25d7ea4fa2d4, 0x3fec000000000000, 0x3ff9811ced05ae7a);
+  status |=
+      test__muldf3(0x6ffd25d7ea4fa2d4, 0x4fec000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201d25d7ea4fa2d4, 0x1fdc000000000000, 0x000cc08e7682d73d);
+  status |=
+      test__muldf3(0x3ff265f139b6c87c, 0x3ff7000000000000, 0x3ffa728ac2f6c032);
+  status |=
+      test__muldf3(0x6ff265f139b6c87c, 0x4ff7000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201265f139b6c87c, 0x1fe7000000000000, 0x000d3945617b6019);
+  status |=
+      test__muldf3(0x3ff265f139b6c87c, 0x3ff5000000000000, 0x3ff825cc9bbfe723);
+  status |=
+      test__muldf3(0x6ff265f139b6c87c, 0x4ff5000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201265f139b6c87c, 0x1fe5000000000000, 0x000c12e64ddff391);
+  status |=
+      test__muldf3(0x3ffe5ab1dc9f12f9, 0x3ff0c1a10c80f0b7, 0x3fffca09666ab16e);
+  status |=
+      test__muldf3(0x6ffe5ab1dc9f12f9, 0x4ff0c1a10c80f0b7, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201e5ab1dc9f12f9, 0x1fe0c1a10c80f0b7, 0x000fe504b33558b7);
+  status |=
+      test__muldf3(0x3ffe5ab1dc9f12f9, 0x3fe73e5ef37f0f49, 0x3ff60c59a0917f00);
+  status |=
+      test__muldf3(0x6ffe5ab1dc9f12f9, 0x4fe73e5ef37f0f49, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201e5ab1dc9f12f9, 0x1fd73e5ef37f0f49, 0x000b062cd048bf80);
+  status |=
+      test__muldf3(0x3ffe5ab1dc9f12f9, 0x3fe8c1a10c80f0b7, 0x3ff77bb12a5d1d75);
+  status |=
+      test__muldf3(0x6ffe5ab1dc9f12f9, 0x4fe8c1a10c80f0b7, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201e5ab1dc9f12f9, 0x1fd8c1a10c80f0b7, 0x000bbdd8952e8ebb);
+  status |=
+      test__muldf3(0x3ffc6be665de3b1d, 0x3fe52d156619a0cb, 0x3ff2ced9f056fba8);
+  status |=
+      test__muldf3(0x6ffc6be665de3b1d, 0x4fe52d156619a0cb, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201c6be665de3b1d, 0x1fd52d156619a0cb, 0x0009676cf82b7dd4);
+  status |=
+      test__muldf3(0x3ffc6be665de3b1d, 0x3fead2ea99e65f35, 0x3ff7d2ffa8765d03);
+  status |=
+      test__muldf3(0x6ffc6be665de3b1d, 0x4fead2ea99e65f35, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201c6be665de3b1d, 0x1fdad2ea99e65f35, 0x000be97fd43b2e82);
+  status |=
+      test__muldf3(0x3ff1c0635d3cd39d, 0x3ff5c9b956d0b54b, 0x3ff82c50eb71ac34);
+  status |=
+      test__muldf3(0x6ff1c0635d3cd39d, 0x4ff5c9b956d0b54b, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x2011c0635d3cd39d, 0x1fe5c9b956d0b54b, 0x000c162875b8d61a);
+  status |=
+      test__muldf3(0x3ff1c0635d3cd39d, 0x3ff23646a92f4ab5, 0x3ff434a77da664d4);
+  status |=
+      test__muldf3(0x6ff1c0635d3cd39d, 0x4ff23646a92f4ab5, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x2011c0635d3cd39d, 0x1fe23646a92f4ab5, 0x000a1a53bed3326a);
+  status |=
+      test__muldf3(0x3ff1c0635d3cd39d, 0x3ffa3646a92f4ab5, 0x3ffd14d92c44cea3);
+  status |=
+      test__muldf3(0x6ff1c0635d3cd39d, 0x4ffa3646a92f4ab5, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x2011c0635d3cd39d, 0x1fea3646a92f4ab5, 0x000e8a6c96226751);
+  status |=
+      test__muldf3(0x3ff1c0635d3cd39d, 0x3ff1c9b956d0b54b, 0x3ff3bc381422774d);
+  status |=
+      test__muldf3(0x6ff1c0635d3cd39d, 0x4ff1c9b956d0b54b, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x2011c0635d3cd39d, 0x1fe1c9b956d0b54b, 0x0009de1c0a113ba6);
+  status |=
+      test__muldf3(0x3ff907065fd11389, 0x3fe46bad37af52b9, 0x3feff135e5756ec7);
+  status |=
+      test__muldf3(0x6ff907065fd11389, 0x4fe46bad37af52b9, 0x7feff135e5756ec7);
+  status |=
+      test__muldf3(0x201907065fd11389, 0x1fd46bad37af52b9, 0x0007fc4d795d5bb2);
+  status |=
+      test__muldf3(0x3ff907065fd11389, 0x3feb9452c850ad47, 0x3ff591ee9cfee5ea);
+  status |=
+      test__muldf3(0x6ff907065fd11389, 0x4feb9452c850ad47, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201907065fd11389, 0x1fdb9452c850ad47, 0x000ac8f74e7f72f5);
+  status |=
+      test__muldf3(0x3ff761c03e198df7, 0x3fe7f47c731d43c7, 0x3ff180e675617e83);
+  status |=
+      test__muldf3(0x6ff761c03e198df7, 0x4fe7f47c731d43c7, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201761c03e198df7, 0x1fd7f47c731d43c7, 0x0008c0733ab0bf41);
+  status |=
+      test__muldf3(0x3ffce6d1246c46fb, 0x3ff0b3469ded2bcd, 0x3ffe2aa6f74c0ffd);
+  status |=
+      test__muldf3(0x6ffce6d1246c46fb, 0x4ff0b3469ded2bcd, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201ce6d1246c46fb, 0x1fe0b3469ded2bcd, 0x000f15537ba607fe);
+  status |=
+      test__muldf3(0x3ffd5701100ec79d, 0x3fee654fee13094b, 0x3ffbde74e37bb583);
+  status |=
+      test__muldf3(0x6ffd5701100ec79d, 0x4fee654fee13094b, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201d5701100ec79d, 0x1fde654fee13094b, 0x000def3a71bddac1);
+  status |=
+      test__muldf3(0x3ffce1a06e8bcfd3, 0x3ff01c54436a605b, 0x3ffd14c361885d61);
+  status |=
+      test__muldf3(0x6ffce1a06e8bcfd3, 0x4ff01c54436a605b, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201ce1a06e8bcfd3, 0x1fe01c54436a605b, 0x000e8a61b0c42eb0);
+  status |=
+      test__muldf3(0x3ff21d1a5ca518a5, 0x3ff29f0ce1150f2d, 0x3ff514cd72d743f2);
+  status |=
+      test__muldf3(0x6ff21d1a5ca518a5, 0x4ff29f0ce1150f2d, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x20121d1a5ca518a5, 0x1fe29f0ce1150f2d, 0x000a8a66b96ba1f9);
+  status |=
+      test__muldf3(0x3ff031a98dbf97ba, 0x3ff4000000000000, 0x3ff43e13f12f7da8);
+  status |=
+      test__muldf3(0x6ff031a98dbf97ba, 0x4ff4000000000000, 0x7ff0000000000000);
+  status |=
+      test__muldf3(0x201031a98dbf97ba, 0x1fe4000000000000, 0x000a1f09f897bed4);
+  status |=
+      test__muldf3(0x0000000000000003, 0xc00fffffffffffff, 0x800000000000000c);
+  status |=
+      test__muldf3(0x0000000000000003, 0x400fffffffffffff, 0x000000000000000c);
+  status |=
+      test__muldf3(0x8000000000000003, 0xc00fffffffffffff, 0x000000000000000c);
+  status |=
+      test__muldf3(0x8000000000000003, 0x400fffffffffffff, 0x800000000000000c);
+  status |=
+      test__muldf3(0x0000000000000003, 0xc00ffffffffffffd, 0x800000000000000c);
+  status |=
+      test__muldf3(0x0000000000000003, 0x400ffffffffffffd, 0x000000000000000c);
+  status |=
+      test__muldf3(0x8000000000000003, 0xc00ffffffffffffd, 0x000000000000000c);
+  status |=
+      test__muldf3(0x8000000000000003, 0x400ffffffffffffd, 0x800000000000000c);
+  status |=
+      test__muldf3(0x1e51f703ee090000, 0x1e5c8000e4000000, 0x0000000000000001);
+  status |=
+      test__muldf3(0x1e561ed9745fdb21, 0x1e57255ca25b68e1, 0x0000000000000001);
+  status |=
+      test__muldf3(0x7feffffffff00000, 0xc000000000080000, 0xfff0000000000000);
 
   // Test that the result of an operation is a NaN at all when it should be.
   //
@@ -371,13 +688,20 @@ int main(void) {
   // encoding. We also use the same value as the input NaN in tests that have
   // one, so that even in EXPECT_EXACT_RESULTS mode these tests should pass,
   // because 0x7ff8000000000000 is still the exact expected NaN.
-  status |= test__muldf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff8000000000000);
-  status |= test__muldf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff8000000000000);
-  status |= test__muldf3(0x8000000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
-  status |= test__muldf3(0x8000000000000000, 0xfff0000000000000, 0x7ff8000000000000);
-  status |= test__muldf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
-  status |= test__muldf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
-  status |= test__muldf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x0000000000000000, 0x7ff8000000000000);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x8000000000000000, 0x7ff8000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0x7ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__muldf3(0x8000000000000000, 0xfff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
+  status |=
+      test__muldf3(0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000);
+  status |=
+      test__muldf3(0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000);
 
 #ifdef ARM_NAN_HANDLING
   // Tests specific to the NaN handling of Arm hardware, mimicked by
@@ -397,58 +721,110 @@ int main(void) {
   //
   //  - invalid operations not involving an input NaN return the quiet
   //    NaN with fewest bits set, 0x7ff8000000000000.
-  status |= test__muldf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
-  status |= test__muldf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
-  status |= test__muldf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
-  status |= test__muldf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
-  status |= test__muldf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
-  status |= test__muldf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
-  status |= test__muldf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
-  status |= test__muldf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
-  status |= test__muldf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
-  status |= test__muldf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
-  status |= test__muldf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
-  status |= test__muldf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
-  status |= test__muldf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
-  status |= test__muldf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
-  status |= test__muldf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
-  status |= test__muldf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
-  status |= test__muldf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
-  status |= test__muldf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
-  status |= test__muldf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
-  status |= test__muldf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
-  status |= test__muldf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
-  status |= test__muldf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
-  status |= test__muldf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
-  status |= test__muldf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
-  status |= test__muldf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
-  status |= test__muldf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
-  status |= test__muldf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
-  status |= test__muldf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
-  status |= test__muldf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
-  status |= test__muldf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
-  status |= test__muldf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
-  status |= test__muldf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
-  status |= test__muldf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
-  status |= test__muldf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
-  status |= test__muldf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
-  status |= test__muldf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
-  status |= test__muldf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
-  status |= test__muldf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
-  status |= test__muldf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
-  status |= test__muldf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
-  status |= test__muldf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
-  status |= test__muldf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
-  status |= test__muldf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
-  status |= test__muldf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
-  status |= test__muldf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
-  status |= test__muldf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
-  status |= test__muldf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
-  status |= test__muldf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
-  status |= test__muldf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
-  status |= test__muldf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
-  status |= test__muldf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
-  status |= test__muldf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
+  status |=
+      test__muldf3(0x0000000000000000, 0x7ff3758244400801, 0x7ffb758244400801);
+  status |=
+      test__muldf3(0x0000000000000000, 0x7fff44d3f65148af, 0x7fff44d3f65148af);
+  status |=
+      test__muldf3(0x0000000000000001, 0x7ff48607b4b37057, 0x7ffc8607b4b37057);
+  status |=
+      test__muldf3(0x0000000000000001, 0x7ff855f2d435b33d, 0x7ff855f2d435b33d);
+  status |=
+      test__muldf3(0x000fffffffffffff, 0x7ff169269a674e13, 0x7ff969269a674e13);
+  status |=
+      test__muldf3(0x000fffffffffffff, 0x7ffc80978b2ef0da, 0x7ffc80978b2ef0da);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x7ff3458ad034593d, 0x7ffb458ad034593d);
+  status |=
+      test__muldf3(0x3ff0000000000000, 0x7ffdd8bb98c9f13a, 0x7ffdd8bb98c9f13a);
+  status |=
+      test__muldf3(0x7fefffffffffffff, 0x7ff79a8b96250a98, 0x7fff9a8b96250a98);
+  status |=
+      test__muldf3(0x7fefffffffffffff, 0x7ffdcc675b63bb94, 0x7ffdcc675b63bb94);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x7ff018cfaf4d0fff, 0x7ff818cfaf4d0fff);
+  status |=
+      test__muldf3(0x7ff0000000000000, 0x7ff83ad1ab4dfd24, 0x7ff83ad1ab4dfd24);
+  status |=
+      test__muldf3(0x7ff48ce6c0cdd5ac, 0x0000000000000000, 0x7ffc8ce6c0cdd5ac);
+  status |=
+      test__muldf3(0x7ff08a34f3d5385b, 0x0000000000000001, 0x7ff88a34f3d5385b);
+  status |=
+      test__muldf3(0x7ff0a264c1c96281, 0x000fffffffffffff, 0x7ff8a264c1c96281);
+  status |=
+      test__muldf3(0x7ff77ce629e61f0e, 0x3ff0000000000000, 0x7fff7ce629e61f0e);
+  status |=
+      test__muldf3(0x7ff715e2d147fd76, 0x7fefffffffffffff, 0x7fff15e2d147fd76);
+  status |=
+      test__muldf3(0x7ff689a2031f1781, 0x7ff0000000000000, 0x7ffe89a2031f1781);
+  status |=
+      test__muldf3(0x7ff5dfb4a0c8cd05, 0x7ff11c1fe9793a33, 0x7ffddfb4a0c8cd05);
+  status |=
+      test__muldf3(0x7ff5826283ffb5d7, 0x7fff609b83884e81, 0x7ffd826283ffb5d7);
+  status |=
+      test__muldf3(0x7ff7cb03f2e61d42, 0x8000000000000000, 0x7fffcb03f2e61d42);
+  status |=
+      test__muldf3(0x7ff2adc8dfe72c96, 0x8000000000000001, 0x7ffaadc8dfe72c96);
+  status |=
+      test__muldf3(0x7ff4fc0bacc707f2, 0x800fffffffffffff, 0x7ffcfc0bacc707f2);
+  status |=
+      test__muldf3(0x7ff76248c8c9a619, 0xbff0000000000000, 0x7fff6248c8c9a619);
+  status |=
+      test__muldf3(0x7ff367972fce131b, 0xffefffffffffffff, 0x7ffb67972fce131b);
+  status |=
+      test__muldf3(0x7ff188f5ac284e92, 0xfff0000000000000, 0x7ff988f5ac284e92);
+  status |=
+      test__muldf3(0x7ffed4c22e4e569d, 0x0000000000000000, 0x7ffed4c22e4e569d);
+  status |=
+      test__muldf3(0x7ffe95105fa3f339, 0x0000000000000001, 0x7ffe95105fa3f339);
+  status |=
+      test__muldf3(0x7ffb8d33dbb9ecfb, 0x000fffffffffffff, 0x7ffb8d33dbb9ecfb);
+  status |=
+      test__muldf3(0x7ff874e41dc63e07, 0x3ff0000000000000, 0x7ff874e41dc63e07);
+  status |=
+      test__muldf3(0x7ffe27594515ecdf, 0x7fefffffffffffff, 0x7ffe27594515ecdf);
+  status |=
+      test__muldf3(0x7ffeac86d5c69bdf, 0x7ff0000000000000, 0x7ffeac86d5c69bdf);
+  status |=
+      test__muldf3(0x7ff97d657b99f76f, 0x7ff7e4149862a796, 0x7fffe4149862a796);
+  status |=
+      test__muldf3(0x7ffad17c6aa33fad, 0x7ffd898893ad4d28, 0x7ffad17c6aa33fad);
+  status |=
+      test__muldf3(0x7ff96e04e9c3d173, 0x8000000000000000, 0x7ff96e04e9c3d173);
+  status |=
+      test__muldf3(0x7ffec01ad8da3abb, 0x8000000000000001, 0x7ffec01ad8da3abb);
+  status |=
+      test__muldf3(0x7ffd1d565c495941, 0x800fffffffffffff, 0x7ffd1d565c495941);
+  status |=
+      test__muldf3(0x7ffe3d24f1e474a7, 0xbff0000000000000, 0x7ffe3d24f1e474a7);
+  status |=
+      test__muldf3(0x7ffc206f2bb8c8ce, 0xffefffffffffffff, 0x7ffc206f2bb8c8ce);
+  status |=
+      test__muldf3(0x7ff93efdecfb7d3b, 0xfff0000000000000, 0x7ff93efdecfb7d3b);
+  status |=
+      test__muldf3(0x8000000000000000, 0x7ff2ee725d143ac5, 0x7ffaee725d143ac5);
+  status |=
+      test__muldf3(0x8000000000000000, 0x7ffbba26e5c5fe98, 0x7ffbba26e5c5fe98);
+  status |=
+      test__muldf3(0x8000000000000001, 0x7ff7818a1cd26df9, 0x7fff818a1cd26df9);
+  status |=
+      test__muldf3(0x8000000000000001, 0x7ffaee6cc63b5292, 0x7ffaee6cc63b5292);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0x7ff401096edaf79d, 0x7ffc01096edaf79d);
+  status |=
+      test__muldf3(0x800fffffffffffff, 0x7ffbf1778c7a2e59, 0x7ffbf1778c7a2e59);
+  status |=
+      test__muldf3(0xbff0000000000000, 0x7ff2e8fb0201c496, 0x7ffae8fb0201c496);
+  status |=
+      test__muldf3(0xbff0000000000000, 0x7ffcb6a5adb2e154, 0x7ffcb6a5adb2e154);
+  status |=
+      test__muldf3(0xffefffffffffffff, 0x7ff1ea1bfc15d71d, 0x7ff9ea1bfc15d71d);
+  status |=
+      test__muldf3(0xffefffffffffffff, 0x7ffae0766e21efc0, 0x7ffae0766e21efc0);
+  status |=
+      test__muldf3(0xfff0000000000000, 0x7ff3b364cffbdfe6, 0x7ffbb364cffbdfe6);
+  status |=
+      test__muldf3(0xfff0000000000000, 0x7ffd0d3223334ae3, 0x7ffd0d3223334ae3);
 
 #endif // ARM_NAN_HANDLING
 

>From 5b149ffcda2495c04f8cf86e31e30892a277e6ae Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:21:17 +0000
Subject: [PATCH 15/33] clang-format

---
 compiler-rt/lib/builtins/arm/dcmp.h            |  2 ++
 compiler-rt/lib/builtins/arm/thumb1/dcmp.h     |  2 ++
 .../test/builtins/Unit/comparedf2new_test.c    | 18 ++++++++----------
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/compiler-rt/lib/builtins/arm/dcmp.h b/compiler-rt/lib/builtins/arm/dcmp.h
index c9fd0ef324365..394ba34ca915e 100644
--- a/compiler-rt/lib/builtins/arm/dcmp.h
+++ b/compiler-rt/lib/builtins/arm/dcmp.h
@@ -55,6 +55,8 @@
 //  - if the 11 exponent bits of the output are not all 1, then there are
 //    definitely no NaNs, so a fast path can handle most non-NaN cases.
 
+// clang-format off
+
   // First diverge control for the negative-numbers case.
   orrs    r12, op0h, op1h
   bmi     LOCAL_LABEL(negative)         // high bit set => at least one negative input
diff --git a/compiler-rt/lib/builtins/arm/thumb1/dcmp.h b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
index fc45b5d469120..4fa2088c060a0 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
+++ b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
@@ -49,6 +49,8 @@
 //  - if the 11 exponent bits of the output are not all 1, then there are
 //    definitely no NaNs, so a fast path can handle most non-NaN cases.
 
+// clang-format off
+
   push    {r4,r5,r6,lr}
 
   // Set up the constant 1 << 20 in a register, which we'll need on all
diff --git a/compiler-rt/test/builtins/Unit/comparedf2new_test.c b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
index f78a1a6aaa02d..8a91f90510971 100644
--- a/compiler-rt/test/builtins/Unit/comparedf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
@@ -20,21 +20,19 @@ COMPILER_RT_ABI int __ltdf2(double, double);
 COMPILER_RT_ABI int __cmpdf2(double, double);
 COMPILER_RT_ABI int __unorddf2(double, double);
 
-enum Result {
-  RESULT_LT,
-  RESULT_GT,
-  RESULT_EQ,
-  RESULT_UN
-};
+enum Result { RESULT_LT, RESULT_GT, RESULT_EQ, RESULT_UN };
 
-int expect(int line, uint64_t a_rep, uint64_t b_rep, const char *name, int result, int ok, const char *expected) {
+int expect(int line, uint64_t a_rep, uint64_t b_rep, const char *name,
+           int result, int ok, const char *expected) {
   if (!ok)
-    printf("error at line %d: %s(%016" PRIx64 ", %016" PRIx64 ") = %d, expected %s\n",
+    printf("error at line %d: %s(%016" PRIx64 ", %016" PRIx64
+           ") = %d, expected %s\n",
            line, name, a_rep, b_rep, result, expected);
   return !ok;
 }
 
-int test__comparedf2(int line, uint64_t a_rep, uint64_t b_rep, enum Result result) {
+int test__comparedf2(int line, uint64_t a_rep, uint64_t b_rep,
+                     enum Result result) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
 
   int eq = __eqdf2(a, b);
@@ -94,7 +92,7 @@ int test__comparedf2(int line, uint64_t a_rep, uint64_t b_rep, enum Result resul
   return ret;
 }
 
-#define test__comparedf2(a,b,x) test__comparedf2(__LINE__,a,b,x)
+#define test__comparedf2(a, b, x) test__comparedf2(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;

>From 54fb81b899d4012d48b9995a7275565601f71bba Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:10:13 +0000
Subject: [PATCH 16/33] Update to use set_special_properties

---
 compiler-rt/lib/builtins/CMakeLists.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index facfe62416daa..2c71400f3c56c 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -526,8 +526,8 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP)
     arm/funder.c
     ${thumb1_base_SOURCES}
   )
-  set_property(SOURCE arm/thumb1/cmpdf2.S PROPERTY crt_supersedes comparedf2.c)
-  set_property(SOURCE arm/thumb1/cmpdf2.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY crt_provides comparedf2)
+  set_special_properties(arm/thumb1/cmpdf2.S
+    SUPERSEDES comparedf2.c PROVIDES comparedf2)
 endif()
 
 set(arm_EABI_RT_SOURCES

>From beea5fc71745c540bffbbe3141c93ca7aa4a772a Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:23:56 +0000
Subject: [PATCH 17/33] clang-format

---
 compiler-rt/lib/builtins/arm/fcmp.h            |  2 ++
 compiler-rt/lib/builtins/arm/thumb1/fcmp.h     |  2 ++
 .../test/builtins/Unit/comparesf2new_test.c    | 18 ++++++++----------
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/compiler-rt/lib/builtins/arm/fcmp.h b/compiler-rt/lib/builtins/arm/fcmp.h
index 23bdd73a10c5b..4860479f45158 100644
--- a/compiler-rt/lib/builtins/arm/fcmp.h
+++ b/compiler-rt/lib/builtins/arm/fcmp.h
@@ -48,6 +48,8 @@
 //  - if the 8 exponent bits of the output are not all 1, then there are
 //    definitely no NaNs, so a fast path can handle most non-NaN cases.
 
+// clang-format off
+
   // First diverge control for the negative-numbers case.
   orrs    r12, op0, op1
   bmi     LOCAL_LABEL(negative)         // high bit set => at least one negative input
diff --git a/compiler-rt/lib/builtins/arm/thumb1/fcmp.h b/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
index bcfe928407e3c..0f0f46b158aad 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
+++ b/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
@@ -48,6 +48,8 @@
 //  - if the 8 exponent bits of the output are not all 1, then there are
 //    definitely no NaNs, so a fast path can handle most non-NaN cases.
 
+// clang-format off
+
   // Set up the constant 1 << 23 in a register, which we'll need on all
   // branches.
   movs    r3, #1
diff --git a/compiler-rt/test/builtins/Unit/comparesf2new_test.c b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
index 5c8be88354618..02fac8ba2a3bd 100644
--- a/compiler-rt/test/builtins/Unit/comparesf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
@@ -20,21 +20,19 @@ COMPILER_RT_ABI int __ltsf2(float, float);
 COMPILER_RT_ABI int __cmpsf2(float, float);
 COMPILER_RT_ABI int __unordsf2(float, float);
 
-enum Result {
-  RESULT_LT,
-  RESULT_GT,
-  RESULT_EQ,
-  RESULT_UN
-};
+enum Result { RESULT_LT, RESULT_GT, RESULT_EQ, RESULT_UN };
 
-int expect(int line, uint32_t a_rep, uint32_t b_rep, const char *name, int result, int ok, const char *expected) {
+int expect(int line, uint32_t a_rep, uint32_t b_rep, const char *name,
+           int result, int ok, const char *expected) {
   if (!ok)
-    printf("error at line %d: %s(%08" PRIx32 ", %08" PRIx32 ") = %d, expected %s\n",
+    printf("error at line %d: %s(%08" PRIx32 ", %08" PRIx32
+           ") = %d, expected %s\n",
            line, name, a_rep, b_rep, result, expected);
   return !ok;
 }
 
-int test__comparesf2(int line, uint32_t a_rep, uint32_t b_rep, enum Result result) {
+int test__comparesf2(int line, uint32_t a_rep, uint32_t b_rep,
+                     enum Result result) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
 
   int eq = __eqsf2(a, b);
@@ -94,7 +92,7 @@ int test__comparesf2(int line, uint32_t a_rep, uint32_t b_rep, enum Result resul
   return ret;
 }
 
-#define test__comparesf2(a,b,x) test__comparesf2(__LINE__,a,b,x)
+#define test__comparesf2(a, b, x) test__comparesf2(__LINE__, a, b, x)
 
 int main(void) {
   int status = 0;

>From c17cb0053a15b211c243fec803702990bb8ddcc6 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:10:26 +0000
Subject: [PATCH 18/33] Update to use set_special_properties

---
 compiler-rt/lib/builtins/CMakeLists.txt | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index ab741b0600973..a245cbd7e39b9 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -534,9 +534,10 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP)
   )
   set_special_properties(arm/thumb1/cmpdf2.S
     SUPERSEDES comparedf2.c PROVIDES comparedf2)
-  set_property(SOURCE arm/thumb1/cmpsf2.S PROPERTY crt_supersedes comparesf2.S)
-  # We don't need to set 'crt_provides' for cmpsf2.S, because the
-  # superseded comparesf2.S will already have enabled the comparesf2 tests.
+  set_special_properties(arm/thumb1/cmpsf2.S
+    SUPERSEDES comparesf2.S)
+  # We don't need to set PROVIDES for cmpsf2.S, because the superseded
+  # comparesf2.S will already have enabled the comparesf2 tests.
 endif()
 
 set(arm_EABI_RT_SOURCES

>From 3f41560935717d7097f511a8c6660d3b595656eb Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:25:18 +0000
Subject: [PATCH 19/33] clang-format

---
 compiler-rt/test/builtins/Unit/extendsfdf2new_test.c | 2 +-
 compiler-rt/test/builtins/Unit/truncdfsf2new_test.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c b/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
index 04446488f73bf..dc7801c029c06 100644
--- a/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
@@ -41,7 +41,7 @@ int test__extendsfdf2(int line, uint32_t a_rep, uint64_t expected_rep) {
   return ret;
 }
 
-#define test__extendsfdf2(a,x) test__extendsfdf2(__LINE__,a,x)
+#define test__extendsfdf2(a, x) test__extendsfdf2(__LINE__, a, x)
 
 int main(void) {
   int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c b/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
index 0542f97643618..6cc4e16a7163a 100644
--- a/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
@@ -41,7 +41,7 @@ int test__truncdfsf2(int line, uint64_t a_rep, uint32_t expected_rep) {
   return ret;
 }
 
-#define test__truncdfsf2(a,x) test__truncdfsf2(__LINE__,a,x)
+#define test__truncdfsf2(a, x) test__truncdfsf2(__LINE__, a, x)
 
 int main(void) {
   int status = 0;

>From 9bac3911b06518bd2825ffca3b4beb6756bee3f7 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Fri, 20 Feb 2026 17:08:04 +0000
Subject: [PATCH 20/33] Move line number to end of function arguments

---
 compiler-rt/test/builtins/Unit/divsf3_test.c | 6 +++---
 compiler-rt/test/builtins/Unit/mulsf3_test.c | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/divsf3_test.c b/compiler-rt/test/builtins/Unit/divsf3_test.c
index a2d823fec840b..8aed069ec7428 100644
--- a/compiler-rt/test/builtins/Unit/divsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/divsf3_test.c
@@ -24,8 +24,8 @@
 // Returns: a / b
 COMPILER_RT_ABI float __divsf3(float a, float b);
 
-int test__divsf3(int line, uint32_t a_rep, uint32_t b_rep,
-                 uint32_t expected_rep) {
+int test__divsf3(uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep,
+                 int line) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
   float x = __divsf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -42,7 +42,7 @@ int test__divsf3(int line, uint32_t a_rep, uint32_t b_rep,
   return ret;
 }
 
-#define test__divsf3(a, b, x) test__divsf3(__LINE__, a, b, x)
+#define test__divsf3(a, b, x) test__divsf3(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/mulsf3_test.c b/compiler-rt/test/builtins/Unit/mulsf3_test.c
index 42bee8a60ff58..be1ce3c107874 100644
--- a/compiler-rt/test/builtins/Unit/mulsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/mulsf3_test.c
@@ -24,8 +24,8 @@
 // Returns: a * b
 COMPILER_RT_ABI float __mulsf3(float a, float b);
 
-int test__mulsf3(int line, uint32_t a_rep, uint32_t b_rep,
-                 uint32_t expected_rep) {
+int test__mulsf3(uint32_t a_rep, uint32_t b_rep, uint32_t expected_rep,
+                 int line) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
   float x = __mulsf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -42,7 +42,7 @@ int test__mulsf3(int line, uint32_t a_rep, uint32_t b_rep,
   return ret;
 }
 
-#define test__mulsf3(a, b, x) test__mulsf3(__LINE__, a, b, x)
+#define test__mulsf3(a, b, x) test__mulsf3(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;

>From ce58e156988d287f10b2663bfe16f27d2cc77f70 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Mon, 23 Feb 2026 16:52:33 +0000
Subject: [PATCH 21/33] Simplify the #if in each unit test

Each test file now just checks `#if COMPILER_RT_ARM_OPTIMIZED_FP` to
decide whether to enable the extra checking, or if it's a function
implemented in Thumb-1 as well, `COMPILER_RT_ARM_OPTIMIZED_FP_THUMB1`.

Conveniently, one of the tests here tests each macro.
---
 compiler-rt/test/builtins/CMakeLists.txt     | 16 ++++++++++++++--
 compiler-rt/test/builtins/Unit/divsf3_test.c |  2 +-
 compiler-rt/test/builtins/Unit/mulsf3_test.c |  2 +-
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/compiler-rt/test/builtins/CMakeLists.txt b/compiler-rt/test/builtins/CMakeLists.txt
index 1d4e69602ee9f..c80208c6db73f 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -73,8 +73,20 @@ foreach(arch ${BUILTIN_TEST_ARCH})
     endif()
   endif()
 
-  if(COMPILER_RT_ARM_OPTIMIZED_FP)
-    list(APPEND BUILTINS_TEST_TARGET_CFLAGS -DCOMPILER_RT_ARM_OPTIMIZED_FP)
+  if(COMPILER_RT_ARM_OPTIMIZED_FP AND arch MATCHES "arm")
+    if(arch MATCHES "armv6m|armv8m\.base")
+      # Set a compile-time definition promising that the Thumb-1 optimized FP
+      # implementations are present in this library, and therefore, can be
+      # expected to behave in the way expected by the extra-strict tests of NaN
+      # and error handling.
+      list(APPEND BUILTINS_TEST_TARGET_CFLAGS -DCOMPILER_RT_ARM_OPTIMIZED_FP_THUMB1)
+    else()
+      # For AArch32 targets that are not just Thumb-1, set a more general flag
+      # _and_ the previous one too, so that tests can check
+      # COMPILER_RT_ARM_OPTIMIZED_FP_THUMB1 by itself to test for an optimized
+      # function available on all AArch32 platforms.
+      list(APPEND BUILTINS_TEST_TARGET_CFLAGS -DCOMPILER_RT_ARM_OPTIMIZED_FP)
+    endif()
     string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}")
   endif()
 
diff --git a/compiler-rt/test/builtins/Unit/divsf3_test.c b/compiler-rt/test/builtins/Unit/divsf3_test.c
index 8aed069ec7428..4815a9efb5dae 100644
--- a/compiler-rt/test/builtins/Unit/divsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/divsf3_test.c
@@ -16,7 +16,7 @@
 // 0x7fc00000. For the Arm optimized FP implementation, which commits to a more
 // detailed handling of NaNs, we tighten up the check and include some extra
 // test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
diff --git a/compiler-rt/test/builtins/Unit/mulsf3_test.c b/compiler-rt/test/builtins/Unit/mulsf3_test.c
index be1ce3c107874..99a27fd10c54f 100644
--- a/compiler-rt/test/builtins/Unit/mulsf3_test.c
+++ b/compiler-rt/test/builtins/Unit/mulsf3_test.c
@@ -16,7 +16,7 @@
 // 0x7fc00000. For the Arm optimized FP implementation, which commits to a more
 // detailed handling of NaNs, we tighten up the check and include some extra
 // test cases specific to that NaN policy.
-#if (__arm__ || __thumb__) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP_THUMB1
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif

>From 438039a2e5c39c936365552665f4f2c4f4266244 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 24 Feb 2026 16:25:44 +0000
Subject: [PATCH 22/33] Update tests to match #179918

---
 compiler-rt/test/builtins/Unit/adddf3new_test.c | 8 ++++----
 compiler-rt/test/builtins/Unit/subdf3new_test.c | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/adddf3new_test.c b/compiler-rt/test/builtins/Unit/adddf3new_test.c
index f7c5edf6c4d9d..c4913144d33d0 100644
--- a/compiler-rt/test/builtins/Unit/adddf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/adddf3new_test.c
@@ -16,7 +16,7 @@
 // 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
 // to a more detailed handling of NaNs, we tighten up the check and include
 // some extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
@@ -24,8 +24,8 @@
 // Returns: a + b
 COMPILER_RT_ABI double __adddf3(double a, double b);
 
-int test__adddf3(int line, uint64_t a_rep, uint64_t b_rep,
-                 uint64_t expected_rep) {
+int test__adddf3(uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep,
+                 int line) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __adddf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -42,7 +42,7 @@ int test__adddf3(int line, uint64_t a_rep, uint64_t b_rep,
   return ret;
 }
 
-#define test__adddf3(a, b, x) (test__adddf3)(__LINE__, a, b, x)
+#define test__adddf3(a, b, x) (test__adddf3)(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/subdf3new_test.c b/compiler-rt/test/builtins/Unit/subdf3new_test.c
index 16132ea920a88..dd72fbb8b8f56 100644
--- a/compiler-rt/test/builtins/Unit/subdf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/subdf3new_test.c
@@ -16,7 +16,7 @@
 // 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
 // to a more detailed handling of NaNs, we tighten up the check and include
 // some extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
@@ -24,8 +24,8 @@
 // Returns: a - b
 COMPILER_RT_ABI double __subdf3(double a, double b);
 
-int test__subdf3(int line, uint64_t a_rep, uint64_t b_rep,
-                 uint64_t expected_rep) {
+int test__subdf3(uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep,
+                 int line) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __subdf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -42,7 +42,7 @@ int test__subdf3(int line, uint64_t a_rep, uint64_t b_rep,
   return ret;
 }
 
-#define test__subdf3(a, b, x) test__subdf3(__LINE__, a, b, x)
+#define test__subdf3(a, b, x) test__subdf3(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;

>From 46b08f4b409492dca56b16760aa90f2e297ccbb3 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 24 Feb 2026 16:28:58 +0000
Subject: [PATCH 23/33] Update tests to match #179918

---
 compiler-rt/test/builtins/Unit/divdf3new_test.c | 8 ++++----
 compiler-rt/test/builtins/Unit/muldf3new_test.c | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/divdf3new_test.c b/compiler-rt/test/builtins/Unit/divdf3new_test.c
index ca33e00a8741d..866c7cb08e519 100644
--- a/compiler-rt/test/builtins/Unit/divdf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/divdf3new_test.c
@@ -16,7 +16,7 @@
 // 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
 // to a more detailed handling of NaNs, we tighten up the check and include
 // some extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
@@ -24,8 +24,8 @@
 // Returns: a / b
 COMPILER_RT_ABI double __divdf3(double a, double b);
 
-int test__divdf3(int line, uint64_t a_rep, uint64_t b_rep,
-                 uint64_t expected_rep) {
+int test__divdf3(uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep,
+                 int line) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __divdf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -42,7 +42,7 @@ int test__divdf3(int line, uint64_t a_rep, uint64_t b_rep,
   return ret;
 }
 
-#define test__divdf3(a, b, x) test__divdf3(__LINE__, a, b, x)
+#define test__divdf3(a, b, x) test__divdf3(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/muldf3new_test.c b/compiler-rt/test/builtins/Unit/muldf3new_test.c
index c2e39254fbc46..b8a5c64460696 100644
--- a/compiler-rt/test/builtins/Unit/muldf3new_test.c
+++ b/compiler-rt/test/builtins/Unit/muldf3new_test.c
@@ -16,7 +16,7 @@
 // 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
 // to a more detailed handling of NaNs, we tighten up the check and include
 // some extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
@@ -24,8 +24,8 @@
 // Returns: a * b
 COMPILER_RT_ABI double __muldf3(double a, double b);
 
-int test__muldf3(int line, uint64_t a_rep, uint64_t b_rep,
-                 uint64_t expected_rep) {
+int test__muldf3(uint64_t a_rep, uint64_t b_rep, uint64_t expected_rep,
+                 int line) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
   double x = __muldf3(a, b);
 #ifdef EXPECT_EXACT_RESULTS
@@ -42,7 +42,7 @@ int test__muldf3(int line, uint64_t a_rep, uint64_t b_rep,
   return ret;
 }
 
-#define test__muldf3(a, b, x) test__muldf3(__LINE__, a, b, x)
+#define test__muldf3(a, b, x) test__muldf3(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;

>From 8d45879bacb55bf28110beed3f22887c44f8075b Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 24 Feb 2026 16:37:03 +0000
Subject: [PATCH 24/33] Update tests to match #179918

---
 .../test/builtins/Unit/comparedf2new_test.c   | 74 +++++++++----------
 1 file changed, 37 insertions(+), 37 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/comparedf2new_test.c b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
index 8a91f90510971..1a17c435987d2 100644
--- a/compiler-rt/test/builtins/Unit/comparedf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
@@ -22,8 +22,8 @@ COMPILER_RT_ABI int __unorddf2(double, double);
 
 enum Result { RESULT_LT, RESULT_GT, RESULT_EQ, RESULT_UN };
 
-int expect(int line, uint64_t a_rep, uint64_t b_rep, const char *name,
-           int result, int ok, const char *expected) {
+int expect(uint64_t a_rep, uint64_t b_rep, const char *name, int result, int ok,
+           const char *expected, int line) {
   if (!ok)
     printf("error at line %d: %s(%016" PRIx64 ", %016" PRIx64
            ") = %d, expected %s\n",
@@ -31,8 +31,8 @@ int expect(int line, uint64_t a_rep, uint64_t b_rep, const char *name,
   return !ok;
 }
 
-int test__comparedf2(int line, uint64_t a_rep, uint64_t b_rep,
-                     enum Result result) {
+int test__comparedf2(uint64_t a_rep, uint64_t b_rep, enum Result result,
+                     int line) {
   double a = fromRep64(a_rep), b = fromRep64(b_rep);
 
   int eq = __eqdf2(a, b);
@@ -48,51 +48,51 @@ int test__comparedf2(int line, uint64_t a_rep, uint64_t b_rep,
 
   switch (result) {
   case RESULT_LT:
-    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0");
-    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt < 0, "< 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == -1, "== -1");
-    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0");
+    ret |= expect(a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0", line);
+    ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt < 0, "< 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == -1, "== -1", line);
+    ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_GT:
-    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt > 0, "> 0");
-    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le > 0, "> 0");
-    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1");
-    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0");
+    ret |= expect(a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt > 0, "> 0", line);
+    ret |= expect(a_rep, b_rep, "__ledf2", le, le > 0, "> 0", line);
+    ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1", line);
+    ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_EQ:
-    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq == 0, "== 0");
-    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne == 0, "== 0");
-    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 0, "== 0");
-    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0");
+    ret |= expect(a_rep, b_rep, "__eqdf2", eq, eq == 0, "== 0", line);
+    ret |= expect(a_rep, b_rep, "__nedf2", ne, ne == 0, "== 0", line);
+    ret |= expect(a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == 0, "== 0", line);
+    ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_UN:
-    ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0");
-    ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__ledf2", le, le > 0, "> 0");
-    ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1");
-    ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 1, "== 1");
+    ret |= expect(a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0", line);
+    ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__ledf2", le, le > 0, "> 0", line);
+    ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1", line);
+    ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 1, "== 1", line);
     break;
   }
 
   return ret;
 }
 
-#define test__comparedf2(a, b, x) test__comparedf2(__LINE__, a, b, x)
+#define test__comparedf2(a, b, x) test__comparedf2(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;

>From df5ed236cc931910e18735f4d0902eabcb22ec31 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 24 Feb 2026 16:40:32 +0000
Subject: [PATCH 25/33] Update tests to match #179918

---
 .../test/builtins/Unit/comparesf2new_test.c   | 74 +++++++++----------
 1 file changed, 37 insertions(+), 37 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/comparesf2new_test.c b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
index 02fac8ba2a3bd..5bed764b0957a 100644
--- a/compiler-rt/test/builtins/Unit/comparesf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
@@ -22,8 +22,8 @@ COMPILER_RT_ABI int __unordsf2(float, float);
 
 enum Result { RESULT_LT, RESULT_GT, RESULT_EQ, RESULT_UN };
 
-int expect(int line, uint32_t a_rep, uint32_t b_rep, const char *name,
-           int result, int ok, const char *expected) {
+int expect(uint32_t a_rep, uint32_t b_rep, const char *name, int result, int ok,
+           const char *expected, int line) {
   if (!ok)
     printf("error at line %d: %s(%08" PRIx32 ", %08" PRIx32
            ") = %d, expected %s\n",
@@ -31,8 +31,8 @@ int expect(int line, uint32_t a_rep, uint32_t b_rep, const char *name,
   return !ok;
 }
 
-int test__comparesf2(int line, uint32_t a_rep, uint32_t b_rep,
-                     enum Result result) {
+int test__comparesf2(uint32_t a_rep, uint32_t b_rep, enum Result result,
+                     int line) {
   float a = fromRep32(a_rep), b = fromRep32(b_rep);
 
   int eq = __eqsf2(a, b);
@@ -48,51 +48,51 @@ int test__comparesf2(int line, uint32_t a_rep, uint32_t b_rep,
 
   switch (result) {
   case RESULT_LT:
-    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge < 0, "< 0");
-    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt < 0, "< 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == -1, "== -1");
-    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0");
+    ret |= expect(a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__gesf2", ge, ge < 0, "< 0", line);
+    ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt < 0, "< 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == -1, "== -1", line);
+    ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_GT:
-    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt > 0, "> 0");
-    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le > 0, "> 0");
-    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1");
-    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0");
+    ret |= expect(a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__gesf2", ge, ge >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt > 0, "> 0", line);
+    ret |= expect(a_rep, b_rep, "__lesf2", le, le > 0, "> 0", line);
+    ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1", line);
+    ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_EQ:
-    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq == 0, "== 0");
-    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne == 0, "== 0");
-    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == 0, "== 0");
-    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0");
+    ret |= expect(a_rep, b_rep, "__eqsf2", eq, eq == 0, "== 0", line);
+    ret |= expect(a_rep, b_rep, "__nesf2", ne, ne == 0, "== 0", line);
+    ret |= expect(a_rep, b_rep, "__gesf2", ge, ge >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == 0, "== 0", line);
+    ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_UN:
-    ret |= expect(line, a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0");
-    ret |= expect(line, a_rep, b_rep, "__gesf2", ge, ge < 0, "< 0");
-    ret |= expect(line, a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0");
-    ret |= expect(line, a_rep, b_rep, "__lesf2", le, le > 0, "> 0");
-    ret |= expect(line, a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0");
-    ret |= expect(line, a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1");
-    ret |= expect(line, a_rep, b_rep, "__unordsf2", unord, unord == 1, "== 1");
+    ret |= expect(a_rep, b_rep, "__eqsf2", eq, eq != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__nesf2", ne, ne != 0, "!= 0", line);
+    ret |= expect(a_rep, b_rep, "__gesf2", ge, ge < 0, "< 0", line);
+    ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0", line);
+    ret |= expect(a_rep, b_rep, "__lesf2", le, le > 0, "> 0", line);
+    ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0", line);
+    ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1", line);
+    ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 1, "== 1", line);
     break;
   }
 
   return ret;
 }
 
-#define test__comparesf2(a, b, x) test__comparesf2(__LINE__, a, b, x)
+#define test__comparesf2(a, b, x) test__comparesf2(a, b, x, __LINE__)
 
 int main(void) {
   int status = 0;

>From 612766c7406b2c71e8ddf106157db7c5c5a4b39a Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 24 Feb 2026 16:42:19 +0000
Subject: [PATCH 26/33] Update tests to match #179918

---
 compiler-rt/test/builtins/Unit/extendsfdf2new_test.c | 6 +++---
 compiler-rt/test/builtins/Unit/truncdfsf2new_test.c  | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c b/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
index dc7801c029c06..d5819d9ef476c 100644
--- a/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/extendsfdf2new_test.c
@@ -16,7 +16,7 @@
 // 0x7ff8000000000000. For the Arm optimized FP implementation, which commits
 // to a more detailed handling of NaNs, we tighten up the check and include
 // some extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
@@ -24,7 +24,7 @@
 // Returns: a converted from float to double
 COMPILER_RT_ABI double __extendsfdf2(float a);
 
-int test__extendsfdf2(int line, uint32_t a_rep, uint64_t expected_rep) {
+int test__extendsfdf2(uint32_t a_rep, uint64_t expected_rep, int line) {
   float a = fromRep32(a_rep);
   double x = __extendsfdf2(a);
 #ifdef EXPECT_EXACT_RESULTS
@@ -41,7 +41,7 @@ int test__extendsfdf2(int line, uint32_t a_rep, uint64_t expected_rep) {
   return ret;
 }
 
-#define test__extendsfdf2(a, x) test__extendsfdf2(__LINE__, a, x)
+#define test__extendsfdf2(a, x) test__extendsfdf2(a, x, __LINE__)
 
 int main(void) {
   int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c b/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
index 6cc4e16a7163a..8b9434765012f 100644
--- a/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/truncdfsf2new_test.c
@@ -16,7 +16,7 @@
 // 0x7fc00000. For the Arm optimized FP implementation, which commits to a more
 // detailed handling of NaNs, we tighten up the check and include some extra
 // test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
 #  define EXPECT_EXACT_RESULTS
 #  define ARM_NAN_HANDLING
 #endif
@@ -24,7 +24,7 @@
 // Returns: a converted from double to float
 COMPILER_RT_ABI float __truncdfsf2(double a);
 
-int test__truncdfsf2(int line, uint64_t a_rep, uint32_t expected_rep) {
+int test__truncdfsf2(uint64_t a_rep, uint32_t expected_rep, int line) {
   double a = fromRep64(a_rep);
   float x = __truncdfsf2(a);
 #ifdef EXPECT_EXACT_RESULTS
@@ -41,7 +41,7 @@ int test__truncdfsf2(int line, uint64_t a_rep, uint32_t expected_rep) {
   return ret;
 }
 
-#define test__truncdfsf2(a, x) test__truncdfsf2(__LINE__, a, x)
+#define test__truncdfsf2(a, x) test__truncdfsf2(a, x, __LINE__)
 
 int main(void) {
   int status = 0;

>From ab2c26dd2701f61cd2b98c3fe30727c4a6f3454c Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Wed, 25 Feb 2026 15:02:15 +0000
Subject: [PATCH 27/33] Rename Thumb1 SetResultRegister to ReturnResult

Also remove the return instructions following it in the main macro,
which aren't needed, since it does the returning itself.
---
 compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S |  2 +-
 compiler-rt/lib/builtins/arm/thumb1/dcmp.h   | 33 ++++++++------------
 compiler-rt/lib/builtins/arm/thumb1/gedf2.S  |  2 +-
 3 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S b/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S
index d6d37198b5145..fe61fe552c400 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S
+++ b/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S
@@ -26,7 +26,7 @@ op0h .req xh
 op0l .req xl
 op1h .req yh
 op1l .req yl
-.macro SetReturnRegister
+.macro ReturnResult
   bhi 0f
   blo 1f
   movs r0, #0
diff --git a/compiler-rt/lib/builtins/arm/thumb1/dcmp.h b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
index 4fa2088c060a0..fb96aa51de027 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
+++ b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h
@@ -26,12 +26,13 @@
 //  - But a function with the reversed semantics of __aeabi_cdrcmple wil define
 //    them the other way round.
 //
-// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up
-// an appropriate return value in r0, for the cases that do *not* involve NaN.
+// ReturnResult: an assembly macro that looks at the PSR flags, sets up an
+// appropriate return value in r0, and returns it, for the cases that do *not*
+// involve NaN.
 //  - On entry to this macro, the condition codes LO, EQ and HI indicate that
 //    op0 < op1, op0 == op1 or op0 > op1 respectively.
-//  - For functions that return a result in the flags, this macro can be empty,
-//    because those are the correct flags to return anyway.
+//  - For functions that return a result in the flags, this macro can just
+//    return immediately, because those are the correct flags to return anyway.
 //  - Functions that return a boolean in r0 should set it up by checking the
 //    flags.
 //
@@ -73,12 +74,10 @@
   // were no NaNs. So we just compare op0 and op1 as unsigned integers.
   cmp     op0h, op1h
   beq     LOCAL_LABEL(low_word_positive)
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
 LOCAL_LABEL(low_word_positive):
   cmp     op0l, op1l
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
 
 LOCAL_LABEL(NaNInf_check_positive):
   // Second tier for positive numbers. We come here if both inputs are
@@ -107,8 +106,7 @@ LOCAL_LABEL(NaNInf_check_positive):
   // must have a set bit not present in the other). So we only need to compare
   // the high words.
   cmp     op0h, op1h
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
 
 LOCAL_LABEL(NaN_check_positive):
   // Third tier for positive numbers. Here we know that at least one of the
@@ -140,8 +138,7 @@ LOCAL_LABEL(NaN_check_positive):
   // again. (The fact that we've just shifted them left doesn't make a
   // difference.)
   cmp     op0h, op1h
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
 
 LOCAL_LABEL(negative):
   // We come here if at least one operand is negative. We haven't checked for
@@ -183,12 +180,10 @@ LOCAL_LABEL(negative):
   // reverse sense.
   cmp     op1h, op0h
   beq     LOCAL_LABEL(low_word_negative)
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
 LOCAL_LABEL(low_word_negative):
   cmp     op1l, op0l
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
 
 LOCAL_LABEL(equal):
   // We come here if we know the inputs are supposed to compare equal. Set up
@@ -197,8 +192,7 @@ LOCAL_LABEL(equal):
   // (We might have come here via a BEQ, in which case we know Z=1, but we also
   // need C=1 for our caller to get _all_ the right flags.)
   cmp     r0, r0             // compare a register with itself
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
 
 LOCAL_LABEL(NaNInf_check_negative):
   // Second tier for negative numbers: we know the OR of the exponents is 0xFF,
@@ -234,5 +228,4 @@ LOCAL_LABEL(NaNInf_check_negative):
   // exponent fields was 0x7FF, which means the exponents can't both have been
   // zero! So we can _just_ do the reversed CMP and finish.
   cmp     op1h, op0h
-  SetReturnRegister
-  pop     {r4,r5,r6,pc}
+  ReturnResult
diff --git a/compiler-rt/lib/builtins/arm/thumb1/gedf2.S b/compiler-rt/lib/builtins/arm/thumb1/gedf2.S
index 3486403761bd5..067bff4c6429f 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/gedf2.S
+++ b/compiler-rt/lib/builtins/arm/thumb1/gedf2.S
@@ -27,7 +27,7 @@ op0h .req xh
 op0l .req xl
 op1h .req yh
 op1l .req yl
-.macro SetReturnRegister
+.macro ReturnResult
   bhi 0f
   blo 1f
   movs r0, #0

>From 8bbb24e73bfd33c3e20ed5c98eefe2c4eb390ea2 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Wed, 25 Feb 2026 14:44:57 +0000
Subject: [PATCH 28/33] Rename Thumb1 SetResultRegister to ReturnResult

Also remove the return instructions following it in the main macro,
which aren't needed, since it does the returning itself.
---
 compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S |  2 +-
 compiler-rt/lib/builtins/arm/thumb1/fcmp.h   | 24 ++++++++------------
 compiler-rt/lib/builtins/arm/thumb1/gesf2.S  |  2 +-
 3 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S b/compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S
index c8611d1147366..e4a5e08c35181 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S
+++ b/compiler-rt/lib/builtins/arm/thumb1/cmpsf2.S
@@ -23,7 +23,7 @@
 
 op0 .req r0
 op1 .req r1
-.macro SetReturnRegister
+.macro ReturnResult
   bhi 0f
   blo 1f
   movs r0, #0
diff --git a/compiler-rt/lib/builtins/arm/thumb1/fcmp.h b/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
index 0f0f46b158aad..7d85abae05129 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
+++ b/compiler-rt/lib/builtins/arm/thumb1/fcmp.h
@@ -25,12 +25,13 @@
 //  - But a function with the reversed semantics of __aeabi_cfrcmple wil define
 //    them the other way round.
 //
-// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up
-// an appropriate return value in r0, for the cases that do *not* involve NaN.
+// ReturnResult: an assembly macro that looks at the PSR flags, sets up an
+// appropriate return value in r0, and returns it, for the cases that do *not*
+// involve NaN.
 //  - On entry to this macro, the condition codes LO, EQ and HI indicate that
 //    op0 < op1, op0 == op1 or op0 > op1 respectively.
-//  - For functions that return a result in the flags, this macro can be empty,
-//    because those are the correct flags to return anyway.
+//  - For functions that return a result in the flags, this macro can just
+//    return immediately, because those are the correct flags to return anyway.
 //  - Functions that return a boolean in r0 should set it up by checking the
 //    flags.
 //
@@ -69,8 +70,7 @@
   // The fastest fast path: both inputs positive and we could easily tell there
   // were no NaNs. So we just compare op0 and op1 as unsigned integers.
   cmp     op0, op1
-  SetReturnRegister
-  bx      lr
+  ReturnResult
 
 LOCAL_LABEL(NaNInf_check_positive):
   // Second tier for positive numbers. We come here if both inputs are
@@ -95,8 +95,7 @@ LOCAL_LABEL(NaNInf_check_positive):
 
   // Second-tier return path, now we've ruled out anything difficult.
   cmp     op0, op1
-  SetReturnRegister
-  bx      lr
+  ReturnResult
 
 LOCAL_LABEL(NaN_check_positive):
   // Third tier for positive numbers. Here we know that at least one of the
@@ -122,8 +121,7 @@ LOCAL_LABEL(NaN_check_positive):
   // positive. So the third-tier return path can just compare the numbers
   // again.
   cmp     op0, op1
-  SetReturnRegister
-  bx      lr
+  ReturnResult
 
 LOCAL_LABEL(negative):
   // We come here if at least one operand is negative. We haven't checked for
@@ -163,8 +161,7 @@ LOCAL_LABEL(negative):
   beq     1f
   cmp     op1, op0                // otherwise, compare them backwards
 1:
-  SetReturnRegister
-  bx      lr
+  ReturnResult
 
 LOCAL_LABEL(NaNInf_check_negative):
   // Second tier for negative numbers: we know the OR of the exponents is 0xFF,
@@ -189,5 +186,4 @@ LOCAL_LABEL(NaNInf_check_negative):
   // exponent fields was 0xFF, which means the exponents can't both have been
   // zero! So we can _just_ do the reversed CMP and finish.
   cmp     op1, op0
-  SetReturnRegister
-  bx      lr
+  ReturnResult
diff --git a/compiler-rt/lib/builtins/arm/thumb1/gesf2.S b/compiler-rt/lib/builtins/arm/thumb1/gesf2.S
index aa75ec7b0a67b..3830b6cb21c29 100644
--- a/compiler-rt/lib/builtins/arm/thumb1/gesf2.S
+++ b/compiler-rt/lib/builtins/arm/thumb1/gesf2.S
@@ -24,7 +24,7 @@
 
 op0 .req r0
 op1 .req r1
-.macro SetReturnRegister
+.macro ReturnResult
   bhi 0f
   blo 1f
   movs r0, #0

>From c64753e6a3fd207acdd6b33fd8c0069fa6d94009 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 26 Feb 2026 13:07:59 +0000
Subject: [PATCH 29/33] Fix CI failure on Windows

The new test was failing on Windows, because it tries to call
`__cmpdf2`, which the generic builtins/comparedf2.c only defines
conditionally on `__ELF__`. Do the same in the test.
---
 compiler-rt/test/builtins/Unit/comparedf2new_test.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/compiler-rt/test/builtins/Unit/comparedf2new_test.c b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
index 1a17c435987d2..d337cb3db4b0f 100644
--- a/compiler-rt/test/builtins/Unit/comparedf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/comparedf2new_test.c
@@ -41,7 +41,11 @@ int test__comparedf2(uint64_t a_rep, uint64_t b_rep, enum Result result,
   int gt = __gtdf2(a, b);
   int le = __ledf2(a, b);
   int lt = __ltdf2(a, b);
+#ifdef __ELF__
+  // The generic builtins/comparedf2.c does not define this function
+  // for object formats other than ELF
   int cmp = __cmpdf2(a, b);
+#endif
   int unord = __unorddf2(a, b);
 
   int ret = 0;
@@ -54,7 +58,9 @@ int test__comparedf2(uint64_t a_rep, uint64_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt < 0, "< 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == -1, "== -1", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_GT:
@@ -64,7 +70,9 @@ int test__comparedf2(uint64_t a_rep, uint64_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt > 0, "> 0", line);
     ret |= expect(a_rep, b_rep, "__ledf2", le, le > 0, "> 0", line);
     ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_EQ:
@@ -74,7 +82,9 @@ int test__comparedf2(uint64_t a_rep, uint64_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == 0, "== 0", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_UN:
@@ -84,7 +94,9 @@ int test__comparedf2(uint64_t a_rep, uint64_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__ledf2", le, le > 0, "> 0", line);
     ret |= expect(a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unorddf2", unord, unord == 1, "== 1", line);
     break;
   }

>From be05b10f52575736f3964b2b22c0a718fe8a9374 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 26 Feb 2026 13:07:59 +0000
Subject: [PATCH 30/33] Fix CI failure on Windows

The new test was failing on Windows, because it tries to call
`__cmpsf2`, which the generic builtins/comparesf2.c only defines
conditionally on `__ELF__`. Do the same in the test.
---
 compiler-rt/test/builtins/Unit/comparesf2new_test.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/compiler-rt/test/builtins/Unit/comparesf2new_test.c b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
index 5bed764b0957a..b5dfe2352958f 100644
--- a/compiler-rt/test/builtins/Unit/comparesf2new_test.c
+++ b/compiler-rt/test/builtins/Unit/comparesf2new_test.c
@@ -41,7 +41,11 @@ int test__comparesf2(uint32_t a_rep, uint32_t b_rep, enum Result result,
   int gt = __gtsf2(a, b);
   int le = __lesf2(a, b);
   int lt = __ltsf2(a, b);
+#ifdef __ELF__
+  // The generic builtins/comparedf2.c does not define this function
+  // for object formats other than ELF
   int cmp = __cmpsf2(a, b);
+#endif
   int unord = __unordsf2(a, b);
 
   int ret = 0;
@@ -54,7 +58,9 @@ int test__comparesf2(uint32_t a_rep, uint32_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt < 0, "< 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == -1, "== -1", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_GT:
@@ -64,7 +70,9 @@ int test__comparesf2(uint32_t a_rep, uint32_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt > 0, "> 0", line);
     ret |= expect(a_rep, b_rep, "__lesf2", le, le > 0, "> 0", line);
     ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_EQ:
@@ -74,7 +82,9 @@ int test__comparesf2(uint32_t a_rep, uint32_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__lesf2", le, le <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == 0, "== 0", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 0, "== 0", line);
     break;
   case RESULT_UN:
@@ -84,7 +94,9 @@ int test__comparesf2(uint32_t a_rep, uint32_t b_rep, enum Result result,
     ret |= expect(a_rep, b_rep, "__gtsf2", gt, gt <= 0, "<= 0", line);
     ret |= expect(a_rep, b_rep, "__lesf2", le, le > 0, "> 0", line);
     ret |= expect(a_rep, b_rep, "__ltsf2", lt, lt >= 0, ">= 0", line);
+#ifdef __ELF__
     ret |= expect(a_rep, b_rep, "__cmpsf2", cmp, cmp == 1, "== 1", line);
+#endif
     ret |= expect(a_rep, b_rep, "__unordsf2", unord, unord == 1, "== 1", line);
     break;
   }

>From daf0054dd63efc43c9d7022c6ca9d8236f6cbc78 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 17 Mar 2026 10:59:18 +0000
Subject: [PATCH 31/33] Allow the new properties to contain multiple
 files/functions

Turns out this will be needed by the final PR in the stack.
---
 compiler-rt/lib/builtins/CMakeLists.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 2c5d8d2869c8a..e64e6b70366e4 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -58,15 +58,15 @@ if (COMPILER_RT_STANDALONE_BUILD)
 endif()
 
 function(set_special_properties source_file)
-  cmake_parse_arguments(ARG "" "SUPERSEDES;PROVIDES" "" ${ARGN})
+  cmake_parse_arguments(ARG "" "" "SUPERSEDES;PROVIDES" ${ARGN})
   if(ARG_SUPERSEDES)
     set_property(SOURCE ${source_file}
-      PROPERTY crt_supersedes ${ARG_SUPERSEDES})
+      PROPERTY crt_supersedes "${ARG_SUPERSEDES}")
   endif()
   if(ARG_PROVIDES AND NOT COMPILER_RT_BUILTINS_STANDALONE_BUILD)
     set_property(SOURCE ${source_file}
       DIRECTORY ${COMPILER_RT_SOURCE_DIR}
-      PROPERTY crt_provides ${ARG_PROVIDES})
+      PROPERTY crt_provides "${ARG_PROVIDES}")
   endif()
 endfunction()
 

>From fe187f654bceb5dfe7a9ce55d336a101f8fcdd18 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 17 Mar 2026 10:43:05 +0000
Subject: [PATCH 32/33] Stop trying to crt_supersede one Arm .S file with
 another

Turns out that doesn't work: both versions of the assembly language
comparison were included in the output library, and the linker would
make an arbitrary choice of which to pull in to the link. Instead,
just put the old files on to the SOURCES list in an else clause.
---
 compiler-rt/lib/builtins/CMakeLists.txt | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 0479120fef2cb..05474e4eb2dc7 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -520,7 +520,6 @@ set(arm_sync_SOURCES
 set(thumb1_base_SOURCES
   arm/divsi3.S
   arm/udivsi3.S
-  arm/comparesf2.S
   arm/addsf3.S
   ${GENERIC_SOURCES}
 )
@@ -543,9 +542,14 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP)
   set_special_properties(arm/thumb1/cmpdf2.S
     SUPERSEDES comparedf2.c PROVIDES comparedf2)
   set_special_properties(arm/thumb1/cmpsf2.S
-    SUPERSEDES comparesf2.S)
-  # We don't need to set PROVIDES for cmpsf2.S, because the superseded
-  # comparesf2.S will already have enabled the comparesf2 tests.
+    SUPERSEDES comparesf2.c PROVIDES comparesf2)
+else()
+  # Other Thumb1 assembly implementations which do not fall under the
+  # COMPILER_RT_ARM_OPTIMIZED_FP umbrella
+  set(thumb1_base_SOURCES
+    arm/comparesf2.S
+    ${thumb1_base_SOURCES}
+  )
 endif()
 
 set(arm_EABI_RT_SOURCES

>From 0521762628c51dcae01a2c3d9e0f42d4d9381338 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 14 May 2026 10:40:46 +0100
Subject: [PATCH 33/33] Update for rename of endian.h in a previous patch

---
 compiler-rt/lib/builtins/arm/extendsfdf2.S | 2 +-
 compiler-rt/lib/builtins/arm/truncdfsf2.S  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/builtins/arm/extendsfdf2.S b/compiler-rt/lib/builtins/arm/extendsfdf2.S
index 21518d4a75b1a..dd40366ed76fd 100644
--- a/compiler-rt/lib/builtins/arm/extendsfdf2.S
+++ b/compiler-rt/lib/builtins/arm/extendsfdf2.S
@@ -12,7 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "../assembly.h"
-#include "endian.h"
+#include "crt_endian.h"
 
   .syntax unified
   .text
diff --git a/compiler-rt/lib/builtins/arm/truncdfsf2.S b/compiler-rt/lib/builtins/arm/truncdfsf2.S
index d87fce8d1bcbb..1b9957ad81a1c 100644
--- a/compiler-rt/lib/builtins/arm/truncdfsf2.S
+++ b/compiler-rt/lib/builtins/arm/truncdfsf2.S
@@ -13,7 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "../assembly.h"
-#include "endian.h"
+#include "crt_endian.h"
 
   .syntax unified
   .text



More information about the llvm-commits mailing list