diff mbox

[3/4] ARM: opcodes: Add helpers for emitting custom opcodes

Message ID 1331829132-9762-4-git-send-email-dave.martin@linaro.org
State Superseded
Headers show

Commit Message

Dave Martin March 15, 2012, 4:32 p.m. UTC
This patch adds some __inst_() macros for injecting custom opcodes
in assembler (both inline and in .S files).  They should make it
easier and cleaner to get things right in little-/big-
endian/ARM/Thumb-2 kernels without a lot of #ifdefs.

Signed-off-by: Dave Martin <dave.martin@linaro.org>
---
 arch/arm/include/asm/opcodes.h |   69 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 69 insertions(+), 0 deletions(-)

Comments

Nicolas Pitre March 15, 2012, 5:54 p.m. UTC | #1
On Thu, 15 Mar 2012, Dave Martin wrote:

> This patch adds some __inst_() macros for injecting custom opcodes
> in assembler (both inline and in .S files).  They should make it
> easier and cleaner to get things right in little-/big-
> endian/ARM/Thumb-2 kernels without a lot of #ifdefs.
> 
> Signed-off-by: Dave Martin <dave.martin@linaro.org>

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


> ---
>  arch/arm/include/asm/opcodes.h |   69 ++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 69 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> index 32730a8..50ef0be 100644
> --- a/arch/arm/include/asm/opcodes.h
> +++ b/arch/arm/include/asm/opcodes.h
> @@ -156,4 +156,73 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
>  	| ___asm_opcode_identity32(___asm_opcode_identity16(second))	    \
>  )
>  
> +/*
> + * Opcode injection helpers
> + *
> + * In rare cases it is necessary to assemble an opcode which the
> + * assembler does not support directly, or which would normally be
> + * rejected because of the CFLAGS or AFLAGS used to build the affected
> + * file.
> + *
> + * Before using these macros, consider carefully whether it is feasible
> + * instead to change the build flags for your file, or whether it really
> + * makes sense to support old assembler versions when building that
> + * particular kernel feature.
> + *
> + * The macros defined here should only be used where there is no viable
> + * alternative.
> + *
> + *
> + * __inst_arm(x): emit the specified ARM opcode
> + * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
> + * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
> + *
> + * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
> + *	16-bit Thumb opcode, depending on whether an ARM or Thumb-2
> + *	kernel is being built
> + *
> + * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
> + *	32-bit Thumb opcode, depending on whether an ARM or Thumb-2
> + *	kernel is being built
> + *
> + *
> + * Note that using these macros directly is poor practice.  Instead, you
> + * should use them to define human-readable wrapper macros to encode the
> + * instructions that you care about.  In code which might run on ARMv7 or
> + * above, you can usually use the __inst_arm_thumb{16,32} macros to
> + * specify the ARM and Thumb alternatives at the same time.  This ensures
> + * that the correct opcode gets emitted depending on the instruction set
> + * used for the kernel build.
> + */
> +#include <linux/stringify.h>
> +
> +#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
> +#define __inst_thumb32(x) ___inst_thumb32(				\
> +	___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)),	\
> +	___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x))	\
> +)
> +#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
> +
> +#ifdef CONFIG_THUMB2_KERNEL
> +#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
> +	__inst_thumb16(thumb_opcode)
> +#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
> +	__inst_thumb32(thumb_opcode)
> +#else
> +#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
> +#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
> +#endif
> +
> +/* Helpers for the helpers.  Don't use these directly. */
> +#ifdef __ASSEMBLY__
> +#define ___inst_arm(x) .long x
> +#define ___inst_thumb16(x) .short x
> +#define ___inst_thumb32(first, second) .short first, second
> +#else
> +#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
> +#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
> +#define ___inst_thumb32(first, second) \
> +	".short " __stringify(first) ", " __stringify(second) "\n\t"
> +#endif
> +
>  #endif /* __ASM_ARM_OPCODES_H */
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
diff mbox

Patch

diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index 32730a8..50ef0be 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -156,4 +156,73 @@  extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
 	| ___asm_opcode_identity32(___asm_opcode_identity16(second))	    \
 )
 
+/*
+ * Opcode injection helpers
+ *
+ * In rare cases it is necessary to assemble an opcode which the
+ * assembler does not support directly, or which would normally be
+ * rejected because of the CFLAGS or AFLAGS used to build the affected
+ * file.
+ *
+ * Before using these macros, consider carefully whether it is feasible
+ * instead to change the build flags for your file, or whether it really
+ * makes sense to support old assembler versions when building that
+ * particular kernel feature.
+ *
+ * The macros defined here should only be used where there is no viable
+ * alternative.
+ *
+ *
+ * __inst_arm(x): emit the specified ARM opcode
+ * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
+ * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
+ *
+ * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
+ *	16-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ *	kernel is being built
+ *
+ * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
+ *	32-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ *	kernel is being built
+ *
+ *
+ * Note that using these macros directly is poor practice.  Instead, you
+ * should use them to define human-readable wrapper macros to encode the
+ * instructions that you care about.  In code which might run on ARMv7 or
+ * above, you can usually use the __inst_arm_thumb{16,32} macros to
+ * specify the ARM and Thumb alternatives at the same time.  This ensures
+ * that the correct opcode gets emitted depending on the instruction set
+ * used for the kernel build.
+ */
+#include <linux/stringify.h>
+
+#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
+#define __inst_thumb32(x) ___inst_thumb32(				\
+	___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)),	\
+	___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x))	\
+)
+#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
+	__inst_thumb16(thumb_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
+	__inst_thumb32(thumb_opcode)
+#else
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#endif
+
+/* Helpers for the helpers.  Don't use these directly. */
+#ifdef __ASSEMBLY__
+#define ___inst_arm(x) .long x
+#define ___inst_thumb16(x) .short x
+#define ___inst_thumb32(first, second) .short first, second
+#else
+#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
+#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
+#define ___inst_thumb32(first, second) \
+	".short " __stringify(first) ", " __stringify(second) "\n\t"
+#endif
+
 #endif /* __ASM_ARM_OPCODES_H */