aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/opcodes.h69
1 files changed, 69 insertions, 0 deletions
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index f57e417cab95..f7937e1c46bf 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);
156 | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \ 156 | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
157) 157)
158 158
159/*
160 * Opcode injection helpers
161 *
162 * In rare cases it is necessary to assemble an opcode which the
163 * assembler does not support directly, or which would normally be
164 * rejected because of the CFLAGS or AFLAGS used to build the affected
165 * file.
166 *
167 * Before using these macros, consider carefully whether it is feasible
168 * instead to change the build flags for your file, or whether it really
169 * makes sense to support old assembler versions when building that
170 * particular kernel feature.
171 *
172 * The macros defined here should only be used where there is no viable
173 * alternative.
174 *
175 *
176 * __inst_arm(x): emit the specified ARM opcode
177 * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
178 * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
179 *
180 * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
181 * 16-bit Thumb opcode, depending on whether an ARM or Thumb-2
182 * kernel is being built
183 *
184 * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
185 * 32-bit Thumb opcode, depending on whether an ARM or Thumb-2
186 * kernel is being built
187 *
188 *
189 * Note that using these macros directly is poor practice. Instead, you
190 * should use them to define human-readable wrapper macros to encode the
191 * instructions that you care about. In code which might run on ARMv7 or
192 * above, you can usually use the __inst_arm_thumb{16,32} macros to
193 * specify the ARM and Thumb alternatives at the same time. This ensures
194 * that the correct opcode gets emitted depending on the instruction set
195 * used for the kernel build.
196 */
197#include <linux/stringify.h>
198
199#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
200#define __inst_thumb32(x) ___inst_thumb32( \
201 ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \
202 ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \
203)
204#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
205
206#ifdef CONFIG_THUMB2_KERNEL
207#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
208 __inst_thumb16(thumb_opcode)
209#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
210 __inst_thumb32(thumb_opcode)
211#else
212#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
213#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
214#endif
215
216/* Helpers for the helpers. Don't use these directly. */
217#ifdef __ASSEMBLY__
218#define ___inst_arm(x) .long x
219#define ___inst_thumb16(x) .short x
220#define ___inst_thumb32(first, second) .short first, second
221#else
222#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
223#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
224#define ___inst_thumb32(first, second) \
225 ".short " __stringify(first) ", " __stringify(second) "\n\t"
226#endif
227
159#endif /* __ASM_ARM_OPCODES_H */ 228#endif /* __ASM_ARM_OPCODES_H */