From patchwork Tue Jan 17 09:55:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Martin X-Patchwork-Id: 6251 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 5B8B323E01 for ; Tue, 17 Jan 2012 09:56:05 +0000 (UTC) Received: from mail-bk0-f52.google.com (mail-bk0-f52.google.com [209.85.214.52]) by fiordland.canonical.com (Postfix) with ESMTP id 3D369A182C0 for ; Tue, 17 Jan 2012 09:56:05 +0000 (UTC) Received: by bkbzt4 with SMTP id zt4so1476291bkb.11 for ; Tue, 17 Jan 2012 01:56:05 -0800 (PST) Received: by 10.204.41.143 with SMTP id o15mr6484370bke.63.1326794164882; Tue, 17 Jan 2012 01:56:04 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.205.82.144 with SMTP id ac16cs114828bkc; Tue, 17 Jan 2012 01:56:04 -0800 (PST) Received: by 10.180.101.101 with SMTP id ff5mr21439307wib.14.1326794162732; Tue, 17 Jan 2012 01:56:02 -0800 (PST) Received: from mail-wi0-f178.google.com (mail-wi0-f178.google.com [209.85.212.178]) by mx.google.com with ESMTPS id u17si12097412wec.121.2012.01.17.01.56.02 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 17 Jan 2012 01:56:02 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.178 is neither permitted nor denied by best guess record for domain of dave.martin@linaro.org) client-ip=209.85.212.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.178 is neither permitted nor denied by best guess record for domain of dave.martin@linaro.org) smtp.mail=dave.martin@linaro.org Received: by wibhn3 with SMTP id hn3so446020wib.37 for ; Tue, 17 Jan 2012 01:56:02 -0800 (PST) Received: by 10.180.101.101 with SMTP id ff5mr21439190wib.14.1326794161891; Tue, 17 Jan 2012 01:56:01 -0800 (PST) Received: from e103592.peterhouse.linaro.org (fw-lnat.cambridge.arm.com. [217.140.96.63]) by mx.google.com with ESMTPS id dr5sm42270684wib.0.2012.01.17.01.56.00 (version=SSLv3 cipher=OTHER); Tue, 17 Jan 2012 01:56:01 -0800 (PST) From: Dave Martin To: patches@arm.linux.org.uk Cc: patches@linaro.org, Dave Martin Subject: [PATCH v4] ARM: Add generic instruction opcode manipulation helpers Date: Tue, 17 Jan 2012 09:55:51 +0000 Message-Id: <1326794151-12297-1-git-send-email-dave.martin@linaro.org> X-Mailer: git-send-email 1.7.4.1 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 Acked-by: Nicolas Pitre --- KernelVersion: next-20120113 Changes since v1: v4: Rebase on top of Leif's patch which created ARM: 7206/1: Add generic ARM instruction set condition code checks. No functional changes. v3: Fix some stupid errors: * remove bogus extra (x) in __opcode_to_mem_arm * fix use of nonexistent "thumb_opcode" argument in __opcode_thumb32_{first,second} which causes these macros to be broken. v2: Remove unnecessary typedef for arm_opcode_t. The general "everything is a word" concept works just fine here -- we don't need a typedef, and people will probably not use it anyway. arch/arm/include/asm/opcodes.h | 68 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 68 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/opcodes.h diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h new file mode 100644 index 0000000..eed11db --- /dev/null +++ b/arch/arm/include/asm/opcodes.h @@ -0,0 +1,68 @@ +/* + * arch/arm/include/asm/opcodes.h + * + * Copyright (C) 2011 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ARM_OPCODES_H +#define __ARM_OPCODES_H + +#include +#include + +/* + * Canonical instruction representation: + * + * ARM: 0xKKLLMMNN + * Thumb 16-bit: 0x0000KKLL, where KK < 0xE8 + * Thumb 32-bit: 0xKKLLMMNN, where KK >= 0xE8 + * + * There is no way to distinguish an ARM instruction in canonical representation + * from a Thumb instruction (just as these cannot be distinguished in memory). + * Where this distinction is important, it needs to be tracked separately. + * + * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not + * represent any valid Thumb-2 instruction. For this range, + * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false. + */ + +#ifdef CONFIG_CPU_ENDIAN_BE8 +#define __opcode_to_mem_arm(x) swab32(x) +#define __opcode_to_mem_thumb16(x) swab16(x) +#define __opcode_to_mem_thumb32(x) swahb32(x) +#else +#define __opcode_to_mem_arm(x) ((u32)(x)) +#define __opcode_to_mem_thumb16(x) ((u16)(x)) +#define __opcode_to_mem_thumb32(x) swahw32(x) +#endif + +#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x) +#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x) +#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x) + +/* Operations specific to Thumb opcodes */ + +/* Instruction size checks: */ +#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL) +#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL) + +/* Operations to construct or split 32-bit Thumb instructions: */ +#define __opcode_thumb32_first(x) ((u16)((x) >> 16)) +#define __opcode_thumb32_second(x) ((u16)(x)) +#define __opcode_thumb32_compose(first, second) \ + (((u32)(u16)(first) << 16) | (u32)(u16)(second)) + +#endif /* ! __ARM_OPCODES_H */ -- 1.7.4.1 -------- arch/arm/include/asm/opcodes.h | 56 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h index c0efdd6..98e9e26 100644 --- a/arch/arm/include/asm/opcodes.h +++ b/arch/arm/include/asm/opcodes.h @@ -9,6 +9,10 @@ #ifndef __ASM_ARM_OPCODES_H #define __ASM_ARM_OPCODES_H +#include +#include + + #ifndef __ASSEMBLY__ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); #endif @@ -17,4 +21,56 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); #define ARM_OPCODE_CONDTEST_PASS 1 #define ARM_OPCODE_CONDTEST_UNCOND 2 + +/* + * Opcode byteswap helpers + * + * These macros help with converting instructions between a canonical integer + * format and in-memory representation, in an endianness-agnostic manner. + * + * __mem_to_opcode_*() convert from in-memory representation to canonical form. + * __opcode_to_mem_*() convert from canonical form to in-memory representation. + * + * + * Canonical instruction representation: + * + * ARM: 0xKKLLMMNN + * Thumb 16-bit: 0x0000KKLL, where KK < 0xE8 + * Thumb 32-bit: 0xKKLLMMNN, where KK >= 0xE8 + * + * There is no way to distinguish an ARM instruction in canonical representation + * from a Thumb instruction (just as these cannot be distinguished in memory). + * Where this distinction is important, it needs to be tracked separately. + * + * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not + * represent any valid Thumb-2 instruction. For this range, + * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false. + */ + +#ifdef CONFIG_CPU_ENDIAN_BE8 +#define __opcode_to_mem_arm(x) swab32(x) +#define __opcode_to_mem_thumb16(x) swab16(x) +#define __opcode_to_mem_thumb32(x) swahb32(x) +#else +#define __opcode_to_mem_arm(x) ((u32)(x)) +#define __opcode_to_mem_thumb16(x) ((u16)(x)) +#define __opcode_to_mem_thumb32(x) swahw32(x) +#endif + +#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x) +#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x) +#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x) + +/* Operations specific to Thumb opcodes */ + +/* Instruction size checks: */ +#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL) +#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL) + +/* Operations to construct or split 32-bit Thumb instructions: */ +#define __opcode_thumb32_first(x) ((u16)((x) >> 16)) +#define __opcode_thumb32_second(x) ((u16)(x)) +#define __opcode_thumb32_compose(first, second) \ + (((u32)(u16)(first) << 16) | (u32)(u16)(second)) + #endif /* __ASM_ARM_OPCODES_H */