[libc-commits] [libc] [libc] Enable the FPU in Arm startup code (PR #166349)

Victor Campos via libc-commits libc-commits at lists.llvm.org
Wed Nov 5 08:39:37 PST 2025


https://github.com/vhscampos updated https://github.com/llvm/llvm-project/pull/166349

>From 78f0a56e5836ffaa6228c39793f68281c57f443a Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Tue, 4 Nov 2025 11:12:01 +0000
Subject: [PATCH 1/3] [libc] Enable the FPU in Arm startup code

This patch enables the FPU in Arm startup code, which is required to run
tests on Arm configurations with hardware floating-point support.
---
 libc/startup/baremetal/arm/start.cpp | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp
index c089a14f5f782..a88861929a23f 100644
--- a/libc/startup/baremetal/arm/start.cpp
+++ b/libc/startup/baremetal/arm/start.cpp
@@ -131,6 +131,28 @@ namespace LIBC_NAMESPACE_DECL {
   __arm_wsr("CPSR_c", 0x13); // SVC
 #endif
 
+#ifdef __ARM_FP
+// Enable FPU
+#if __ARM_ARCH_PROFILE == 'M'
+  // Set CPACR cp10 and cp11
+  auto cpacr = (volatile uint32_t *const)0xE000ED88;
+  *cpacr |= (0xF << 20);
+  __dsb(0xF);
+  __isb(0xF);
+#elif __ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R'
+  // Set CPACR cp10 and cp11
+  uint32_t cpacr = __arm_rsr("p15:0:c1:c0:2");
+  cpacr |= (0xF << 20);
+  __arm_wsr("p15:0:c1:c0:2", cpacr);
+  // Set FPEXC.EN
+  uint32_t fpexc;
+  __asm__ __volatile__("vmrs %0, FPEXC" : "=r"(fpexc) : :);
+  fpexc |= (1 << 30);
+  __asm__ __volatile__("vmsr FPEXC, %0" : : "r"(fpexc) :);
+  __isb(0xF);
+#endif
+#endif
+
   // Perform the equivalent of scatterloading
   LIBC_NAMESPACE::memcpy(__data_start, __data_source,
                          reinterpret_cast<uintptr_t>(__data_size));

>From fd44ca52d40c7c9a4a418adcfb33293bb40b84a8 Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Wed, 5 Nov 2025 15:29:55 +0000
Subject: [PATCH 2/3] Move the ISB barrier

---
 libc/startup/baremetal/arm/start.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp
index a88861929a23f..da8d8a2ab6108 100644
--- a/libc/startup/baremetal/arm/start.cpp
+++ b/libc/startup/baremetal/arm/start.cpp
@@ -144,12 +144,12 @@ namespace LIBC_NAMESPACE_DECL {
   uint32_t cpacr = __arm_rsr("p15:0:c1:c0:2");
   cpacr |= (0xF << 20);
   __arm_wsr("p15:0:c1:c0:2", cpacr);
+  __isb(0xF);
   // Set FPEXC.EN
   uint32_t fpexc;
   __asm__ __volatile__("vmrs %0, FPEXC" : "=r"(fpexc) : :);
   fpexc |= (1 << 30);
   __asm__ __volatile__("vmsr FPEXC, %0" : : "r"(fpexc) :);
-  __isb(0xF);
 #endif
 #endif
 

>From 8e08d5f41b8a9d2c206e5593812552fda47c541b Mon Sep 17 00:00:00 2001
From: Victor Campos <victor.campos at arm.com>
Date: Wed, 5 Nov 2025 16:36:52 +0000
Subject: [PATCH 3/3] Added links to references

---
 libc/startup/baremetal/arm/start.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libc/startup/baremetal/arm/start.cpp b/libc/startup/baremetal/arm/start.cpp
index da8d8a2ab6108..4740067722022 100644
--- a/libc/startup/baremetal/arm/start.cpp
+++ b/libc/startup/baremetal/arm/start.cpp
@@ -134,12 +134,16 @@ namespace LIBC_NAMESPACE_DECL {
 #ifdef __ARM_FP
 // Enable FPU
 #if __ARM_ARCH_PROFILE == 'M'
+  // Based on
+  // https://developer.arm.com/documentation/dui0646/c/Cortex-M7-Peripherals/Floating-Point-Unit/Enabling-the-FPU
   // Set CPACR cp10 and cp11
   auto cpacr = (volatile uint32_t *const)0xE000ED88;
   *cpacr |= (0xF << 20);
   __dsb(0xF);
   __isb(0xF);
 #elif __ARM_ARCH_PROFILE == 'A' || __ARM_ARCH_PROFILE == 'R'
+  // Based on
+  // https://developer.arm.com/documentation/dui0472/m/Compiler-Coding-Practices/Enabling-NEON-and-FPU-for-bare-metal
   // Set CPACR cp10 and cp11
   uint32_t cpacr = __arm_rsr("p15:0:c1:c0:2");
   cpacr |= (0xF << 20);



More information about the libc-commits mailing list