Build: Support FPU with ARMCLANG.

Support FPU with ARMCLANG on AN521 and AN552.

Signed-off-by: Chendi Sun <chendi.sun@arm.com>
Change-Id: Id167c0c6bef0987199476edf1b0451057f8441be
diff --git a/bl2/CMakeLists.txt b/bl2/CMakeLists.txt
index 51cf730..2005714 100644
--- a/bl2/CMakeLists.txt
+++ b/bl2/CMakeLists.txt
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -46,7 +46,7 @@
 target_link_options(bl2
     PRIVATE
         $<$<C_COMPILER_ID:GNU>:-Wl,-Map=${CMAKE_BINARY_DIR}/bin/bl2.map>
-        $<$<C_COMPILER_ID:ARMClang>:--map>
+        $<$<C_COMPILER_ID:ARMClang>:--map;${BL2_LINKER_CP_OPTION}>
         $<$<C_COMPILER_ID:IAR>:--map\;${CMAKE_BINARY_DIR}/bin/bl2.map>
 )
 
diff --git a/config/cp_check.cmake b/config/cp_check.cmake
index 16d879c..408314b 100644
--- a/config/cp_check.cmake
+++ b/config/cp_check.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2022, Arm Limited. All rights reserved.
+# Copyright (c) 2022-2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,8 +7,10 @@
 
 ########################## FPU and MVE #########################################
 
-tfm_invalid_config(NOT CMAKE_C_COMPILER_ID STREQUAL "GNU" AND (CONFIG_TFM_ENABLE_FP OR CONFIG_TFM_ENABLE_MVE OR CONFIG_TFM_ENABLE_MVE_FP))
+tfm_invalid_config(NOT CMAKE_C_COMPILER_ID STREQUAL "GNU" AND (CONFIG_TFM_ENABLE_MVE OR CONFIG_TFM_ENABLE_MVE_FP))
+tfm_invalid_config((NOT CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_ID STREQUAL "ARMClang") AND CONFIG_TFM_ENABLE_FP)
 tfm_invalid_config((NOT CONFIG_TFM_FP_ARCH) AND (CONFIG_TFM_ENABLE_FP OR CONFIG_TFM_ENABLE_MVE_FP))
+tfm_invalid_config((CMAKE_C_COMPILER_ID STREQUAL "ARMClang") AND (NOT CONFIG_TFM_FP_ARCH_LINK) AND (CONFIG_TFM_ENABLE_FP OR CONFIG_TFM_ENABLE_MVE_FP))
 tfm_invalid_config((NOT CONFIG_TFM_ENABLE_FP AND NOT CONFIG_TFM_ENABLE_MVE AND NOT CONFIG_TFM_ENABLE_MVE_FP) AND CONFIG_TFM_LAZY_STACKING)
 tfm_invalid_config((CONFIG_TFM_ENABLE_FP OR CONFIG_TFM_ENABLE_MVE OR CONFIG_TFM_ENABLE_MVE_FP) AND NOT CONFIG_TFM_ENABLE_CP10CP11)
 
@@ -20,11 +22,19 @@
     # Create test C file.
     file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cvetest.c "int x;")
     # Compile with mitigation -mfix-cmse-cve-2021-35465.
-    execute_process (
-        COMMAND ${CMAKE_C_COMPILER} -mfix-cmse-cve-2021-35465 -S ${CMAKE_CURRENT_BINARY_DIR}/cvetest.c -o ${CMAKE_CURRENT_BINARY_DIR}/cvetest.s
-        RESULT_VARIABLE ret
-        ERROR_VARIABLE err
-    )
+    if (CMAKE_C_COMPILER_ID STREQUAL "ARMClang")
+        execute_process (
+            COMMAND ${CMAKE_C_COMPILER} --target=${CROSS_COMPILE} ${CMAKE_C_FLAGS} -mcmse -mfix-cmse-cve-2021-35465 -S ${CMAKE_CURRENT_BINARY_DIR}/cvetest.c -o ${CMAKE_CURRENT_BINARY_DIR}/cvetest.s
+            RESULT_VARIABLE ret
+            ERROR_VARIABLE err
+        )
+    else()
+        execute_process (
+            COMMAND ${CMAKE_C_COMPILER} -mfix-cmse-cve-2021-35465 -S ${CMAKE_CURRENT_BINARY_DIR}/cvetest.c -o ${CMAKE_CURRENT_BINARY_DIR}/cvetest.s
+            RESULT_VARIABLE ret
+            ERROR_VARIABLE err
+        )
+    endif()
     file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/cvetest.c)
     # Check result
     if(NOT ret EQUAL 0)
diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt
index d9c6ca8..e33407b 100755
--- a/platform/CMakeLists.txt
+++ b/platform/CMakeLists.txt
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2023, Arm Limited. All rights reserved.
 # Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company)
 # or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
 #
@@ -219,6 +219,10 @@
             $<$<BOOL:${PLATFORM_DEFAULT_OTP_WRITEABLE}>:OTP_WRITEABLE>
     )
 
+    target_compile_options(platform_bl2
+        PUBLIC
+            ${BL2_COMPILER_CP_FLAG}
+    )
 endif()
 
 #========================= Platform BL1_1 =====================================#
diff --git a/platform/ext/target/arm/mps2/an521/preload.cmake b/platform/ext/target/arm/mps2/an521/preload.cmake
index c40a092..2694a89 100644
--- a/platform/ext/target/arm/mps2/an521/preload.cmake
+++ b/platform/ext/target/arm/mps2/an521/preload.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -15,3 +15,4 @@
 set(TFM_SYSTEM_ARCHITECTURE armv8-m.main)
 set(TFM_SYSTEM_DSP OFF)
 set(CONFIG_TFM_FP_ARCH "fpv5-d16")
