aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorDave Martin <dave.martin@linaro.org>2012-09-03 08:49:24 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-09-15 16:25:57 -0400
commita61a41a01822d48bbe53e6c1df56b88ee2f3de34 (patch)
tree6cddc5d2834588e739f76e26d8befdbbb4aebba0 /arch/arm
parent0ce3de23f2a520a6ac8c2179fb8f88342c4992ef (diff)
ARM: 7510/1: opcodes: Add helpers for emitting custom opcodes
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. This pure-preprocessor approach is preferred over the alternative method of wedging extra assembler directives into the assembler input using top-level asm() blocks, since there is no way to guarantee that the compiler won't reorder those with respect to each other or with respect to non-toplevel asm() blocks, unless -fno-toplevel-reorder is passed (which is in itself somewhat undesirable because it defeats some potential optimisations). Currently <asm/unified.h> _does_ silently rely on the compiler not reordering at the top level, but it seems better to avoid adding extra code which depends on this if the same result can be achieved in another way. Signed-off-by: Dave Martin <dave.martin@linaro.org> Acked-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-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 */