Message ID | 1331829132-9762-4-git-send-email-dave.martin@linaro.org |
---|---|
State | Superseded |
Headers | show |
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 --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 */
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(-)