+set(CONFIG_TFM_FP_ARCH_LINK "FPv5_D16")
diff --git a/platform/ext/target/arm/mps3/an552/preload.cmake b/platform/ext/target/arm/mps3/an552/preload.cmake
index 2933c1e..394d971 100644
--- a/platform/ext/target/arm/mps3/an552/preload.cmake
+++ b/platform/ext/target/arm/mps3/an552/preload.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -14,3 +14,4 @@
 set(TFM_SYSTEM_PROCESSOR cortex-m55)
 set(TFM_SYSTEM_ARCHITECTURE armv8.1-m.main)
 set(CONFIG_TFM_FP_ARCH "fpv5-d16")
+set(CONFIG_TFM_FP_ARCH_LINK "FPv5_D16")
diff --git a/toolchain_ARMCLANG.cmake b/toolchain_ARMCLANG.cmake
index 0aed71a..6645bfb 100644
--- a/toolchain_ARMCLANG.cmake
+++ b/toolchain_ARMCLANG.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2023, Arm Limited. All rights reserved.
 # Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company)
 # or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
 #
@@ -43,8 +43,6 @@
         $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-nostdlib>
         $<$<COMPILE_LANGUAGE:C>:-std=c99>
         $<$<COMPILE_LANGUAGE:CXX>:-std=c++11>
-        $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-mfpu=none>
-        $<$<COMPILE_LANGUAGE:ASM>:--fpu=none>
         $<$<COMPILE_LANGUAGE:ASM>:--cpu=${CMAKE_ASM_CPU_FLAG}>
         $<$<AND:$<COMPILE_LANGUAGE:C>,$<BOOL:${TFM_DEBUG_SYMBOLS}>>:-g>
         $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:${TFM_DEBUG_SYMBOLS}>>:-g>
@@ -77,7 +75,6 @@
         --diag_suppress=6304
         # Pattern only matches removed unused sections.
         --diag_suppress=6329
-        --fpu=softvfp
     )
 endmacro()
 
@@ -96,7 +93,21 @@
             endif()
         endif()
 
+        # ARMCLANG specifies that '+nofp' is available on following M-profile cpus:
+        # 'cortex-m4', 'cortex-m7', 'cortex-m33', 'cortex-m35p' and 'cortex-m55'.
+        # Build fails if other M-profile cpu, such as 'cortex-m23', is added with '+nofp'.
+        # Explicitly list those cpu to align with ARMCLANG description.
+        if (NOT CONFIG_TFM_FLOAT_ABI STREQUAL "hard" AND
+            (TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m4"
+            OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m7"
+            OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m33"
+            OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m35p"
+            OR TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m55"))
+                string(APPEND CMAKE_SYSTEM_PROCESSOR "+nofp")
+        endif()
+
         string(REGEX REPLACE "\\+nodsp" ".no_dsp" CMAKE_ASM_CPU_FLAG "${CMAKE_SYSTEM_PROCESSOR}")
+        string(REGEX REPLACE "\\+nofp" ".no_fp" CMAKE_ASM_CPU_FLAG "${CMAKE_ASM_CPU_FLAG}")
     else()
         set(CMAKE_ASM_CPU_FLAG  ${TFM_SYSTEM_ARCHITECTURE})
 
@@ -108,6 +119,10 @@
         if (TFM_SYSTEM_DSP)
             string(APPEND CMAKE_ASM_CPU_FLAG ".dsp")
         endif()
+
+        if (CONFIG_TFM_FLOAT_ABI STREQUAL "hard")
+            string(APPEND CMAKE_ASM_CPU_FLAG ".fp")
+        endif()
     endif()
 
     # CMAKE_SYSTEM_ARCH is an ARMCLANG CMAKE internal variable, used to set
@@ -201,6 +216,24 @@
         set(CMAKE_CXX_FLAGS "-march=${CMAKE_SYSTEM_ARCH}")
     endif()
 
+    set(BL2_COMPILER_CP_FLAG -mfloat-abi=soft)
+    # As BL2 does not use hardware FPU, specify '--fpu=SoftVFP' explicitly to use software
+    # library functions for BL2 to override any implicit FPU option, such as '--cpu' option.
+    # Because the implicit hardware FPU option enforces BL2 to initialize FPU but hardware FPU
+    # is not actually enabled in BL2, it will cause BL2 runtime fault.
+    set(BL2_LINKER_CP_OPTION --fpu=SoftVFP)
+
+    if (CONFIG_TFM_FLOAT_ABI STREQUAL "hard")
+        set(COMPILER_CP_FLAG -mfloat-abi=hard)
+        if (CONFIG_TFM_ENABLE_FP)
+            set(COMPILER_CP_FLAG -mfloat-abi=hard -mfpu=${CONFIG_TFM_FP_ARCH})
+            set(LINKER_CP_OPTION --fpu=${CONFIG_TFM_FP_ARCH_LINK})
+        endif()
+    else()
+        set(COMPILER_CP_FLAG -mfloat-abi=soft)
+        set(LINKER_CP_OPTION --fpu=SoftVFP)
+    endif()
+
     # Workaround for issues with --depend-single-line with armasm and Ninja
     if (CMAKE_GENERATOR STREQUAL "Ninja")
         set( CMAKE_DEPFILE_FLAGS_ASM "--depend=<OBJECT>.d")