diff options
author | Dave Martin <dave.martin@linaro.org> | 2012-02-01 04:42:22 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-03-24 05:38:51 -0400 |
commit | f5f5195487affe53f90d99cba4aee73a20cae565 (patch) | |
tree | 3c2f539c086a42f2056b3979be29de15022438da /arch/arm/include/asm | |
parent | a9d6d15131b0519363b0c94734ee80955c411093 (diff) |
ARM: 7311/1: Add generic instruction opcode manipulation helpers
This patch adds some endianness-agnostic helpers to convert machine
instructions between canonical integer form and in-memory
representation.
A canonical integer form for representing instructions is also
formalised here.
Signed-off-by: Dave Martin <dave.martin@linaro.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Jon Medhurst <tixy@yxit.co.uk>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/include/asm')
-rw-r--r-- | arch/arm/include/asm/opcodes.h | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h index c0efdd60966f..19c48deda70f 100644 --- a/arch/arm/include/asm/opcodes.h +++ b/arch/arm/include/asm/opcodes.h | |||
@@ -17,4 +17,63 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); | |||
17 | #define ARM_OPCODE_CONDTEST_PASS 1 | 17 | #define ARM_OPCODE_CONDTEST_PASS 1 |
18 | #define ARM_OPCODE_CONDTEST_UNCOND 2 | 18 | #define ARM_OPCODE_CONDTEST_UNCOND 2 |
19 | 19 | ||
20 | |||
21 | /* | ||
22 | * Opcode byteswap helpers | ||
23 | * | ||
24 | * These macros help with converting instructions between a canonical integer | ||
25 | * format and in-memory representation, in an endianness-agnostic manner. | ||
26 | * | ||
27 | * __mem_to_opcode_*() convert from in-memory representation to canonical form. | ||
28 | * __opcode_to_mem_*() convert from canonical form to in-memory representation. | ||
29 | * | ||
30 | * | ||
31 | * Canonical instruction representation: | ||
32 | * | ||
33 | * ARM: 0xKKLLMMNN | ||
34 | * Thumb 16-bit: 0x0000KKLL, where KK < 0xE8 | ||
35 | * Thumb 32-bit: 0xKKLLMMNN, where KK >= 0xE8 | ||
36 | * | ||
37 | * There is no way to distinguish an ARM instruction in canonical representation | ||
38 | * from a Thumb instruction (just as these cannot be distinguished in memory). | ||
39 | * Where this distinction is important, it needs to be tracked separately. | ||
40 | * | ||
41 | * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not | ||
42 | * represent any valid Thumb-2 instruction. For this range, | ||
43 | * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false. | ||
44 | */ | ||
45 | |||
46 | #ifndef __ASSEMBLY__ | ||
47 | |||
48 | #include <linux/types.h> | ||
49 | #include <linux/swab.h> | ||
50 | |||
51 | #ifdef CONFIG_CPU_ENDIAN_BE8 | ||
52 | #define __opcode_to_mem_arm(x) swab32(x) | ||
53 | #define __opcode_to_mem_thumb16(x) swab16(x) | ||
54 | #define __opcode_to_mem_thumb32(x) swahb32(x) | ||
55 | #else | ||
56 | #define __opcode_to_mem_arm(x) ((u32)(x)) | ||
57 | #define __opcode_to_mem_thumb16(x) ((u16)(x)) | ||
58 | #define __opcode_to_mem_thumb32(x) swahw32(x) | ||
59 | #endif | ||
60 | |||
61 | #define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x) | ||
62 | #define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x) | ||
63 | #define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x) | ||
64 | |||
65 | /* Operations specific to Thumb opcodes */ | ||
66 | |||
67 | /* Instruction size checks: */ | ||
68 | #define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL) | ||
69 | #define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL) | ||
70 | |||
71 | /* Operations to construct or split 32-bit Thumb instructions: */ | ||
72 | #define __opcode_thumb32_first(x) ((u16)((x) >> 16)) | ||
73 | #define __opcode_thumb32_second(x) ((u16)(x)) | ||
74 | #define __opcode_thumb32_compose(first, second) \ | ||
75 | (((u32)(u16)(first) << 16) | (u32)(u16)(second)) | ||
76 | |||
77 | #endif /* __ASSEMBLY__ */ | ||
78 | |||
20 | #endif /* __ASM_ARM_OPCODES_H */ | 79 | #endif /* __ASM_ARM_OPCODES_H */ |