Skip to content

Conversation

@vhscampos
Copy link
Member

This patch enables the FPU in Arm startup code, which is required to run tests on Arm configurations with hardware floating-point support.

This patch enables the FPU in Arm startup code, which is required to run
tests on Arm configurations with hardware floating-point support.
@llvmbot llvmbot added the libc label Nov 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2025

@llvm/pr-subscribers-libc

Author: Victor Campos (vhscampos)

Changes

This patch enables the FPU in Arm startup code, which is required to run tests on Arm configurations with hardware floating-point support.


Full diff: https://github.com/llvm/llvm-project/pull/166349.diff

1 Files Affected:

  • (modified) libc/startup/baremetal/arm/start.cpp (+22)
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));

@lntue lntue requested a review from statham-arm November 5, 2025 04:50
// Set CPACR cp10 and cp11
auto cpacr = (volatile uint32_t *const)0xE000ED88;
*cpacr |= (0xF << 20);
__dsb(0xF);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this makes sense to me except that I'm not sure why this __dsb is here and not in the A/R branch. I didn't see any ArmARM documentation that mentioned it. Is it deliberately M-only?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the references. I notice that the middle one of your links puts the ISB before attempting to mess with FPEXC, rather than after, which makes sense to me since the VMSR/VMRS pair are themselves (modelled as) MRC/MCR to coprocessor 10 which you've only just enabled. That seems like a reasonable precaution if we're going to include it at all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @vhscampos and @statham-arm ! @vhscampos do you mind adding the references for these to the comments for each cases? Thanks,

@vhscampos vhscampos merged commit 22b6c49 into llvm:main Nov 6, 2025
20 checks passed
@vhscampos vhscampos deleted the libc-arm-enable-fpu branch November 6, 2025 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants