[PATCH] Make macro checks ARMv8-M baseline proof

Richard Earnshaw (lists) Richard.Earnshaw@arm.com
Wed Dec 16 20:39:00 GMT 2015


On 16/12/15 12:45, Thomas Preud'homme wrote:
> To get optimal performance, newlib provides multiple implementation of several routines such as strcmp which are guarded by macro checks. One common check is to look if the target supports only Thumb-1. ARMv6-M being until now the only architecture in such a case, this check was implemented by looking at the value of __ARM_ARCH or checking whether __ARM_ARCH_6M__ is defined. ARMv8-M make this wrong since ARMv8-M baseline is also (mostly) Thumb-1 only and ARMv8-M mainline is also Thumb-2 only. This patch replace checks for __ARM_ARCH_*__ for checks against __ARM_ARCH_ISA_THUMB and __ARM_ARCH_ISA_ARM instead. For instance, Thumb-1 only can be checked with #if !__ARM_ARCH_ISA_ARM && __ARM_ARCH_ISA_THUMB == 1.
> 
> 
> === Quick overview of ARMv8-M ===
> 
> ARMv8-M has two profiles[1]: Baseline and Mainline.  In terms of features they can be defined as:
> 
> ARMv8-M Baseline (armv8-m.base):
>  * All ARMv6-M features
>  * 16-bit immediate moves
>  * Wide Branch
>  * Compare & branch if (not) zero
>  * Integer divide
>  * Load/store exclusives
>  * Atomic Load/stores
>  * Security extensions
> 
> ARMv8-M Mainline (armv8-m.main):
>  * All ARMv7-M features
>  * Atomic load/stores
>  * Security extensions.
> 
> ARMv8-M Mainline with DSP extension (armv8-m.main+dsp):
>  * ARMv8-M Mainline
>  * Those instructions added to ARMv7E-M on top of ARMv7-M.
> 
> Note that although certain architectural features of the security extensions are optional for cores implementing ARMv8-M, some of the new instructions are always available in the architecture.
> 
> Note also that only the instructions from security extensions are new instructions, all other instructions have previously been available in other ARM Architecture profiles.
> 
> [1] http://www.arm.com/products/processors/instruction-set-architectures/armv8-m-architecture.php
> 
> 
> ChangeLog entries are as follow:
> 
> *** libgloss/ChangeLog ***
> 
> 2015-12-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * arm/arm.h (THUMB_V7_V6M): Rename to ...
>         (PREFER_THUMB): This.  Use ACLE macros __ARM_ARCH_ISA_ARM instead of
>         __ARM_ARCH_6M__ to decide whether to define it.
>         (THUMB_V7M_V6M): Delete.
>         (THUMB1_ONLY): Define for Thumb-1 only targets.
>         * arm/crt0.S: Use THUMB1_ONLY rather than __ARM_ARCH_6M__,
>         !__ARM_ARCH_ISA_ARM rather than THUMB_V7M_V6M, and PREFER_THUMB rather
>         than THUMB_V7_V6M.
>         * arm/linux-crt0.c: Likewise.
>         * arm/redboot-crt0.S: Likewise.
>         * arm/swi.h: Likewise.
>         * arm/trap.S: Likewise.
> 

Some older versions of GCC only partially (at best) define the ACLE
macros.  You can handle this by including acle-compat.h from
newlib/libc/machine/arm.  However, I'm not exactly sure if it's possible
to reach over directly from libgloss to the newlib source tree.

Jeff/Corinna: is this possible?  if so, what are the runes needed?
Ideally acle-compat.h should not be installed since it's only intended
to support building newlib.

R.

