Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions libc/startup/baremetal/arm/start.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,32 @@ namespace LIBC_NAMESPACE_DECL {
__arm_wsr("CPSR_c", 0x13); // SVC
#endif

#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);
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,

__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);
__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) :);
#endif
#endif

// Perform the equivalent of scatterloading
LIBC_NAMESPACE::memcpy(__data_start, __data_source,
reinterpret_cast<uintptr_t>(__data_size));
Expand Down
Loading