@@ -322,7 +322,7 @@ arc*-*-*)
arm*-*-*)
cpu_type=arm
extra_objs="arm-builtins.o aarch-common.o"
- extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h"
+ extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h"
target_type_format_char='%'
c_target_objs="arm-c.o"
cxx_target_objs="arm-c.o"
@@ -70,10 +70,10 @@ ARM_ARCH ("armv8.2-a+fp16", cortexa53, 8A,
ARM_FSET_MAKE (FL_CO_PROC | FL_CRC32 | FL_FOR_ARCH8A,
FL2_FOR_ARCH8_2A | FL2_FP16INST))
ARM_ARCH("armv8-m.base", cortexm0, 8M_BASE,
- ARM_FSET_MAKE_CPU1 ( FL_FOR_ARCH8M_BASE))
+ ARM_FSET_MAKE ( FL_FOR_ARCH8M_BASE, FL2_CMSE))
ARM_ARCH("armv8-m.main", cortexm7, 8M_MAIN,
- ARM_FSET_MAKE_CPU1(FL_CO_PROC | FL_FOR_ARCH8M_MAIN))
+ ARM_FSET_MAKE (FL_CO_PROC | FL_FOR_ARCH8M_MAIN, FL2_CMSE))
ARM_ARCH("armv8-m.main+dsp", cortexm7, 8M_MAIN,
- ARM_FSET_MAKE_CPU1(FL_CO_PROC | FL_ARCH7EM | FL_FOR_ARCH8M_MAIN))
+ ARM_FSET_MAKE (FL_CO_PROC | FL_ARCH7EM | FL_FOR_ARCH8M_MAIN, FL2_CMSE))
ARM_ARCH("iwmmxt", iwmmxt, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT))
ARM_ARCH("iwmmxt2", iwmmxt2, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2))
@@ -77,6 +77,14 @@ arm_cpu_builtins (struct cpp_reader* pfile)
def_or_undef_macro (pfile, "__ARM_32BIT_STATE", TARGET_32BIT);
+ if (arm_arch8 && !arm_arch_notm)
+ {
+ if (arm_arch_cmse && use_cmse)
+ builtin_define_with_int_value ("__ARM_FEATURE_CMSE", 3);
+ else
+ builtin_define ("__ARM_FEATURE_CMSE");
+ }
+
if (TARGET_ARM_FEATURE_LDREX)
builtin_define_with_int_value ("__ARM_FEATURE_LDREX",
TARGET_ARM_FEATURE_LDREX);
@@ -396,6 +396,7 @@ extern bool arm_is_constant_pool_ref (rtx);
#define FL2_ARCH8_2 (1 << 1) /* Architecture 8.2. */
#define FL2_FP16INST (1 << 2) /* FP16 Instructions for ARMv8.2 and
later. */
+#define FL2_CMSE (1 << 3) /* ARMv8-M Security Extensions. */
/* Flags that only effect tuning, not available instructions. */
#define FL_TUNE (FL_WBUF | FL_VFPV2 | FL_STRONG | FL_LDSCHED \
@@ -524,6 +524,9 @@ extern bool arm_disable_literal_pool;
/* Nonzero if chip supports the ARMv8 CRC instructions. */
extern int arm_arch_crc;
+/* Nonzero if chip supports the ARMv8-M Security Extensions. */
+extern int arm_arch_cmse;
+
#ifndef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_APCS_FRAME)
#endif
@@ -906,6 +906,9 @@ int arm_condexec_masklen = 0;
/* Nonzero if chip supports the ARMv8 CRC instructions. */
int arm_arch_crc = 0;
+/* Nonzero if chip supports the ARMv8-M security extensions. */
+int arm_arch_cmse = 0;
+
/* Nonzero if the core has a very small, high-latency, multiply unit. */
int arm_m_profile_small_mul = 0;
@@ -3256,6 +3259,7 @@ arm_option_override (void)
arm_arch_no_volatile_ce = ARM_FSET_HAS_CPU1 (insn_flags, FL_NO_VOLATILE_CE);
arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0;
arm_arch_crc = ARM_FSET_HAS_CPU1 (insn_flags, FL_CRC32);
+ arm_arch_cmse = ARM_FSET_HAS_CPU2 (insn_flags, FL2_CMSE);
arm_m_profile_small_mul = ARM_FSET_HAS_CPU1 (insn_flags, FL_SMALLMUL);
arm_fp16_inst = ARM_FSET_HAS_CPU2 (insn_flags, FL2_FP16INST);
if (arm_fp16_inst)
@@ -3523,6 +3527,9 @@ arm_option_override (void)
if (target_slow_flash_data || target_pure_code)
arm_disable_literal_pool = true;
+ if (use_cmse && !arm_arch_cmse)
+ error ("target CPU does not support ARMv8-M Security Extensions");
+
/* Disable scheduling fusion by default if it's not armv7 processor
or doesn't prefer ldrd/strd. */
if (flag_schedule_fusion == 2
@@ -109,6 +109,10 @@ mfloat-abi=
Target RejectNegative Joined Enum(float_abi_type) Var(arm_float_abi) Init(TARGET_DEFAULT_FLOAT_ABI)
Specify if floating point hardware should be used.
+mcmse
+Target RejectNegative Var(use_cmse)
+Specify that the compiler should target secure code as per ARMv8-M Security Extensions.
+
Enum
Name(float_abi_type) Type(enum float_abi_type)
Known floating-point ABIs (for use with the -mfloat-abi= option):
new file mode 100644
@@ -0,0 +1,192 @@
+/* ARMv8-M Secure Extensions intrinsics include file.
+
+ Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#ifndef _GCC_ARM_CMSE_H
+#define _GCC_ARM_CMSE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __ARM_FEATURE_CMSE & 1
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __ARM_BIG_ENDIAN
+
+typedef union {
+ struct cmse_address_info {
+#if __ARM_FEATURE_CMSE & 2
+ unsigned idau_region:8;
+ unsigned idau_region_valid:1;
+ unsigned secure:1;
+ unsigned nonsecure_readwrite_ok:1;
+ unsigned nonsecure_read_ok:1;
+#else
+ unsigned :12;
+#endif
+ unsigned readwrite_ok:1;
+ unsigned read_ok:1;
+#if __ARM_FEATURE_CMSE & 2
+ unsigned sau_region_valid:1;
+#else
+ unsigned :1;
+#endif
+ unsigned mpu_region_valid:1;
+#if __ARM_FEATURE_CMSE & 2
+ unsigned sau_region:8;
+#else
+ unsigned :8;
+#endif
+ unsigned mpu_region:8;
+ } flags;
+ unsigned value;
+} cmse_address_info_t;
+
+#else
+
+typedef union {
+ struct cmse_address_info {
+ unsigned mpu_region:8;
+#if __ARM_FEATURE_CMSE & 2
+ unsigned sau_region:8;
+#else
+ unsigned :8;
+#endif
+ unsigned mpu_region_valid:1;
+#if __ARM_FEATURE_CMSE & 2
+ unsigned sau_region_valid:1;
+#else
+ unsigned :1;
+#endif
+ unsigned read_ok:1;
+ unsigned readwrite_ok:1;
+#if __ARM_FEATURE_CMSE & 2
+ unsigned nonsecure_read_ok:1;
+ unsigned nonsecure_readwrite_ok:1;
+ unsigned secure:1;
+ unsigned idau_region_valid:1;
+ unsigned idau_region:8;
+#else
+ unsigned :12;
+#endif
+ } flags;
+ unsigned value;
+} cmse_address_info_t;
+
+#endif /* __ARM_BIG_ENDIAN */
+
+#define cmse_TT_fptr(p) (__cmse_TT_fptr ((__cmse_fptr)(p)))
+
+typedef void (*__cmse_fptr)(void);
+
+#define __CMSE_TT_ASM(flags) \
+{ \
+ cmse_address_info_t __result; \
+ __asm__ ("tt" # flags " %0,%1" \
+ : "=r"(__result) \
+ : "r"(__p) \
+ : "memory"); \
+ return __result; \
+}
+
+__extension__ static __inline __attribute__ ((__always_inline__))
+cmse_address_info_t
+__cmse_TT_fptr (__cmse_fptr __p)
+__CMSE_TT_ASM ()
+
+__extension__ static __inline __attribute__ ((__always_inline__))
+cmse_address_info_t
+cmse_TT (void *__p)
+__CMSE_TT_ASM ()
+
+#define cmse_TTT_fptr(p) (__cmse_TTT_fptr ((__cmse_fptr)(p)))
+
+__extension__ static __inline __attribute__ ((__always_inline__))
+cmse_address_info_t
+__cmse_TTT_fptr (__cmse_fptr __p)
+__CMSE_TT_ASM (t)
+
+__extension__ static __inline __attribute__ ((__always_inline__))
+cmse_address_info_t
+cmse_TTT (void *__p)
+__CMSE_TT_ASM (t)
+
+#if __ARM_FEATURE_CMSE & 2
+
+#define cmse_TTA_fptr(p) (__cmse_TTA_fptr ((__cmse_fptr)(p)))
+
+__extension__ static __inline __attribute__ ((__always_inline__))
+cmse_address_info_t
+__cmse_TTA_fptr (__cmse_fptr __p)
+__CMSE_TT_ASM (a)
+
+__extension__ static __inline __attribute__ ((__always_inline__))
+cmse_address_info_t
+cmse_TTA (void *__p)
+__CMSE_TT_ASM (a)
+
+#define cmse_TTAT_fptr(p) (__cmse_TTAT_fptr ((__cmse_fptr)(p)))
+
+__extension__ static __inline cmse_address_info_t
+__attribute__ ((__always_inline__))
+__cmse_TTAT_fptr (__cmse_fptr __p)
+__CMSE_TT_ASM (at)
+
+__extension__ static __inline cmse_address_info_t
+__attribute__ ((__always_inline__))
+cmse_TTAT (void *__p)
+__CMSE_TT_ASM (at)
+
+#define CMSE_AU_NONSECURE 2
+#define CMSE_MPU_NONSECURE 16
+#define CMSE_NONSECURE 18
+
+#define cmse_nsfptr_create(p) ((typeof ((p))) ((intptr_t) (p) & ~1))
+
+#define cmse_is_nsfptr(p) (!((intptr_t) (p) & 1))
+
+#endif /* __ARM_FEATURE_CMSE & 2 */
+
+#define CMSE_MPU_UNPRIV 4
+#define CMSE_MPU_READWRITE 1
+#define CMSE_MPU_READ 8
+
+__extension__ void *
+cmse_check_address_range (void *, size_t, int);
+
+#define cmse_check_pointed_object(p, f) \
+ ((typeof ((p))) cmse_check_address_range ((p), sizeof (*(p)), (f)))
+
+#endif /* __ARM_FEATURE_CMSE & 1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GCC_ARM_CMSE_H */
@@ -11753,6 +11753,7 @@ instructions, but allow the compiler to schedule those calls.
* ARM iWMMXt Built-in Functions::
* ARM C Language Extensions (ACLE)::
* ARM Floating Point Status and Control Intrinsics::
+* ARM ARMv8-M Security Extensions::
* AVR Built-in Functions::
* Blackfin Built-in Functions::
* FR-V Built-in Functions::
@@ -12598,6 +12599,31 @@ unsigned int __builtin_arm_get_fpscr ()
void __builtin_arm_set_fpscr (unsigned int)
@end smallexample
+@node ARM ARMv8-M Security Extensions
+@subsection ARM ARMv8-M Security Extensions
+
+GCC implements the ARMv8-M Security Extensions as described in the ARMv8-M
+Security Extensions: Requiremenets on Development Tools Engineering
+Specification, which can be found at
+@uref{http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/ECM0359818_armv8m_security_extensions_reqs_on_dev_tools_1_0.pdf}.
+
+As part of the Security Extensions GCC implements the intrinsics below. FPTR
+is used here to mean any function pointer type.
+
+@smallexample
+cmse_address_info_t cmse_TT (void *)
+cmse_address_info_t cmse_TT_fptr (FPTR)
+cmse_address_info_t cmse_TTT (void *)
+cmse_address_info_t cmse_TTT_fptr (FPTR)
+cmse_address_info_t cmse_TTA (void *)
+cmse_address_info_t cmse_TTA_fptr (FPTR)
+cmse_address_info_t cmse_TTAT (void *)
+cmse_address_info_t cmse_TTAT_fptr (FPTR)
+void * cmse_check_address_range (void *, size_t, int)
+typeof(p) cmse_nsfptr_create (FPTR p)
+intptr_t cmse_is_nsfptr (FPTR)
+@end smallexample
+
@node AVR Built-in Functions
@subsection AVR Built-in Functions
@@ -645,7 +645,8 @@ Objective-C and Objective-C++ Dialects}.
-mslow-flash-data @gol
-masm-syntax-unified @gol
-mrestrict-it @gol
--mpure-code}
+-mpure-code @gol
+-mcmse}
@emph{AVR Options}
@gccoptlist{-mmcu=@var{mcu} -maccumulate-args -mbranch-cost=@var{cost} @gol
@@ -15170,6 +15171,11 @@ Additionally, when compiling for ELF object format give all text sections the
ELF processor-specific section attribute @code{SHF_ARM_PURECODE}. This option
is only available when generating non-pic code for ARMv7-M targets.
+@item -mcmse
+@opindex mcmse
+Generate secure code as per the "ARMv8-M Security Extensions: Requirements on
+Development Tools Engineering Specification", which can be found on
+@url{http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/ECM0359818_armv8m_security_extensions_reqs_on_dev_tools_1_0.pdf}.
@end table
@node AVR Options
@@ -1675,6 +1675,10 @@ and @code{MOVT} instructions available.
ARM target generates Thumb-1 code for @code{-mthumb} with
@code{CBZ} and @code{CBNZ} instructions available.
+@item arm_cmse_ok
+ARM target supports ARMv8-M Security Extensions, enabled by the @code{-mcmse}
+option.
+
@end table
@subsubsection AArch64-specific attributes
new file mode 100644
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mcmse -fdump-rtl-expand" } */
+
+#include <arm_cmse.h>
+
+extern int a;
+extern int bar (void);
+
+int foo (char * p)
+{
+ cmse_address_info_t cait;
+
+ cait = cmse_TT (&a);
+ if (cait.flags.mpu_region)
+ a++;
+
+ cait = cmse_TT_fptr (&bar);
+ if (cait.flags.mpu_region)
+ a+= bar ();
+
+ cait = cmse_TTA (&a);
+ if (cait.flags.mpu_region)
+ a++;
+
+ cait = cmse_TTA_fptr (&bar);
+ if (cait.flags.mpu_region)
+ a+= bar ();
+
+ cait = cmse_TTT (&a);
+ if (cait.flags.mpu_region)
+ a++;
+
+ cait = cmse_TTT_fptr (&bar);
+ if (cait.flags.mpu_region)
+ a+= bar ();
+
+ cait = cmse_TTAT (&a);
+ if (cait.flags.mpu_region)
+ a++;
+
+ cait = cmse_TTAT_fptr (&bar);
+ if (cait.flags.mpu_region)
+ a+= bar ();
+
+ p = (char *) cmse_check_address_range ((void *) p, sizeof (char), 0);
+ p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
+ CMSE_MPU_UNPRIV);
+ p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
+ CMSE_MPU_READWRITE);
+ p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
+ CMSE_MPU_UNPRIV | CMSE_MPU_READ);
+ p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
+ CMSE_AU_NONSECURE
+ | CMSE_MPU_NONSECURE);
+ p = (char *) cmse_check_address_range ((void *) p, sizeof (char),
+ CMSE_NONSECURE | CMSE_MPU_UNPRIV);
+
+ p = (char *) cmse_check_pointed_object (p, CMSE_NONSECURE | CMSE_MPU_UNPRIV);
+
+ return a;
+}
+/* { dg-final { scan-assembler-times "\ttt " 2 } } */
+/* { dg-final { scan-assembler-times "ttt " 2 } } */
+/* { dg-final { scan-assembler-times "tta " 2 } } */
+/* { dg-final { scan-assembler-times "ttat " 2 } } */
+/* { dg-final { scan-assembler-times "bl.cmse_check_address_range" 7 } } */
+/* { dg-final { scan-assembler-not "cmse_check_pointed_object" } } */
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+#include <arm_cmse.h>
+
+char *
+foo (char * p)
+{
+ if (!cmse_is_nsfptr (p))
+ return cmse_nsfptr_create (p);
+}
+
+/* Checks for saving and clearing prior to function call. */
+/* { dg-final { scan-assembler-not "cmse_is_nsfptr" } } */
+/* { dg-final { scan-assembler-not "cmse_nsfptr_create" } } */
new file mode 100644
@@ -0,0 +1,50 @@
+# Copyright (C) 1997-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite for ARMv8-M Security Extensions using the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Exit immediately if the target does not support -mcmse.
+if ![check_effective_target_arm_cmse_ok] then {
+ return
+}
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+set saved-dg-do-what-default ${dg-do-what-default}
+set dg-do-what-default "assemble"
+
+set saved-lto_torture_options ${LTO_TORTURE_OPTIONS}
+set LTO_TORTURE_OPTIONS ""
+
+# These are for both baseline and mainline.
+gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.c]] \
+ "" $DEFAULT_CFLAGS
+
+set LTO_TORTURE_OPTIONS ${saved-lto_torture_options}
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
@@ -3866,6 +3866,19 @@ proc check_effective_target_arm_thumb1_cbz_ok {} {
}
}
+# Return 1 if this is an ARM target where ARMv8-M Security Extensions is
+# available.
+
+proc check_effective_target_arm_cmse_ok {} {
+ return [check_no_compiler_messages arm_cmse object {
+ int
+ foo (void)
+ {
+ asm ("bxns r0");
+ }
+ } "-mcmse"];
+}
+
# Return 1 if this compilation turns on string_ops_prefer_neon on.
proc check_effective_target_arm_tune_string_ops_prefer_neon { } {
new file mode 100644
@@ -0,0 +1,108 @@
+/* ARMv8-M Security Extensions routines.
+ Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#if __ARM_FEATURE_CMSE & 1
+
+#include <arm_cmse.h>
+
+/* ARM intrinsic function to perform a permission check on a given
+ address range. See ACLE changes for ARMv8-M. */
+
+void *
+cmse_check_address_range (void *p, size_t size, int flags)
+{
+ cmse_address_info_t permb, perme;
+ char *pb = (char *) p, *pe;
+
+ /* Check if the range wraps around. */
+ if (UINTPTR_MAX - (uintptr_t) p < size)
+ return NULL;
+
+ /* Check if an unknown flag is present. */
+ int known = CMSE_MPU_UNPRIV | CMSE_MPU_READWRITE | CMSE_MPU_READ;
+ int known_secure_level = CMSE_MPU_UNPRIV;
+#if __ARM_FEATURE_CMSE & 2
+ known |= CMSE_AU_NONSECURE | CMSE_MPU_NONSECURE;
+ known_secure_level |= CMSE_MPU_NONSECURE;
+#endif
+ if (flags & (~known))
+ return NULL;
+
+ /* Execute the right variant of the TT instructions. */
+ pe = pb + size - 1;
+ const int singleCheck = (((uintptr_t) pb ^ (uintptr_t) pe) < 32);
+ switch (flags & known_secure_level)
+ {
+ case 0:
+ permb = cmse_TT (pb);
+ perme = singleCheck ? permb : cmse_TT (pe);
+ break;
+ case CMSE_MPU_UNPRIV:
+ permb = cmse_TTT (pb);
+ perme = singleCheck ? permb : cmse_TTT (pe);
+ break;
+#if __ARM_FEATURE_CMSE & 2
+ case CMSE_MPU_NONSECURE:
+ permb = cmse_TTA (pb);
+ perme = singleCheck ? permb : cmse_TTA (pe);
+ break;
+ case CMSE_MPU_UNPRIV | CMSE_MPU_NONSECURE:
+ permb = cmse_TTAT (pb);
+ perme = singleCheck ? permb : cmse_TTAT (pe);
+ break;
+#endif
+ default:
+ /* Invalid flag, eg. CMSE_MPU_NONSECURE specified but
+ __ARM_FEATURE_CMSE & 2 == 0. */
+ return NULL;
+ }
+
+ /* Check that the range does not cross MPU, SAU, or IDAU boundaries. */
+ if (permb.value != perme.value)
+ return NULL;
+
+ /* Check the permissions on the range. */
+ switch (flags & (~known_secure_level))
+ {
+#if __ARM_FEATURE_CMSE & 2
+ case CMSE_MPU_READ | CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:
+ case CMSE_MPU_READWRITE | CMSE_AU_NONSECURE:
+ return permb.flags.nonsecure_readwrite_ok ? p : NULL;
+ case CMSE_MPU_READ | CMSE_AU_NONSECURE:
+ return permb.flags.nonsecure_read_ok ? p : NULL;
+ case CMSE_AU_NONSECURE:
+ return permb.flags.secure ? NULL : p;
+#endif
+ case CMSE_MPU_READ | CMSE_MPU_READWRITE:
+ case CMSE_MPU_READWRITE:
+ return permb.flags.readwrite_ok ? p : NULL;
+ case CMSE_MPU_READ:
+ return permb.flags.read_ok ? p : NULL;
+ default:
+ return NULL;
+ }
+}
+
+
+#endif /* __ARM_FEATURE_CMSE & 1. */
@@ -1,3 +1,15 @@
LIB1ASMSRC = arm/lib1funcs.S
LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
_thumb1_case_uhi _thumb1_case_si
+
+HAVE_CMSE:=$(findstring __ARM_FEATURE_CMSE,$(shell $(gcc_compile_bare) -dM -E - </dev/null))
+ifneq ($(shell $(gcc_compile_bare) -E -mcmse - </dev/null 2>/dev/null),)
+CMSE_OPTS:=-mcmse
+endif
+
+ifdef HAVE_CMSE
+libgcc-objects += cmse.o cmse_nonsecure_call.o
+
+cmse.o: $(srcdir)/config/arm/cmse.c
+ $(gcc_compile) -c $(CMSE_OPTS) $<
+endif