18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/arm/include/asm/opcodes.h 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef __ASM_ARM_OPCODES_H 78c2ecf20Sopenharmony_ci#define __ASM_ARM_OPCODES_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 108c2ecf20Sopenharmony_ci#include <linux/linkage.h> 118c2ecf20Sopenharmony_ciextern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); 128c2ecf20Sopenharmony_ci#endif 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define ARM_OPCODE_CONDTEST_FAIL 0 158c2ecf20Sopenharmony_ci#define ARM_OPCODE_CONDTEST_PASS 1 168c2ecf20Sopenharmony_ci#define ARM_OPCODE_CONDTEST_UNCOND 2 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * Assembler opcode byteswap helpers. 218c2ecf20Sopenharmony_ci * These are only intended for use by this header: don't use them directly, 228c2ecf20Sopenharmony_ci * because they will be suboptimal in most cases. 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci#define ___asm_opcode_swab32(x) ( \ 258c2ecf20Sopenharmony_ci (((x) << 24) & 0xFF000000) \ 268c2ecf20Sopenharmony_ci | (((x) << 8) & 0x00FF0000) \ 278c2ecf20Sopenharmony_ci | (((x) >> 8) & 0x0000FF00) \ 288c2ecf20Sopenharmony_ci | (((x) >> 24) & 0x000000FF) \ 298c2ecf20Sopenharmony_ci) 308c2ecf20Sopenharmony_ci#define ___asm_opcode_swab16(x) ( \ 318c2ecf20Sopenharmony_ci (((x) << 8) & 0xFF00) \ 328c2ecf20Sopenharmony_ci | (((x) >> 8) & 0x00FF) \ 338c2ecf20Sopenharmony_ci) 348c2ecf20Sopenharmony_ci#define ___asm_opcode_swahb32(x) ( \ 358c2ecf20Sopenharmony_ci (((x) << 8) & 0xFF00FF00) \ 368c2ecf20Sopenharmony_ci | (((x) >> 8) & 0x00FF00FF) \ 378c2ecf20Sopenharmony_ci) 388c2ecf20Sopenharmony_ci#define ___asm_opcode_swahw32(x) ( \ 398c2ecf20Sopenharmony_ci (((x) << 16) & 0xFFFF0000) \ 408c2ecf20Sopenharmony_ci | (((x) >> 16) & 0x0000FFFF) \ 418c2ecf20Sopenharmony_ci) 428c2ecf20Sopenharmony_ci#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF) 438c2ecf20Sopenharmony_ci#define ___asm_opcode_identity16(x) ((x) & 0xFFFF) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci * Opcode byteswap helpers 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * These macros help with converting instructions between a canonical integer 508c2ecf20Sopenharmony_ci * format and in-memory representation, in an endianness-agnostic manner. 518c2ecf20Sopenharmony_ci * 528c2ecf20Sopenharmony_ci * __mem_to_opcode_*() convert from in-memory representation to canonical form. 538c2ecf20Sopenharmony_ci * __opcode_to_mem_*() convert from canonical form to in-memory representation. 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * Canonical instruction representation: 578c2ecf20Sopenharmony_ci * 588c2ecf20Sopenharmony_ci * ARM: 0xKKLLMMNN 598c2ecf20Sopenharmony_ci * Thumb 16-bit: 0x0000KKLL, where KK < 0xE8 608c2ecf20Sopenharmony_ci * Thumb 32-bit: 0xKKLLMMNN, where KK >= 0xE8 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * There is no way to distinguish an ARM instruction in canonical representation 638c2ecf20Sopenharmony_ci * from a Thumb instruction (just as these cannot be distinguished in memory). 648c2ecf20Sopenharmony_ci * Where this distinction is important, it needs to be tracked separately. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not 678c2ecf20Sopenharmony_ci * represent any valid Thumb-2 instruction. For this range, 688c2ecf20Sopenharmony_ci * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false. 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * The ___asm variants are intended only for use by this header, in situations 718c2ecf20Sopenharmony_ci * involving inline assembler. For .S files, the normal __opcode_*() macros 728c2ecf20Sopenharmony_ci * should do the right thing. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_ci#ifdef __ASSEMBLY__ 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define ___opcode_swab32(x) ___asm_opcode_swab32(x) 778c2ecf20Sopenharmony_ci#define ___opcode_swab16(x) ___asm_opcode_swab16(x) 788c2ecf20Sopenharmony_ci#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x) 798c2ecf20Sopenharmony_ci#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x) 808c2ecf20Sopenharmony_ci#define ___opcode_identity32(x) ___asm_opcode_identity32(x) 818c2ecf20Sopenharmony_ci#define ___opcode_identity16(x) ___asm_opcode_identity16(x) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#else /* ! __ASSEMBLY__ */ 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#include <linux/types.h> 868c2ecf20Sopenharmony_ci#include <linux/swab.h> 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define ___opcode_swab32(x) swab32(x) 898c2ecf20Sopenharmony_ci#define ___opcode_swab16(x) swab16(x) 908c2ecf20Sopenharmony_ci#define ___opcode_swahb32(x) swahb32(x) 918c2ecf20Sopenharmony_ci#define ___opcode_swahw32(x) swahw32(x) 928c2ecf20Sopenharmony_ci#define ___opcode_identity32(x) ((u32)(x)) 938c2ecf20Sopenharmony_ci#define ___opcode_identity16(x) ((u16)(x)) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#endif /* ! __ASSEMBLY__ */ 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_ENDIAN_BE8 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define __opcode_to_mem_arm(x) ___opcode_swab32(x) 1018c2ecf20Sopenharmony_ci#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x) 1028c2ecf20Sopenharmony_ci#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x) 1038c2ecf20Sopenharmony_ci#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x) 1048c2ecf20Sopenharmony_ci#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x) 1058c2ecf20Sopenharmony_ci#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x) 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci#else /* ! CONFIG_CPU_ENDIAN_BE8 */ 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define __opcode_to_mem_arm(x) ___opcode_identity32(x) 1108c2ecf20Sopenharmony_ci#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x) 1118c2ecf20Sopenharmony_ci#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x) 1128c2ecf20Sopenharmony_ci#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x) 1138c2ecf20Sopenharmony_ci#ifndef CONFIG_CPU_ENDIAN_BE32 1148c2ecf20Sopenharmony_ci/* 1158c2ecf20Sopenharmony_ci * On BE32 systems, using 32-bit accesses to store Thumb instructions will not 1168c2ecf20Sopenharmony_ci * work in all cases, due to alignment constraints. For now, a correct 1178c2ecf20Sopenharmony_ci * version is not provided for BE32. 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_ci#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x) 1208c2ecf20Sopenharmony_ci#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x) 1218c2ecf20Sopenharmony_ci#endif 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#endif /* ! CONFIG_CPU_ENDIAN_BE8 */ 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x) 1268c2ecf20Sopenharmony_ci#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x) 1278c2ecf20Sopenharmony_ci#ifndef CONFIG_CPU_ENDIAN_BE32 1288c2ecf20Sopenharmony_ci#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x) 1298c2ecf20Sopenharmony_ci#endif 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* Operations specific to Thumb opcodes */ 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* Instruction size checks: */ 1348c2ecf20Sopenharmony_ci#define __opcode_is_thumb32(x) ( \ 1358c2ecf20Sopenharmony_ci ((x) & 0xF8000000) == 0xE8000000 \ 1368c2ecf20Sopenharmony_ci || ((x) & 0xF0000000) == 0xF0000000 \ 1378c2ecf20Sopenharmony_ci) 1388c2ecf20Sopenharmony_ci#define __opcode_is_thumb16(x) ( \ 1398c2ecf20Sopenharmony_ci ((x) & 0xFFFF0000) == 0 \ 1408c2ecf20Sopenharmony_ci && !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \ 1418c2ecf20Sopenharmony_ci) 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/* Operations to construct or split 32-bit Thumb instructions: */ 1448c2ecf20Sopenharmony_ci#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16)) 1458c2ecf20Sopenharmony_ci#define __opcode_thumb32_second(x) (___opcode_identity16(x)) 1468c2ecf20Sopenharmony_ci#define __opcode_thumb32_compose(first, second) ( \ 1478c2ecf20Sopenharmony_ci (___opcode_identity32(___opcode_identity16(first)) << 16) \ 1488c2ecf20Sopenharmony_ci | ___opcode_identity32(___opcode_identity16(second)) \ 1498c2ecf20Sopenharmony_ci) 1508c2ecf20Sopenharmony_ci#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16)) 1518c2ecf20Sopenharmony_ci#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x)) 1528c2ecf20Sopenharmony_ci#define ___asm_opcode_thumb32_compose(first, second) ( \ 1538c2ecf20Sopenharmony_ci (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \ 1548c2ecf20Sopenharmony_ci | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \ 1558c2ecf20Sopenharmony_ci) 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/* 1588c2ecf20Sopenharmony_ci * Opcode injection helpers 1598c2ecf20Sopenharmony_ci * 1608c2ecf20Sopenharmony_ci * In rare cases it is necessary to assemble an opcode which the 1618c2ecf20Sopenharmony_ci * assembler does not support directly, or which would normally be 1628c2ecf20Sopenharmony_ci * rejected because of the CFLAGS or AFLAGS used to build the affected 1638c2ecf20Sopenharmony_ci * file. 1648c2ecf20Sopenharmony_ci * 1658c2ecf20Sopenharmony_ci * Before using these macros, consider carefully whether it is feasible 1668c2ecf20Sopenharmony_ci * instead to change the build flags for your file, or whether it really 1678c2ecf20Sopenharmony_ci * makes sense to support old assembler versions when building that 1688c2ecf20Sopenharmony_ci * particular kernel feature. 1698c2ecf20Sopenharmony_ci * 1708c2ecf20Sopenharmony_ci * The macros defined here should only be used where there is no viable 1718c2ecf20Sopenharmony_ci * alternative. 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * 1748c2ecf20Sopenharmony_ci * __inst_arm(x): emit the specified ARM opcode 1758c2ecf20Sopenharmony_ci * __inst_thumb16(x): emit the specified 16-bit Thumb opcode 1768c2ecf20Sopenharmony_ci * __inst_thumb32(x): emit the specified 32-bit Thumb opcode 1778c2ecf20Sopenharmony_ci * 1788c2ecf20Sopenharmony_ci * __inst_arm_thumb16(arm, thumb): emit either the specified arm or 1798c2ecf20Sopenharmony_ci * 16-bit Thumb opcode, depending on whether an ARM or Thumb-2 1808c2ecf20Sopenharmony_ci * kernel is being built 1818c2ecf20Sopenharmony_ci * 1828c2ecf20Sopenharmony_ci * __inst_arm_thumb32(arm, thumb): emit either the specified arm or 1838c2ecf20Sopenharmony_ci * 32-bit Thumb opcode, depending on whether an ARM or Thumb-2 1848c2ecf20Sopenharmony_ci * kernel is being built 1858c2ecf20Sopenharmony_ci * 1868c2ecf20Sopenharmony_ci * 1878c2ecf20Sopenharmony_ci * Note that using these macros directly is poor practice. Instead, you 1888c2ecf20Sopenharmony_ci * should use them to define human-readable wrapper macros to encode the 1898c2ecf20Sopenharmony_ci * instructions that you care about. In code which might run on ARMv7 or 1908c2ecf20Sopenharmony_ci * above, you can usually use the __inst_arm_thumb{16,32} macros to 1918c2ecf20Sopenharmony_ci * specify the ARM and Thumb alternatives at the same time. This ensures 1928c2ecf20Sopenharmony_ci * that the correct opcode gets emitted depending on the instruction set 1938c2ecf20Sopenharmony_ci * used for the kernel build. 1948c2ecf20Sopenharmony_ci * 1958c2ecf20Sopenharmony_ci * Look at opcodes-virt.h for an example of how to use these macros. 1968c2ecf20Sopenharmony_ci */ 1978c2ecf20Sopenharmony_ci#include <linux/stringify.h> 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x)) 2008c2ecf20Sopenharmony_ci#define __inst_thumb32(x) ___inst_thumb32( \ 2018c2ecf20Sopenharmony_ci ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \ 2028c2ecf20Sopenharmony_ci ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \ 2038c2ecf20Sopenharmony_ci) 2048c2ecf20Sopenharmony_ci#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x)) 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL 2078c2ecf20Sopenharmony_ci#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \ 2088c2ecf20Sopenharmony_ci __inst_thumb16(thumb_opcode) 2098c2ecf20Sopenharmony_ci#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \ 2108c2ecf20Sopenharmony_ci __inst_thumb32(thumb_opcode) 2118c2ecf20Sopenharmony_ci#else 2128c2ecf20Sopenharmony_ci#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode) 2138c2ecf20Sopenharmony_ci#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode) 2148c2ecf20Sopenharmony_ci#endif 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/* Helpers for the helpers. Don't use these directly. */ 2178c2ecf20Sopenharmony_ci#ifdef __ASSEMBLY__ 2188c2ecf20Sopenharmony_ci#define ___inst_arm(x) .long x 2198c2ecf20Sopenharmony_ci#define ___inst_thumb16(x) .short x 2208c2ecf20Sopenharmony_ci#define ___inst_thumb32(first, second) .short first, second 2218c2ecf20Sopenharmony_ci#else 2228c2ecf20Sopenharmony_ci#define ___inst_arm(x) ".long " __stringify(x) "\n\t" 2238c2ecf20Sopenharmony_ci#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t" 2248c2ecf20Sopenharmony_ci#define ___inst_thumb32(first, second) \ 2258c2ecf20Sopenharmony_ci ".short " __stringify(first) ", " __stringify(second) "\n\t" 2268c2ecf20Sopenharmony_ci#endif 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#endif /* __ASM_ARM_OPCODES_H */ 229