162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/include/asm/opcodes.h 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef __ASM_ARM_OPCODES_H 762306a36Sopenharmony_ci#define __ASM_ARM_OPCODES_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 1062306a36Sopenharmony_ci#include <linux/linkage.h> 1162306a36Sopenharmony_ciextern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); 1262306a36Sopenharmony_ci#endif 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define ARM_OPCODE_CONDTEST_FAIL 0 1562306a36Sopenharmony_ci#define ARM_OPCODE_CONDTEST_PASS 1 1662306a36Sopenharmony_ci#define ARM_OPCODE_CONDTEST_UNCOND 2 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * Assembler opcode byteswap helpers. 2162306a36Sopenharmony_ci * These are only intended for use by this header: don't use them directly, 2262306a36Sopenharmony_ci * because they will be suboptimal in most cases. 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci#define ___asm_opcode_swab32(x) ( \ 2562306a36Sopenharmony_ci (((x) << 24) & 0xFF000000) \ 2662306a36Sopenharmony_ci | (((x) << 8) & 0x00FF0000) \ 2762306a36Sopenharmony_ci | (((x) >> 8) & 0x0000FF00) \ 2862306a36Sopenharmony_ci | (((x) >> 24) & 0x000000FF) \ 2962306a36Sopenharmony_ci) 3062306a36Sopenharmony_ci#define ___asm_opcode_swab16(x) ( \ 3162306a36Sopenharmony_ci (((x) << 8) & 0xFF00) \ 3262306a36Sopenharmony_ci | (((x) >> 8) & 0x00FF) \ 3362306a36Sopenharmony_ci) 3462306a36Sopenharmony_ci#define ___asm_opcode_swahb32(x) ( \ 3562306a36Sopenharmony_ci (((x) << 8) & 0xFF00FF00) \ 3662306a36Sopenharmony_ci | (((x) >> 8) & 0x00FF00FF) \ 3762306a36Sopenharmony_ci) 3862306a36Sopenharmony_ci#define ___asm_opcode_swahw32(x) ( \ 3962306a36Sopenharmony_ci (((x) << 16) & 0xFFFF0000) \ 4062306a36Sopenharmony_ci | (((x) >> 16) & 0x0000FFFF) \ 4162306a36Sopenharmony_ci) 4262306a36Sopenharmony_ci#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF) 4362306a36Sopenharmony_ci#define ___asm_opcode_identity16(x) ((x) & 0xFFFF) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * Opcode byteswap helpers 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * These macros help with converting instructions between a canonical integer 5062306a36Sopenharmony_ci * format and in-memory representation, in an endianness-agnostic manner. 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * __mem_to_opcode_*() convert from in-memory representation to canonical form. 5362306a36Sopenharmony_ci * __opcode_to_mem_*() convert from canonical form to in-memory representation. 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * Canonical instruction representation: 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * ARM: 0xKKLLMMNN 5962306a36Sopenharmony_ci * Thumb 16-bit: 0x0000KKLL, where KK < 0xE8 6062306a36Sopenharmony_ci * Thumb 32-bit: 0xKKLLMMNN, where KK >= 0xE8 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * There is no way to distinguish an ARM instruction in canonical representation 6362306a36Sopenharmony_ci * from a Thumb instruction (just as these cannot be distinguished in memory). 6462306a36Sopenharmony_ci * Where this distinction is important, it needs to be tracked separately. 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not 6762306a36Sopenharmony_ci * represent any valid Thumb-2 instruction. For this range, 6862306a36Sopenharmony_ci * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * The ___asm variants are intended only for use by this header, in situations 7162306a36Sopenharmony_ci * involving inline assembler. For .S files, the normal __opcode_*() macros 7262306a36Sopenharmony_ci * should do the right thing. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci#ifdef __ASSEMBLY__ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define ___opcode_swab32(x) ___asm_opcode_swab32(x) 7762306a36Sopenharmony_ci#define ___opcode_swab16(x) ___asm_opcode_swab16(x) 7862306a36Sopenharmony_ci#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x) 7962306a36Sopenharmony_ci#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x) 8062306a36Sopenharmony_ci#define ___opcode_identity32(x) ___asm_opcode_identity32(x) 8162306a36Sopenharmony_ci#define ___opcode_identity16(x) ___asm_opcode_identity16(x) 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#else /* ! __ASSEMBLY__ */ 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#include <linux/types.h> 8662306a36Sopenharmony_ci#include <linux/swab.h> 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define ___opcode_swab32(x) swab32(x) 8962306a36Sopenharmony_ci#define ___opcode_swab16(x) swab16(x) 9062306a36Sopenharmony_ci#define ___opcode_swahb32(x) swahb32(x) 9162306a36Sopenharmony_ci#define ___opcode_swahw32(x) swahw32(x) 9262306a36Sopenharmony_ci#define ___opcode_identity32(x) ((u32)(x)) 9362306a36Sopenharmony_ci#define ___opcode_identity16(x) ((u16)(x)) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#endif /* ! __ASSEMBLY__ */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define __opcode_to_mem_arm(x) ___opcode_swab32(x) 10162306a36Sopenharmony_ci#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x) 10262306a36Sopenharmony_ci#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x) 10362306a36Sopenharmony_ci#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x) 10462306a36Sopenharmony_ci#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x) 10562306a36Sopenharmony_ci#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x) 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#else /* ! CONFIG_CPU_ENDIAN_BE8 */ 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define __opcode_to_mem_arm(x) ___opcode_identity32(x) 11062306a36Sopenharmony_ci#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x) 11162306a36Sopenharmony_ci#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x) 11262306a36Sopenharmony_ci#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x) 11362306a36Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE32 11462306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * On BE32 systems, using 32-bit accesses to store Thumb instructions will not 11762306a36Sopenharmony_ci * work in all cases, due to alignment constraints. For now, a correct 11862306a36Sopenharmony_ci * version is not provided for BE32, but the prototype needs to be there 11962306a36Sopenharmony_ci * to compile patch.c. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ciextern __u32 __opcode_to_mem_thumb32(__u32); 12262306a36Sopenharmony_ci#endif 12362306a36Sopenharmony_ci#else 12462306a36Sopenharmony_ci#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x) 12562306a36Sopenharmony_ci#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x) 12662306a36Sopenharmony_ci#endif 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#endif /* ! CONFIG_CPU_ENDIAN_BE8 */ 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x) 13162306a36Sopenharmony_ci#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x) 13262306a36Sopenharmony_ci#ifndef CONFIG_CPU_ENDIAN_BE32 13362306a36Sopenharmony_ci#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x) 13462306a36Sopenharmony_ci#endif 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* Operations specific to Thumb opcodes */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/* Instruction size checks: */ 13962306a36Sopenharmony_ci#define __opcode_is_thumb32(x) ( \ 14062306a36Sopenharmony_ci ((x) & 0xF8000000) == 0xE8000000 \ 14162306a36Sopenharmony_ci || ((x) & 0xF0000000) == 0xF0000000 \ 14262306a36Sopenharmony_ci) 14362306a36Sopenharmony_ci#define __opcode_is_thumb16(x) ( \ 14462306a36Sopenharmony_ci ((x) & 0xFFFF0000) == 0 \ 14562306a36Sopenharmony_ci && !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \ 14662306a36Sopenharmony_ci) 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* Operations to construct or split 32-bit Thumb instructions: */ 14962306a36Sopenharmony_ci#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16)) 15062306a36Sopenharmony_ci#define __opcode_thumb32_second(x) (___opcode_identity16(x)) 15162306a36Sopenharmony_ci#define __opcode_thumb32_compose(first, second) ( \ 15262306a36Sopenharmony_ci (___opcode_identity32(___opcode_identity16(first)) << 16) \ 15362306a36Sopenharmony_ci | ___opcode_identity32(___opcode_identity16(second)) \ 15462306a36Sopenharmony_ci) 15562306a36Sopenharmony_ci#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16)) 15662306a36Sopenharmony_ci#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x)) 15762306a36Sopenharmony_ci#define ___asm_opcode_thumb32_compose(first, second) ( \ 15862306a36Sopenharmony_ci (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \ 15962306a36Sopenharmony_ci | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \ 16062306a36Sopenharmony_ci) 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci/* 16362306a36Sopenharmony_ci * Opcode injection helpers 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * In rare cases it is necessary to assemble an opcode which the 16662306a36Sopenharmony_ci * assembler does not support directly, or which would normally be 16762306a36Sopenharmony_ci * rejected because of the CFLAGS or AFLAGS used to build the affected 16862306a36Sopenharmony_ci * file. 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci * Before using these macros, consider carefully whether it is feasible 17162306a36Sopenharmony_ci * instead to change the build flags for your file, or whether it really 17262306a36Sopenharmony_ci * makes sense to support old assembler versions when building that 17362306a36Sopenharmony_ci * particular kernel feature. 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci * The macros defined here should only be used where there is no viable 17662306a36Sopenharmony_ci * alternative. 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci * 17962306a36Sopenharmony_ci * __inst_arm(x): emit the specified ARM opcode 18062306a36Sopenharmony_ci * __inst_thumb16(x): emit the specified 16-bit Thumb opcode 18162306a36Sopenharmony_ci * __inst_thumb32(x): emit the specified 32-bit Thumb opcode 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * __inst_arm_thumb16(arm, thumb): emit either the specified arm or 18462306a36Sopenharmony_ci * 16-bit Thumb opcode, depending on whether an ARM or Thumb-2 18562306a36Sopenharmony_ci * kernel is being built 18662306a36Sopenharmony_ci * 18762306a36Sopenharmony_ci * __inst_arm_thumb32(arm, thumb): emit either the specified arm or 18862306a36Sopenharmony_ci * 32-bit Thumb opcode, depending on whether an ARM or Thumb-2 18962306a36Sopenharmony_ci * kernel is being built 19062306a36Sopenharmony_ci * 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * Note that using these macros directly is poor practice. Instead, you 19362306a36Sopenharmony_ci * should use them to define human-readable wrapper macros to encode the 19462306a36Sopenharmony_ci * instructions that you care about. In code which might run on ARMv7 or 19562306a36Sopenharmony_ci * above, you can usually use the __inst_arm_thumb{16,32} macros to 19662306a36Sopenharmony_ci * specify the ARM and Thumb alternatives at the same time. This ensures 19762306a36Sopenharmony_ci * that the correct opcode gets emitted depending on the instruction set 19862306a36Sopenharmony_ci * used for the kernel build. 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * Look at opcodes-virt.h for an example of how to use these macros. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci#include <linux/stringify.h> 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x)) 20562306a36Sopenharmony_ci#define __inst_thumb32(x) ___inst_thumb32( \ 20662306a36Sopenharmony_ci ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \ 20762306a36Sopenharmony_ci ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \ 20862306a36Sopenharmony_ci) 20962306a36Sopenharmony_ci#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x)) 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 21262306a36Sopenharmony_ci#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \ 21362306a36Sopenharmony_ci __inst_thumb16(thumb_opcode) 21462306a36Sopenharmony_ci#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \ 21562306a36Sopenharmony_ci __inst_thumb32(thumb_opcode) 21662306a36Sopenharmony_ci#else 21762306a36Sopenharmony_ci#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode) 21862306a36Sopenharmony_ci#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode) 21962306a36Sopenharmony_ci#endif 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci/* Helpers for the helpers. Don't use these directly. */ 22262306a36Sopenharmony_ci#ifdef __ASSEMBLY__ 22362306a36Sopenharmony_ci#define ___inst_arm(x) .long x 22462306a36Sopenharmony_ci#define ___inst_thumb16(x) .short x 22562306a36Sopenharmony_ci#define ___inst_thumb32(first, second) .short first, second 22662306a36Sopenharmony_ci#else 22762306a36Sopenharmony_ci#define ___inst_arm(x) ".long " __stringify(x) "\n\t" 22862306a36Sopenharmony_ci#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t" 22962306a36Sopenharmony_ci#define ___inst_thumb32(first, second) \ 23062306a36Sopenharmony_ci ".short " __stringify(first) ", " __stringify(second) "\n\t" 23162306a36Sopenharmony_ci#endif 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci#endif /* __ASM_ARM_OPCODES_H */ 234