|
@@ -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 */
|