[PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible

Nicolas Pitre nicolas.pitre at linaro.org
Thu Mar 15 13:53:20 EDT 2012


On Thu, 15 Mar 2012, Dave Martin wrote:

> Most of the existing macros don't work with assembler, due to the
> use of type casts and C functions from <linux/swab.h>.
> 
> This patch abstracts out those operations and provides simple
> explicit versions for use in assembly code.
> 
> __opcode_is_thumb32() and __opcode_is_thumb16() are also converted
> to do bitmask-based testing to avoid confusion if these are used in
> assembly code (the assembler typically treats all arithmetic values
> as signed).
> 
> Signed-off-by: Dave Martin <dave.martin at linaro.org>

OK.  One really has to read through the whole series to see the point of 
this.

Acked-by: Nicolas Pitre <nico at linaro.org>



> ---
>  arch/arm/include/asm/opcodes.h |   97 +++++++++++++++++++++++++++++++++------
>  1 files changed, 82 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> index cf877c8..32730a8 100644
> --- a/arch/arm/include/asm/opcodes.h
> +++ b/arch/arm/include/asm/opcodes.h
> @@ -19,6 +19,33 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
>  
>  
>  /*
> + * Assembler opcode byteswap helpers.
> + * These are only intended for use by this header: don't use them directly,
> + * because they will be suboptimal in most cases.
> + */
> +#define ___asm_opcode_swab32(x) (	\
> +	  (((x) << 24) & 0xFF000000)	\
> +	| (((x) <<  8) & 0x00FF0000)	\
> +	| (((x) >>  8) & 0x0000FF00)	\
> +	| (((x) >> 24) & 0x000000FF)	\
> +)
> +#define ___asm_opcode_swab16(x) (	\
> +	  (((x) << 8) & 0xFF00)		\
> +	| (((x) >> 8) & 0x00FF)		\
> +)
> +#define ___asm_opcode_swahb32(x) (	\
> +	  (((x) << 8) & 0xFF00FF00)	\
> +	| (((x) >> 8) & 0x00FF00FF)	\
> +)
> +#define ___asm_opcode_swahw32(x) (	\
> +	  (((x) << 16) & 0xFFFF0000)	\
> +	| (((x) >> 16) & 0x0000FFFF)	\
> +)
> +#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
> +#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
> +
> +
> +/*
>   * Opcode byteswap helpers
>   *
>   * These macros help with converting instructions between a canonical integer
> @@ -41,30 +68,58 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
>   * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
>   * represent any valid Thumb-2 instruction.  For this range,
>   * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
> + *
> + * The ___asm variants are intended only for use by this header, in situations
> + * involving inline assembler.  For .S files, the normal __opcode_*() macros
> + * should do the right thing.
>   */
> +#ifdef __ASSEMBLY__
>  
> -#ifndef __ASSEMBLY__
> +#define ___opcode_swab32(x) ___asm_opcode_swab32(x)
> +#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
> +#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
> +#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
> +#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
> +#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
> +
> +#else /* ! __ASSEMBLY__ */
>  
>  #include <linux/types.h>
>  #include <linux/swab.h>
>  
> +#define ___opcode_swab32(x) swab32(x)
> +#define ___opcode_swab16(x) swab16(x)
> +#define ___opcode_swahb32(x) swahb32(x)
> +#define ___opcode_swahw32(x) swahw32(x)
> +#define ___opcode_identity32(x) ((u32)(x))
> +#define ___opcode_identity16(x) ((u16)(x))
> +
> +#endif /* ! __ASSEMBLY__ */
> +
> +
>  #ifdef CONFIG_CPU_ENDIAN_BE8
>  
> -#define __opcode_to_mem_arm(x) swab32(x)
> -#define __opcode_to_mem_thumb16(x) swab16(x)
> -#define __opcode_to_mem_thumb32(x) swahb32(x)
> +#define __opcode_to_mem_arm(x) ___opcode_swab32(x)
> +#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
> +#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
> +#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
> +#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
> +#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
>  
>  #else /* ! CONFIG_CPU_ENDIAN_BE8 */
>  
> -#define __opcode_to_mem_arm(x) ((u32)(x))
> -#define __opcode_to_mem_thumb16(x) ((u16)(x))
> +#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
> +#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
> +#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
> +#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
>  #ifndef CONFIG_CPU_ENDIAN_BE32
>  /*
>   * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
>   * work in all cases, due to alignment constraints.  For now, a correct
>   * version is not proivided for BE32.
>   */
> -#define __opcode_to_mem_thumb32(x) swahw32(x)
> +#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
> +#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
>  #endif
>  
>  #endif /* ! CONFIG_CPU_ENDIAN_BE8 */
> @@ -78,15 +133,27 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
>  /* Operations specific to Thumb opcodes */
>  
>  /* Instruction size checks: */
> -#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
> -#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
> +#define __opcode_is_thumb32(x) (		\
> +	   ((x) & 0xF8000000) == 0xE8000000	\
> +	|| ((x) & 0xF0000000) == 0xF0000000	\
> +)
> +#define __opcode_is_thumb16(x) (					\
> +	   ((x) & 0xFFFF0000) == 0					\
> +	&& !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000)	\
> +)
>  
>  /* Operations to construct or split 32-bit Thumb instructions: */
> -#define __opcode_thumb32_first(x) ((u16)((x) >> 16))
> -#define __opcode_thumb32_second(x) ((u16)(x))
> -#define __opcode_thumb32_compose(first, second) \
> -	(((u32)(u16)(first) << 16) | (u32)(u16)(second))
> -
> -#endif /* __ASSEMBLY__ */
> +#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
> +#define __opcode_thumb32_second(x) (___opcode_identity16(x))
> +#define __opcode_thumb32_compose(first, second) (			\
> +	  (___opcode_identity32(___opcode_identity16(first)) << 16)	\
> +	| ___opcode_identity32(___opcode_identity16(second))		\
> +)
> +#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
> +#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
> +#define ___asm_opcode_thumb32_compose(first, second) (			    \
> +	  (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
> +	| ___asm_opcode_identity32(___asm_opcode_identity16(second))	    \
> +)
>  
>  #endif /* __ASM_ARM_OPCODES_H */
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 



More information about the linux-arm-kernel mailing list