From patchwork Thu Mar 24 10:22:57 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 88161 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by ozlabs.org (Postfix) with ESMTP id CAE3CB6F7D for ; Thu, 24 Mar 2011 21:29:50 +1100 (EST) Received: from localhost ([127.0.0.1]:39481 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q2hi5-0002Ph-Nl for incoming@patchwork.ozlabs.org; Thu, 24 Mar 2011 06:24:09 -0400 Received: from [140.186.70.92] (port=46972 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q2hh2-0002KR-Uu for qemu-devel@nongnu.org; Thu, 24 Mar 2011 06:23:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q2hh1-0000YQ-7N for qemu-devel@nongnu.org; Thu, 24 Mar 2011 06:23:04 -0400 Received: from mail-fx0-f45.google.com ([209.85.161.45]:36973) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q2hh0-0000Y5-Pq for qemu-devel@nongnu.org; Thu, 24 Mar 2011 06:23:03 -0400 Received: by fxm2 with SMTP id 2so9313786fxm.4 for ; Thu, 24 Mar 2011 03:23:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:subject:date:message-id:x-mailer; bh=LO9dEHMV3nhmPdi1HZU0R7jMg2Q/HFgTG+GaTm08MvA=; b=jHFdSRF5dFn6Ncl7LEWdxWMYjoQ1PbEx7yo8+GeciMQ8lRvMNwt7RQYrk/f7PWzz4g RZpuCzEkA2vGMk5V467IkTlUPqSlIUFvjOxU06PyhKZwkJcDsfTyUXKJFjwA1ZDnKOK4 aPmYUbxpRXyRE/FmwK6GrSs5kIe7267tzdSQI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:x-mailer; b=YqteUvTLHGMgB2HTyglAGTloDbb2Gif85Dfgibpxh4mLozRHWEcHQdLYTdOw5J5z/p 86bSwGJSW08X0Q+YD9KZXF4raBfQx6rPP/wS/xOgiqcfArEzas0zcEOZQxUl6Zzwbora OMScv86Rx0xXDDw9+FsuwCKtNk2OTBLXLLRo8= Received: by 10.223.30.77 with SMTP id t13mr928146fac.112.1300962181742; Thu, 24 Mar 2011 03:23:01 -0700 (PDT) Received: from doriath.ww600.siemens.net (pd95b1e1f.dip0.t-ipconnect.de [217.91.30.31]) by mx.google.com with ESMTPS id b18sm3615062fak.32.2011.03.24.03.23.00 (version=SSLv3 cipher=OTHER); Thu, 24 Mar 2011 03:23:00 -0700 (PDT) From: Dmitry Eremin-Solenikov To: qemu-devel@nongnu.org Date: Thu, 24 Mar 2011 13:22:57 +0300 Message-Id: <1300962179-21676-1-git-send-email-dbaryshkov@gmail.com> X-Mailer: git-send-email 1.7.4.1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.161.45 Subject: [Qemu-devel] [PATCH 1/3] arm: basic support for ARMv4/ARMv4T emulation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently target-arm/ assumes at least ARMv5 core. Add support for handling also ARMv4/ARMv4T. This changes the following instructions: BX(v4T and later) BKPT, BLX, CDP2, CLZ, LDC2, LDRD, MCRR, MCRR2, MRRC, MCRR, MRC2, MRRC, MRRC2, PLD QADD, QDADD, QDSUB, QSUB, STRD, SMLAxy, SMLALxy, SMLAWxy, SMULxy, SMULWxy, STC2 (v5 and later) All instructions that are "v5TE and later" are also bound to just v5, as that's how it was before. This patch doesn _not_ include disabling of cp15 access and base-updated data abort model (that will be required to emulate chips based on a ARM7TDMI), because: * no ARM7TDMI chips are currently emulated (or planned) * those features aren't strictly necessary for my purposes (SA-1 core emulation). Patch is heavily based on patch by Filip Navara which in turn is based on work by Ulrich Hecht and Vincent Sanders . Signed-off-by: Dmitry Eremin-Solenikov --- target-arm/cpu.h | 4 +++- target-arm/helper.c | 24 ++++++++++++++++++++++++ target-arm/translate.c | 25 ++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 1ae7982..e247a7a 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -360,7 +360,9 @@ enum arm_features { ARM_FEATURE_M, /* Microcontroller profile. */ ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */ ARM_FEATURE_THUMB2EE, - ARM_FEATURE_V7MP /* v7 Multiprocessing Extensions */ + ARM_FEATURE_V7MP, /* v7 Multiprocessing Extensions */ + ARM_FEATURE_V4T, + ARM_FEATURE_V5, }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/helper.c b/target-arm/helper.c index 78f3d39..49ff5cf 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -48,17 +48,23 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) env->cp15.c0_cpuid = id; switch (id) { case ARM_CPUID_ARM926: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_VFP); env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090; env->cp15.c0_cachetype = 0x1dd20d2; env->cp15.c1_sys = 0x00090078; break; case ARM_CPUID_ARM946: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_MPU); env->cp15.c0_cachetype = 0x0f004006; env->cp15.c1_sys = 0x00000078; break; case ARM_CPUID_ARM1026: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_VFP); set_feature(env, ARM_FEATURE_AUXCR); env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0; @@ -67,6 +73,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) break; case ARM_CPUID_ARM1136_R2: case ARM_CPUID_ARM1136: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_V6); set_feature(env, ARM_FEATURE_VFP); set_feature(env, ARM_FEATURE_AUXCR); @@ -79,6 +87,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) env->cp15.c1_sys = 0x00050078; break; case ARM_CPUID_ARM11MPCORE: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_V6); set_feature(env, ARM_FEATURE_V6K); set_feature(env, ARM_FEATURE_VFP); @@ -91,6 +101,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) env->cp15.c0_cachetype = 0x1dd20d2; break; case ARM_CPUID_CORTEXA8: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_V6); set_feature(env, ARM_FEATURE_V6K); set_feature(env, ARM_FEATURE_V7); @@ -113,6 +125,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) env->cp15.c1_sys = 0x00c50078; break; case ARM_CPUID_CORTEXA9: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_V6); set_feature(env, ARM_FEATURE_V6K); set_feature(env, ARM_FEATURE_V7); @@ -140,6 +154,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) env->cp15.c1_sys = 0x00c50078; break; case ARM_CPUID_CORTEXM3: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_V6); set_feature(env, ARM_FEATURE_THUMB2); set_feature(env, ARM_FEATURE_V7); @@ -147,6 +163,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) set_feature(env, ARM_FEATURE_DIV); break; case ARM_CPUID_ANY: /* For userspace emulation. */ + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_V6); set_feature(env, ARM_FEATURE_V6K); set_feature(env, ARM_FEATURE_V7); @@ -161,6 +179,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) break; case ARM_CPUID_TI915T: case ARM_CPUID_TI925T: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_OMAPCP); env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring. */ env->cp15.c0_cachetype = 0x5109149; @@ -173,6 +193,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) case ARM_CPUID_PXA260: case ARM_CPUID_PXA261: case ARM_CPUID_PXA262: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_XSCALE); /* JTAG_ID is ((id << 28) | 0x09265013) */ env->cp15.c0_cachetype = 0xd172172; @@ -184,6 +206,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) case ARM_CPUID_PXA270_B1: case ARM_CPUID_PXA270_C0: case ARM_CPUID_PXA270_C5: + set_feature(env, ARM_FEATURE_V4T); + set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_XSCALE); /* JTAG_ID is ((id << 28) | 0x09265013) */ set_feature(env, ARM_FEATURE_IWMMXT); diff --git a/target-arm/translate.c b/target-arm/translate.c index f69912f..c9df87e 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -34,6 +34,8 @@ #define GEN_HELPER 1 #include "helpers.h" +#define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T) +#define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5) #define ENABLE_ARCH_5J 0 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6) #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K) @@ -6129,6 +6131,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } } /* Otherwise PLD; v5TE+ */ + ARCH(5); return; } if (((insn & 0x0f70f000) == 0x0450f000) || @@ -6255,6 +6258,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* branch link and change to thumb (blx ) */ int32_t offset; + ARCH(5); val = (uint32_t)s->pc; tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, val); @@ -6268,6 +6272,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_bx_im(s, val); return; } else if ((insn & 0x0e000f00) == 0x0c000100) { + ARCH(5); if (arm_feature(env, ARM_FEATURE_IWMMXT)) { /* iWMMXt register transfer. */ if (env->cp15.c15_cpar & (1 << 1)) @@ -6276,8 +6281,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } } else if ((insn & 0x0fe00000) == 0x0c400000) { /* Coprocessor double register transfer. */ + ARCH(5); } else if ((insn & 0x0f000010) == 0x0e000010) { /* Additional coprocessor register transfer. */ + ARCH(5); } else if ((insn & 0x0ff10020) == 0x01000000) { uint32_t mask; uint32_t val; @@ -6376,10 +6383,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) case 0x1: if (op1 == 1) { /* branch/exchange thumb (bx). */ + ARCH(4T); tmp = load_reg(s, rm); gen_bx(s, tmp); } else if (op1 == 3) { /* clz */ + ARCH(5); rd = (insn >> 12) & 0xf; tmp = load_reg(s, rm); gen_helper_clz(tmp, tmp); @@ -6402,6 +6411,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) if (op1 != 1) goto illegal_op; + ARCH(5); /* branch link/exchange thumb (blx) */ tmp = load_reg(s, rm); tmp2 = tcg_temp_new_i32(); @@ -6410,6 +6420,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_bx(s, tmp); break; case 0x5: /* saturating add/subtract */ + ARCH(5); rd = (insn >> 12) & 0xf; rn = (insn >> 16) & 0xf; tmp = load_reg(s, rm); @@ -6431,12 +6442,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) goto illegal_op; } /* bkpt */ + ARCH(5); gen_exception_insn(s, 4, EXCP_BKPT); break; case 0x8: /* signed multiply */ case 0xa: case 0xc: case 0xe: + ARCH(5); rs = (insn >> 8) & 0xf; rn = (insn >> 12) & 0xf; rd = (insn >> 16) & 0xf; @@ -6832,6 +6845,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } load = 1; } else if (sh & 2) { + ARCH(5); /* doubleword */ if (sh & 1) { /* store */ @@ -7172,10 +7186,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } if (insn & (1 << 20)) { /* Complete the load. */ - if (rd == 15) + if (rd == 15 && ENABLE_ARCH_4T) { gen_bx(s, tmp); - else + } else { store_reg(s, rd, tmp); + } } break; case 0x08: @@ -7229,7 +7244,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* load */ tmp = gen_ld32(addr, IS_USER(s)); if (i == 15) { - gen_bx(s, tmp); + if (ENABLE_ARCH_4T) { + gen_bx(s, tmp); + } else { + store_reg(s, i, tmp); + } } else if (user) { tmp2 = tcg_const_i32(i); gen_helper_set_user_reg(tmp2, tmp);