1# 2# Copyright (c) 2023, Arm Limited. All rights reserved. 3# 4# SPDX-License-Identifier: BSD-3-Clause 5# 6 7# This build helper makefile is used to determine a suitable march build 8# option to be used, based on platform provided ARM_ARCH_MAJOR/MINOR 9# data and compiler supported march version. 10 11# Set the compiler's target architecture profile based on 12# ARM_ARCH_MAJOR and ARM_ARCH_MINOR options. 13 14 15# This is used to collect available march values from compiler. 16# Example on a gcc-12.2 arm64 toolchain it will look like: 17# [...] 18#./aarch64-none-elf-gcc --target-help -march=foo 19# cc1: error: unknown value 'foo' for '-march' 20# cc1: note: valid arguments are: armv8-a armv8.1-a armv8.2-a armv8.3-a armv8.4-a armv8.5-a 21# armv8.6-a armv8.7-a armv8.8-a armv8-r armv9-a 22# [...] 23# 24GCC_MARCH_OUTPUT := $(shell $(CC) -march=foo -Q --help=target -v 2>&1) 25 26# This function is used to find the best march value supported by the given compiler. 27# We try to use `GCC_MARCH_OUTPUT` which has verbose message with supported march values we filter that 28# to find armvX.Y-a or armvX-a values, then filter the best supported arch based on ARM_ARCH_MAJOR. 29# 30# Example on a gcc-12.2 arm64 toolchain this will return armv9-a if platform requested for armv9.2-a 31# Similarly on gcc 11.3 it would return armv8.6-a if platform requested armv8.8-a 32define major_best_avail_march 33$(1) := $(lastword $(filter armv$(ARM_ARCH_MAJOR)% ,$(filter armv%-a, $(GCC_MARCH_OUTPUT)))) 34endef 35 36# This function is used to just return latest march value supported by the given compiler. 37# 38# Example: this would return armv8.6-a on a gcc-11.3 when platform requested for armv9.0-a 39# 40# Thus this function should be used in conjunction with major_best_avail_march, when best match 41# is not found it should be ok to try with lastest known supported march value from the 42# compiler. 43define latest_match_march 44$(1) := $(lastword $(filter armv%-a, $(GCC_MARCH_OUTPUT))) 45endef 46 47ifdef MARCH_DIRECTIVE 48 march-directive := $(MARCH_DIRECTIVE) 49else 50 51ifeq (${ARM_ARCH_MINOR},0) 52 provided-march = armv${ARM_ARCH_MAJOR}-a 53else 54 provided-march = armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a 55endif 56 57ifeq ($(findstring clang,$(notdir $(CC))),) 58 59# We expect from Platform to provide a correct Major/Minor value but expecting something 60# from compiler with unsupported march means we shouldn't fail without trying anything, 61# so here we try to find best supported march value and use that for compilation. 62# If we don't support current march version from gcc compiler, try with lower arch based on 63# availability. In TF-A there is no hard rule for need of higher version march for basic 64# functionality, denying a build on only this fact doesn't look correct, so try with best 65# or latest march values from whats available from compiler. 66ifeq (,$(findstring $(provided-march), $(GCC_MARCH_OUTPUT))) 67 $(eval $(call major_best_avail_march, available-march)) 68 69ifeq (, $(available-march)) 70 $(eval $(call latest_match_march, available-march)) 71endif 72 73# If we fail to come up with any available-march value so far, don't update 74# provided-march and thus allow the build to fail using the provided-march 75# which is derived based on arch_major and arch_minor values. 76ifneq (,$(available-march)) 77 provided-march := ${available-march} 78endif 79 80endif # provided-march supported 81endif # not clang 82 83march-directive := -march=${provided-march} 84 85endif # MARCH_DIRECTIVE 86