> *** newlib/ChangeLog ***
> 
> 2015-12-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * libc/machine/arm/memcpy-stub.c: Use ACLE macros __ARM_ARCH_ISA_THUMB
>         and __ARM_ARCH_ISA_ARM to check for Thumb-2 only targets rather than
>         __ARM_ARCH and __ARM_ARCH_PROFILE.
>         * libc/machine/arm/memcpy.S: Likewise.
>         * libc/machine/arm/setjmp.S: Likewise for Thumb-1 only target.
>         * libc/machine/arm/strcmp.S: Likewise for Thumb-1 and Thumb-2 only
>         target.
>         * libc/sys/arm/arm.h (THUMB_V7_V6M): Rename to ...
>         (PREFER_THUMB): This.  Use ACLE macro __ARM_ARCH_ISA_ARM instead of
>         __ARM_ARCH_6M__ to decide whether to define it.
>         (THUMB_V7M_V6M): Delete.
>         (THUMB1_ONLY): Define for Thumb-1 only targets.
>         * libc/sys/arm/crt0.S: Use !__ARM_ARCH_ISA_ARM rather than
>         THUMB_V7M_V6M and PREFER_THUMB rather than THUMB_V7_V6M.
>         * libc/sys/arm/swi.h: Likewise.
> 
> 
> diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
> index 26a1ff1..d50fcb2 100644
> --- a/libgloss/arm/arm.h
> +++ b/libgloss/arm/arm.h
> @@ -29,25 +29,17 @@
>  #ifndef _LIBGLOSS_ARM_H
>  #define _LIBGLOSS_ARM_H
>  
> -/* __thumb2__ stands for thumb on armva7(A/R/M/EM) architectures,
> -   __ARM_ARCH_6M__ stands for armv6-M(thumb only) architecture,
> -   __ARM_ARCH_7M__ stands for armv7-M(thumb only) architecture.
> -   __ARM_ARCH_7EM__ stands for armv7e-M(thumb only) architecture.
> -   There are some macro combinations used many times in libgloss/arm,
> -   like (__thumb2__ || (__thumb__ && __ARM_ARCH_6M__)), so factor
> -   it out and use THUMB_V7_V6M instead, which stands for thumb on
> -   v6-m/v7 arch as the combination does.  */
> -#if defined(__thumb2__) || (defined(__thumb__) && defined(__ARM_ARCH_6M__))
> -# define THUMB_V7_V6M
> +/* Checking for targets supporting only Thumb instructions (eg. ARMv6-M) or
> +   supporting Thumb-2 instructions, whether ARM instructions are available or
> +   not, is done many times in libgloss/arm.  So factor it out and use
> +   PREFER_THUMB instead.  */
> +#if __thumb2__ || (__thumb__ && !__ARM_ARCH_ISA_ARM)
> +# define PREFER_THUMB
>  #endif
>  
> -/* The (__ARM_ARCH_7EM__ || __ARM_ARCH_7M__ || __ARM_ARCH_6M__) combination
> -   stands for cortex-M profile architectures, which don't support ARM state.
> -   Factor it out and use THUMB_V7M_V6M instead.  */
> -#if defined(__ARM_ARCH_7M__)     \
> -    || defined(__ARM_ARCH_7EM__) \
> -    || defined(__ARM_ARCH_6M__)
> -# define THUMB_V7M_V6M
> +/* Processor only capable of executing Thumb-1 instructions.  */
> +#if __ARM_ARCH_ISA_THUMB == 1 && !__ARM_ARCH_ISA_ARM
> +# define THUMB1_ONLY
>  #endif
>  
>  /* Defined if this target supports the BLX Rm instruction.  */
> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> index cb9021d..be5c1b9 100644
> --- a/libgloss/arm/crt0.S
> +++ b/libgloss/arm/crt0.S
> @@ -44,7 +44,7 @@
>  /* .text is used instead of .section .text so it works with arm-aout too.  */
>  	.text
>  	.syntax unified
> -#ifdef THUMB_V7_V6M
> +#ifdef PREFER_THUMB
>  	.thumb
>  .macro FUNC_START name
>  	.global \name
> @@ -98,7 +98,7 @@
>  
>  	/*  stack limit is at end of data */
>  	/*  allow slop for stack overflow handling and small frames */
> -#ifdef __ARM_ARCH_6M__
> +#ifdef THUMB1_ONLY
>  	ldr	r0, .LC2
>  	adds	r0, #128
>  	adds	r0, #128
> @@ -112,7 +112,7 @@
>  	/*  Issue Angel SWI to read stack info */
>  	movs	r0, #AngelSWI_Reason_HeapInfo
>  	adr	r1, .LC0	/*  point at ptr to 4 words to receive data */
> -#ifdef THUMB_V7M_V6M
> +#ifndef __ARM_ARCH_ISA_ARM
>  	bkpt	AngelSWI
>  #elif defined(__thumb2__)
>  	/*  We are in thumb mode for startup on armv7 architectures. */
> @@ -154,7 +154,7 @@
>  	cmp	r2, #0
>  	beq	.LC27
>  	/*  allow slop for stack overflow handling and small frames */
> -#ifdef __ARM_ARCH_6M__
> +#ifdef THUMB1_ONLY
>  	adds	r2, #128
>  	adds	r2, #128
>  	mov	sl, r2
> @@ -180,7 +180,7 @@
>  #ifdef __thumb2__
>  	it	eq
>  #endif	
> -#ifdef __ARM_ARCH_6M__
> +#ifdef THUMB1_ONLY
>  	bne	.LC28
>  	ldr	r3, .LC0
>  .LC28:
> @@ -192,7 +192,7 @@
>  		 have somehow missed it below (in which case it gets the same
>  		 value as FIQ - not ideal, but better than nothing.) */
>  	mov	sp, r3
> -#ifdef THUMB_V7_V6M
> +#ifdef PREFER_THUMB
>  	/* XXX Fill in stack assignments for interrupt modes.  */
>  #else
>  	mrs	r2, CPSR
> @@ -235,7 +235,7 @@
>  	   this default 64k is enough for the program being executed.
>  	   However, it ensures that this simple crt0 world will not
>  	   immediately cause an overflow event:  */
> -#ifdef __ARM_ARCH_6M__
> +#ifdef THUMB1_ONLY
>  	movs	r2, #64
>  	lsls	r2, r2, #10
>  	subs	r2, r3, r2
> @@ -255,7 +255,7 @@
>  	subs	a3, a3, a1		/* Third arg: length of block */
>  	
>  
> -#if defined(__thumb__) && !defined(THUMB_V7_V6M)
> +#if __thumb__ && !defined(PREFER_THUMB)
>  	/* Enter Thumb mode.... */
>  	add	a4, pc, #1	/* Get the address of the Thumb block */
>  	bx	a4		/* Go there and start Thumb decoding  */
> @@ -426,7 +426,7 @@ __change_mode:
>  
>  	bl	FUNCTION (exit)		/* Should not return.  */
>  
> -#if defined(__thumb__) && !defined(THUMB_V7_V6M)
> +#if __thumb__ && !defined(PREFER_THUMB)
>  	/* Come out of Thumb mode.  This code should be redundant.  */
>  
>  	mov	a4, pc
> diff --git a/libgloss/arm/linux-crt0.c b/libgloss/arm/linux-crt0.c
> index c313d26..878ece7 100644
> --- a/libgloss/arm/linux-crt0.c
> +++ b/libgloss/arm/linux-crt0.c
> @@ -12,7 +12,7 @@
>  
>  static int _main(int argc, char *argv[]) __attribute__((noreturn));
>  
> -#if defined(__thumb__) && !defined(THUMB_V7_V6M)
> +#if __thumb__ && !defined(PREFER_THUMB)
>  asm("\n"
>  	".code 32\n"
>  	".global _start\n"
> diff --git a/libgloss/arm/redboot-crt0.S b/libgloss/arm/redboot-crt0.S
> index 1d90228..0e3a9b4 100644
> --- a/libgloss/arm/redboot-crt0.S
> +++ b/libgloss/arm/redboot-crt0.S
> @@ -14,7 +14,7 @@
>      .text
>  	.syntax unified
>       /* Setup the assembly entry point.  */
> -#ifdef THUMB_V7_V6M
> +#ifdef PREFER_THUMB
>  .macro FUNC_START name
>  	.global \name
>  	.thumb_func
> @@ -31,13 +31,13 @@
>  	FUNC_START SYM_NAME(_start)
>      /* Unnecessary to set fp for v6-m/v7-m, which don't support
>         ARM state.  */
> -#ifndef THUMB_V7M_V6M
> +#if __ARM_ARCH_ISA_ARM
>  	mov	fp, #0	/* Null frame pointer.  */
>  #endif
>  	movs	r7, #0	/* Null frame pointer for Thumb.  */
>  
>  	/* Enable interrupts for gdb debugging.  */
> -#ifdef THUMB_V7_V6M
> +#ifdef PREFER_THUMB
>  	cpsie if
>  #else
>  	mrs    r0, cpsr
> @@ -66,7 +66,7 @@
>  	/* Nothing to left to clear.  */
>  #endif
>  
> -#if defined(__thumb__) && !defined(THUMB_V7_V6M)
> +#if __thumb__ && !defined(PREFER_THUMB)
>  	/* Enter Thumb mode. */
>  	add	a4, pc, #1	/* Get the address of the Thumb block.  */
>  	bx	a4		/* Go there and start Thumb decoding.   */
> diff --git a/libgloss/arm/swi.h b/libgloss/arm/swi.h
> index 0f93134..76937fa 100644
> --- a/libgloss/arm/swi.h
> +++ b/libgloss/arm/swi.h
> @@ -36,7 +36,7 @@
>  #define AngelSWI 			AngelSWI_ARM
>  #endif
>  /* For thumb only architectures use the BKPT instruction instead of SWI.  */
> -#ifdef THUMB_V7M_V6M
> +#if !__ARM_ARCH_ISA_ARM
>  #define AngelSWIInsn			"bkpt"
>  #define AngelSWIAsm			bkpt
>  #else
> diff --git a/libgloss/arm/trap.S b/libgloss/arm/trap.S
> index 9eb3906..d854b57 100644
> --- a/libgloss/arm/trap.S
> +++ b/libgloss/arm/trap.S
> @@ -1,6 +1,6 @@
>  #include "arm.h"
>          /* Run-time exception support */
> -#ifndef THUMB_V7_V6M
> +#ifndef PREFER_THUMB
>  #include "swi.h"
>  
>  /* .text is used instead of .section .text so it works with arm-aout too.  */
> diff --git a/newlib/libc/machine/arm/memcpy-stub.c b/newlib/libc/machine/arm/memcpy-stub.c
> index 52a0f91..6cd0e3b 100644
> --- a/newlib/libc/machine/arm/memcpy-stub.c
> +++ b/newlib/libc/machine/arm/memcpy-stub.c
> @@ -34,7 +34,7 @@
>  #elif (__ARM_ARCH >= 7 && __ARM_ARCH_PROFILE == 'A' \
>         && defined (__ARM_FEATURE_UNALIGNED))
>  /* Defined in memcpy.S.  */
> -#elif __ARM_ARCH >= 7 && __ARM_ARCH_PROFILE == 'M'
> +#elif __ARM_ARCH_ISA_THUMB == 2 && !__ARM_ARCH_ISA_ARM
>  /* Defined in memcpy.S.  */
>  #else
>  # include "../../string/memcpy.c"
> diff --git a/newlib/libc/machine/arm/memcpy.S b/newlib/libc/machine/arm/memcpy.S
> index d9d5810..77bd2a6 100644
> --- a/newlib/libc/machine/arm/memcpy.S
> +++ b/newlib/libc/machine/arm/memcpy.S
> @@ -38,7 +38,7 @@
>         && defined (__ARM_FEATURE_UNALIGNED))
>  #include "memcpy-armv7a.S"
>  
> -#elif __ARM_ARCH >= 7 && __ARM_ARCH_PROFILE == 'M'
> +#elif __ARM_ARCH_ISA_THUMB == 2 && !__ARM_ARCH_ISA_ARM
>  #include "memcpy-armv7m.S"
>  
>  #else
> diff --git a/newlib/libc/machine/arm/setjmp.S b/newlib/libc/machine/arm/setjmp.S
> index a65fbab..fa35bb2 100644
> --- a/newlib/libc/machine/arm/setjmp.S
> +++ b/newlib/libc/machine/arm/setjmp.S
> @@ -55,8 +55,8 @@
>     
>     For Thumb-2 do everything in Thumb mode.  */
>  
> -#if defined(__ARM_ARCH_6M__)
> -/* ARMv6-M has to be implemented in Thumb mode.  */
> +#if __ARM_ARCH_ISA_THUMB == 1 && !__ARM_ARCH_ISA_ARM
> +/* ARMv6-M-like has to be implemented in Thumb mode.  */
>  
>  .thumb
>  .thumb_func
> diff --git a/newlib/libc/machine/arm/strcmp.S b/newlib/libc/machine/arm/strcmp.S
> index 7b4d7fc..d5fe82b 100644
> --- a/newlib/libc/machine/arm/strcmp.S
> +++ b/newlib/libc/machine/arm/strcmp.S
> @@ -61,7 +61,7 @@
>  	.endm
>  
>  #if defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) \
> -	|| (__ARM_ARCH == 6 && __ARM_ARCH_PROFILE == 'M')
> +	|| (__ARM_ARCH_ISA_THUMB == 1 && !__ARM_ARCH_ISA_ARM)
>  
>  # if defined (__thumb__) && !defined (__thumb2__)
>  /* Thumb1 only variant.  If size is preferred, use strcmp-armv4t.S.
> @@ -78,7 +78,7 @@
>  #  include "strcmp-arm-tiny.S"
>  # endif
>  
> -#elif __ARM_ARCH >= 7
> +#elif __ARM_ARCH_ISA_THUMB == 2
>  
>  # ifdef __ARM_FEATURE_SIMD32
>  #  include "strcmp-armv7.S"
> diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
> index 26a1ff1..d50fcb2 100644
> --- a/newlib/libc/sys/arm/arm.h
> +++ b/newlib/libc/sys/arm/arm.h
> @@ -29,25 +29,17 @@
>  #ifndef _LIBGLOSS_ARM_H
>  #define _LIBGLOSS_ARM_H
>  
> -/* __thumb2__ stands for thumb on armva7(A/R/M/EM) architectures,
> -   __ARM_ARCH_6M__ stands for armv6-M(thumb only) architecture,
> -   __ARM_ARCH_7M__ stands for armv7-M(thumb only) architecture.
> -   __ARM_ARCH_7EM__ stands for armv7e-M(thumb only) architecture.
> -   There are some macro combinations used many times in libgloss/arm,
> -   like (__thumb2__ || (__thumb__ && __ARM_ARCH_6M__)), so factor
> -   it out and use THUMB_V7_V6M instead, which stands for thumb on
> -   v6-m/v7 arch as the combination does.  */
> -#if defined(__thumb2__) || (defined(__thumb__) && defined(__ARM_ARCH_6M__))
> -# define THUMB_V7_V6M
> +/* Checking for targets supporting only Thumb instructions (eg. ARMv6-M) or
> +   supporting Thumb-2 instructions, whether ARM instructions are available or
> +   not, is done many times in libgloss/arm.  So factor it out and use
> +   PREFER_THUMB instead.  */
> +#if __thumb2__ || (__thumb__ && !__ARM_ARCH_ISA_ARM)
> +# define PREFER_THUMB
>  #endif
>  
> -/* The (__ARM_ARCH_7EM__ || __ARM_ARCH_7M__ || __ARM_ARCH_6M__) combination
> -   stands for cortex-M profile architectures, which don't support ARM state.
> -   Factor it out and use THUMB_V7M_V6M instead.  */
> -#if defined(__ARM_ARCH_7M__)     \
> -    || defined(__ARM_ARCH_7EM__) \
> -    || defined(__ARM_ARCH_6M__)
> -# define THUMB_V7M_V6M
> +/* Processor only capable of executing Thumb-1 instructions.  */
> +#if __ARM_ARCH_ISA_THUMB == 1 && !__ARM_ARCH_ISA_ARM
> +# define THUMB1_ONLY
>  #endif
>  
>  /* Defined if this target supports the BLX Rm instruction.  */
> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> index b56072f..c5dc17c 100644
> --- a/newlib/libc/sys/arm/crt0.S
> +++ b/newlib/libc/sys/arm/crt0.S
> @@ -44,7 +44,7 @@
>  /* .text is used instead of .section .text so it works with arm-aout too.  */
>  	.text
>  	.syntax unified
> -#ifdef THUMB_V7_V6M
> +#ifdef PREFER_THUMB
>  	.thumb
>  .macro FUNC_START name
>  	.global \name
> @@ -99,7 +99,7 @@
>  	/*  Issue Angel SWI to read stack info.  */
>  	movs	r0, #AngelSWI_Reason_HeapInfo
>  	adr	r1, .LC0	/*  Point at ptr to 4 words to receive data.  */
> -#ifdef THUMB_V7M_V6M
> +#if !__ARM_ARCH_ISA_ARM
>  	bkpt	AngelSWI
>  #elif defined(__thumb2__)
>  	/*  We are in thumb mode for startup on armv7 architectures.  */
> @@ -176,7 +176,7 @@
>  		 have somehow missed it below (in which case it gets the same
>  		 value as FIQ - not ideal, but better than nothing).  */
>  	mov	sp, r3
> -#ifdef THUMB_V7_V6M
> +#ifdef PREFER_THUMB
>  	/* XXX Fill in stack assignments for interrupt modes.  */
>  #else
>  	mrs	r2, CPSR
> @@ -239,7 +239,7 @@
>  	subs	a3, a3, a1		/* Third arg: length of block.  */
>  	
>  
> -#if defined(__thumb__) && !defined(THUMB_V7_V6M)
> +#if __thumb__ && !defined(PREFER_THUMB)
>  	/* Enter Thumb mode...  */
>  	add	a4, pc, #1	/* Get the address of the Thumb block.  */
>  	bx	a4		/* Go there and start Thumb decoding.  */
> @@ -278,7 +278,7 @@ __change_mode:
>  #else
>  	movs	r0, #AngelSWI_Reason_GetCmdLine
>  	adr	r1, .LC30	/* Space for command line.  */
> -#ifdef THUMB_V7M_V6M
> +#if !__ARM_ARCH_ISA_ARM
>  	bkpt	AngelSWI
>  #else
>   	AngelSWIAsm	AngelSWI
> @@ -404,7 +404,7 @@ __change_mode:
>  
>  	bl	FUNCTION (exit)		/* Should not return.  */
>  
> -#if defined(__thumb__) && !defined(THUMB_V7_V6M)
> +#if __thumb__ && !defined(PREFER_THUMB)
>  	/* Come out of Thumb mode.  This code should be redundant.  */
>  	mov	a4, pc
>  	bx	a4
> diff --git a/newlib/libc/sys/arm/swi.h b/newlib/libc/sys/arm/swi.h
> index 0f93134..76937fa 100644
> --- a/newlib/libc/sys/arm/swi.h
> +++ b/newlib/libc/sys/arm/swi.h
> @@ -36,7 +36,7 @@
>  #define AngelSWI 			AngelSWI_ARM
>  #endif
>  /* For thumb only architectures use the BKPT instruction instead of SWI.  */
> -#ifdef THUMB_V7M_V6M
> +#if !__ARM_ARCH_ISA_ARM
>  #define AngelSWIInsn			"bkpt"
>  #define AngelSWIAsm			bkpt
>  #else
> 
> 
> Tested by building newlib and comparing all *.a and *.o binaries before and
> after with objdump -D and readelf -A for all permutations of:
> 
>   Architectures:
>     armv4 armv4t armv5 armv5t armv5te armv6 armv6j armv6k
>     armv6z armv6kz armv6t2 armv6s-m armv7 armv7-a armv7ve
>     armv7-r armv7-m armv7e-m armv8-a armv8-a+crc iwmmxt
>     iwmmxt2
> 
>   ISAs:
>     thumb arm
> 
>   Optimization Levels:
>     Os O2
> 
>   Excluding:
>     armv6s-m -marm
>     armv7 -marm
>     armv7-m -marm
>     armv7e-m -marm
>     iwmmxt -mthumb
>     iwmmxt2 -mthumb
> 
> as being rejected by the compiler or assembler. ARMv6-m was not tested because compilation fails due to svc instruction.
> 
> Is this ok for the master branch?
> 
> Best regards,
> 
> Thomas
> 



More information about the Newlib mailing list