From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NVMft-0000a7-24 for qemu-devel@nongnu.org; Thu, 14 Jan 2010 05:11:33 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NVMfn-0000Zu-NU for qemu-devel@nongnu.org; Thu, 14 Jan 2010 05:11:31 -0500 Received: from [199.232.76.173] (port=38199 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NVMfn-0000Zr-EF for qemu-devel@nongnu.org; Thu, 14 Jan 2010 05:11:27 -0500 Received: from mail-pw0-f43.google.com ([209.85.160.43]:51436) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NVMfm-0006mo-Oj for qemu-devel@nongnu.org; Thu, 14 Jan 2010 05:11:27 -0500 Received: by pwj11 with SMTP id 11so4218375pwj.2 for ; Thu, 14 Jan 2010 02:11:25 -0800 (PST) MIME-Version: 1.0 In-Reply-To: References: Date: Thu, 14 Jan 2010 11:11:24 +0100 Message-ID: <761ea48b1001140211o2f1caaa1td85b3a249fb850b2@mail.gmail.com> Subject: Re: [Qemu-devel] [PATCH] target-arm: ARMv4 emulation From: Laurent Desnogues Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Filip Navara Cc: vince@kyllikki.org, qemu-devel@nongnu.org, paul@codesourcery.com Since you wanted a "no, because..." there's at least one :-) On Tue, Dec 1, 2009 at 9:41 PM, Filip Navara wrote= : > While most of the ARMv5 instructions are backward compatible with ARMv4, = there > are few important differences. Most notably the stack pop and load instru= ctions > ignore the lowest bit, which is used by ARMv5 to switch to Thumb mode. A > base-updated data-abort model is used on ARM7TDMI, CP15 coprocessor is no= t > present and several instructions of later architectures are not implement= ed. > > This patch introduces flags for the V5, CP15 and ABORT_BU (base-updated a= bort > model) features. When V5 feature is not set the bit 0 on POP, LD and LDM = of PC > register is ignored and doesn't swith to/from Thumb mode and several > instructions are treated as unimplemented (BLX, PLD, BKPT, LDRD, STRD). > > Added are processor definitions for ARM7TDMI and ARM920T. > > Based on patches by Ulrich Hecht and Vincent Sanders . > > Signed-off-by: Filip Navara > --- > =A0target-arm/cpu.h =A0 =A0 =A0 | =A0 =A07 ++- > =A0target-arm/helper.c =A0 =A0| =A0 31 ++++++++++++ > =A0target-arm/translate.c | =A0119 ++++++++++++++++++++++++++++++++++----= --------- > =A03 files changed, 123 insertions(+), 34 deletions(-) > > diff --git a/target-arm/cpu.h b/target-arm/cpu.h > index 4a1c53f..b8e1e4b 100644 > --- a/target-arm/cpu.h > +++ b/target-arm/cpu.h > @@ -334,6 +334,7 @@ enum arm_features { > =A0 =A0 ARM_FEATURE_AUXCR, =A0/* ARM1026 Auxiliary control register. =A0*= / > =A0 =A0 ARM_FEATURE_XSCALE, /* Intel XScale extensions. =A0*/ > =A0 =A0 ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. =A0*/ > + =A0 =A0ARM_FEATURE_V5, > =A0 =A0 ARM_FEATURE_V6, > =A0 =A0 ARM_FEATURE_V6K, > =A0 =A0 ARM_FEATURE_V7, > @@ -345,7 +346,9 @@ enum arm_features { > =A0 =A0 ARM_FEATURE_DIV, > =A0 =A0 ARM_FEATURE_M, /* Microcontroller profile. =A0*/ > =A0 =A0 ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. =A0*/ > - =A0 =A0ARM_FEATURE_THUMB2EE > + =A0 =A0ARM_FEATURE_THUMB2EE, > + =A0 =A0ARM_FEATURE_CP15, /* ARM7TDMI, ARM7TDMI-S, ARM7EJ-S, and ARM9TDM= I cores do not have a CP15 */ > + =A0 =A0ARM_FEATURE_ABORT_BU /* base updated abort model, e.g. ARMxTDMI = */ > =A0}; > > =A0static inline int arm_feature(CPUARMState *env, int feature) > @@ -371,6 +374,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, > =A0#define IS_M(env) arm_feature(env, ARM_FEATURE_M) > =A0#define ARM_CPUID(env) (env->cp15.c0_cpuid) > > +#define ARM_CPUID_ARM7TDMI =A0 =A00x41807000 /* guess; no CP15 on ARM7TD= MI */ > +#define ARM_CPUID_ARM920T =A0 =A0 0x41129200 > =A0#define ARM_CPUID_ARM1026 =A0 =A0 0x4106a262 > =A0#define ARM_CPUID_ARM926 =A0 =A0 =A00x41069265 > =A0#define ARM_CPUID_ARM946 =A0 =A0 =A00x41059461 > diff --git a/target-arm/helper.c b/target-arm/helper.c > index b3aec99..b82959f 100644 > --- a/target-arm/helper.c > +++ b/target-arm/helper.c > @@ -44,19 +44,34 @@ static void cpu_reset_model_id(CPUARMState *env, uint= 32_t id) > =A0{ > =A0 =A0 env->cp15.c0_cpuid =3D id; > =A0 =A0 switch (id) { > + =A0 =A0case ARM_CPUID_ARM7TDMI: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_ABORT_BU); > + =A0 =A0 =A0 =A0break; > + =A0 =A0case ARM_CPUID_ARM920T: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_ABORT_BU); ARM920T is using an ARM9TDMI which uses the Base Restored Data Abort Model and not the Updated one. Ref: http://infocenter.arm.com/help/index.jsp?topic=3D/com.arm.doc.ddi0180a= /ch02s01s01.html Laurent > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > + =A0 =A0 =A0 =A0env->cp15.c0_cachetype =3D 0x0d172172; > + =A0 =A0 =A0 =A0env->cp15.c1_sys =3D 0x00000078; > + =A0 =A0 =A0 =A0break; > =A0 =A0 case ARM_CPUID_ARM926: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_VFP); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 env->vfp.xregs[ARM_VFP_FPSID] =3D 0x41011090; > =A0 =A0 =A0 =A0 env->cp15.c0_cachetype =3D 0x1dd20d2; > =A0 =A0 =A0 =A0 env->cp15.c1_sys =3D 0x00090078; > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_ARM946: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_MPU); > =A0 =A0 =A0 =A0 env->cp15.c0_cachetype =3D 0x0f004006; > =A0 =A0 =A0 =A0 env->cp15.c1_sys =3D 0x00000078; > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_ARM1026: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_VFP); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_AUXCR); > =A0 =A0 =A0 =A0 env->vfp.xregs[ARM_VFP_FPSID] =3D 0x410110a0; > =A0 =A0 =A0 =A0 env->cp15.c0_cachetype =3D 0x1dd20d2; > @@ -64,8 +79,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint3= 2_t id) > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_ARM1136_R2: > =A0 =A0 case ARM_CPUID_ARM1136: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_VFP); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_AUXCR); > =A0 =A0 =A0 =A0 env->vfp.xregs[ARM_VFP_FPSID] =3D 0x410120b4; > =A0 =A0 =A0 =A0 env->vfp.xregs[ARM_VFP_MVFR0] =3D 0x11111111; > @@ -75,9 +92,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint3= 2_t id) > =A0 =A0 =A0 =A0 env->cp15.c0_cachetype =3D 0x1dd20d2; > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_ARM11MPCORE: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6K); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_VFP); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_AUXCR); > =A0 =A0 =A0 =A0 env->vfp.xregs[ARM_VFP_FPSID] =3D 0x410120b4; > =A0 =A0 =A0 =A0 env->vfp.xregs[ARM_VFP_MVFR0] =3D 0x11111111; > @@ -87,9 +106,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint= 32_t id) > =A0 =A0 =A0 =A0 env->cp15.c0_cachetype =3D 0x1dd20d2; > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_CORTEXA8: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6K); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V7); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_AUXCR); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_THUMB2); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_VFP); > @@ -129,6 +150,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint= 32_t id) > =A0 =A0 =A0 =A0 env->cp15.c0_ccsid[1] =3D 0x200fe015; /* 16k L1 icache. *= / > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_CORTEXM3: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_THUMB2); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V7); > @@ -136,6 +158,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint= 32_t id) > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_DIV); > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_ANY: /* For userspace emulation. =A0*/ > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V6K); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_V7); > @@ -149,6 +172,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint= 32_t id) > =A0 =A0 =A0 =A0 break; > =A0 =A0 case ARM_CPUID_TI915T: > =A0 =A0 case ARM_CPUID_TI925T: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_OMAPCP); > =A0 =A0 =A0 =A0 env->cp15.c0_cpuid =3D ARM_CPUID_TI925T; /* Depends on wi= ring. =A0*/ > =A0 =A0 =A0 =A0 env->cp15.c0_cachetype =3D 0x5109149; > @@ -161,6 +186,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint= 32_t id) > =A0 =A0 case ARM_CPUID_PXA260: > =A0 =A0 case ARM_CPUID_PXA261: > =A0 =A0 case ARM_CPUID_PXA262: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_XSCALE); > =A0 =A0 =A0 =A0 /* JTAG_ID is ((id << 28) | 0x09265013) */ > =A0 =A0 =A0 =A0 env->cp15.c0_cachetype =3D 0xd172172; > @@ -172,6 +199,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint= 32_t id) > =A0 =A0 case ARM_CPUID_PXA270_B1: > =A0 =A0 case ARM_CPUID_PXA270_C0: > =A0 =A0 case ARM_CPUID_PXA270_C5: > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_V5); > + =A0 =A0 =A0 =A0set_feature(env, ARM_FEATURE_CP15); > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_XSCALE); > =A0 =A0 =A0 =A0 /* JTAG_ID is ((id << 28) | 0x09265013) */ > =A0 =A0 =A0 =A0 set_feature(env, ARM_FEATURE_IWMMXT); > @@ -306,6 +335,8 @@ struct arm_cpu_t { > =A0}; > > =A0static const struct arm_cpu_t arm_cpu_names[] =3D { > + =A0 =A0 =A0 { ARM_CPUID_ARM7TDMI, "arm7tdmi"}, > + =A0 =A0{ ARM_CPUID_ARM920T, "arm920t"}, > =A0 =A0 { ARM_CPUID_ARM926, "arm926"}, > =A0 =A0 { ARM_CPUID_ARM946, "arm946"}, > =A0 =A0 { ARM_CPUID_ARM1026, "arm1026"}, > diff --git a/target-arm/translate.c b/target-arm/translate.c > index 45bf772..48602bb 100644 > --- a/target-arm/translate.c > +++ b/target-arm/translate.c > @@ -34,9 +34,10 @@ > =A0#define GEN_HELPER 1 > =A0#include "helpers.h" > > +#define ENABLE_ARCH_5 =A0 =A0 arm_feature(env, ARM_FEATURE_V5) > =A0#define ENABLE_ARCH_5J =A0 =A00 > =A0#define ENABLE_ARCH_6 =A0 =A0 arm_feature(env, ARM_FEATURE_V6) > -#define ENABLE_ARCH_6K =A0 arm_feature(env, ARM_FEATURE_V6K) > +#define ENABLE_ARCH_6K =A0 =A0arm_feature(env, ARM_FEATURE_V6K) > =A0#define ENABLE_ARCH_6T2 =A0 arm_feature(env, ARM_FEATURE_THUMB2) > =A0#define ENABLE_ARCH_7 =A0 =A0 arm_feature(env, ARM_FEATURE_V7) > > @@ -2463,8 +2464,10 @@ static int disas_cp15_insn(CPUState *env, DisasCon= text *s, uint32_t insn) > =A0 =A0 TCGv tmp, tmp2; > > =A0 =A0 /* M profile cores use memory mapped registers instead of cp15. = =A0*/ > - =A0 =A0if (arm_feature(env, ARM_FEATURE_M)) > - =A0 =A0 =A0 return 1; > + =A0 =A0if (arm_feature(env, ARM_FEATURE_M) || > + =A0 =A0 =A0 =A0!arm_feature(env, ARM_FEATURE_CP15)) { > + =A0 =A0 =A0 =A0 =A0 return 1; > + =A0 =A0} > > =A0 =A0 if ((insn & (1 << 25)) =3D=3D 0) { > =A0 =A0 =A0 =A0 if (insn & (1 << 20)) { > @@ -6000,9 +6003,10 @@ static void disas_arm_insn(CPUState * env, DisasCo= ntext *s) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto illegal_op; > =A0 =A0 =A0 =A0 =A0 =A0 return; > =A0 =A0 =A0 =A0 } > - =A0 =A0 =A0 =A0if ((insn & 0x0d70f000) =3D=3D 0x0550f000) > + =A0 =A0 =A0 =A0if ((insn & 0x0d70f000) =3D=3D 0x0550f000) { > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 return; /* PLD */ > - =A0 =A0 =A0 =A0else if ((insn & 0x0ffffdff) =3D=3D 0x01010000) { > + =A0 =A0 =A0 =A0} else if ((insn & 0x0ffffdff) =3D=3D 0x01010000) { > =A0 =A0 =A0 =A0 =A0 =A0 ARCH(6); > =A0 =A0 =A0 =A0 =A0 =A0 /* setend */ > =A0 =A0 =A0 =A0 =A0 =A0 if (insn & (1 << 9)) { > @@ -6119,7 +6123,7 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 } else if ((insn & 0x0e000000) =3D=3D 0x0a000000) { > =A0 =A0 =A0 =A0 =A0 =A0 /* branch link and change to thumb (blx )= */ > =A0 =A0 =A0 =A0 =A0 =A0 int32_t offset; > - > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 val =3D (uint32_t)s->pc; > =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D new_tmp(); > =A0 =A0 =A0 =A0 =A0 =A0 tcg_gen_movi_i32(tmp, val); > @@ -6141,8 +6145,10 @@ static void disas_arm_insn(CPUState * env, DisasCo= ntext *s) > =A0 =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 } else if ((insn & 0x0fe00000) =3D=3D 0x0c400000) { > =A0 =A0 =A0 =A0 =A0 =A0 /* Coprocessor double register transfer. =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 } else if ((insn & 0x0f000010) =3D=3D 0x0e000010) { > =A0 =A0 =A0 =A0 =A0 =A0 /* Additional coprocessor register transfer. =A0*= / > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 } else if ((insn & 0x0ff10020) =3D=3D 0x01000000) { > =A0 =A0 =A0 =A0 =A0 =A0 uint32_t mask; > =A0 =A0 =A0 =A0 =A0 =A0 uint32_t val; > @@ -6245,6 +6251,7 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_bx(s, tmp); > =A0 =A0 =A0 =A0 =A0 =A0 } else if (op1 =3D=3D 3) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* clz */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rd =3D (insn >> 12) & 0xf; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D load_reg(s, rm); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_helper_clz(tmp, tmp); > @@ -6266,8 +6273,8 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 case 0x3: > =A0 =A0 =A0 =A0 =A0 =A0 if (op1 !=3D 1) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto illegal_op; > - > =A0 =A0 =A0 =A0 =A0 =A0 /* branch link/exchange thumb (blx) */ > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D load_reg(s, rm); > =A0 =A0 =A0 =A0 =A0 =A0 tmp2 =3D new_tmp(); > =A0 =A0 =A0 =A0 =A0 =A0 tcg_gen_movi_i32(tmp2, s->pc); > @@ -6275,6 +6282,7 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 =A0 =A0 gen_bx(s, tmp); > =A0 =A0 =A0 =A0 =A0 =A0 break; > =A0 =A0 =A0 =A0 case 0x5: /* saturating add/subtract */ > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 rd =3D (insn >> 12) & 0xf; > =A0 =A0 =A0 =A0 =A0 =A0 rn =3D (insn >> 16) & 0xf; > =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D load_reg(s, rm); > @@ -6289,6 +6297,7 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 =A0 =A0 store_reg(s, rd, tmp); > =A0 =A0 =A0 =A0 =A0 =A0 break; > =A0 =A0 =A0 =A0 case 7: /* bkpt */ > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 gen_set_condexec(s); > =A0 =A0 =A0 =A0 =A0 =A0 gen_set_pc_im(s->pc - 4); > =A0 =A0 =A0 =A0 =A0 =A0 gen_exception(EXCP_BKPT); > @@ -6298,6 +6307,7 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 case 0xa: > =A0 =A0 =A0 =A0 case 0xc: > =A0 =A0 =A0 =A0 case 0xe: > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 rs =3D (insn >> 8) & 0xf; > =A0 =A0 =A0 =A0 =A0 =A0 rn =3D (insn >> 12) & 0xf; > =A0 =A0 =A0 =A0 =A0 =A0 rd =3D (insn >> 16) & 0xf; > @@ -7019,7 +7029,7 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 =A0 =A0 if (insn & (1 << 20)) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Complete the load. =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (rd =3D=3D 15) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (rd =3D=3D 15 && ENABLE_ARCH_5) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_bx(s, tmp); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 store_reg(s, rd, tmp); > @@ -7029,6 +7039,7 @@ static void disas_arm_insn(CPUState * env, DisasCon= text *s) > =A0 =A0 =A0 =A0 case 0x09: > =A0 =A0 =A0 =A0 =A0 =A0 { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int j, n, user, loaded_base; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int crement =3D 0; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TCGv loaded_var; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* load/store multiple words */ > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* XXX: store correct base if write back = */ > @@ -7069,6 +7080,38 @@ static void disas_arm_insn(CPUState * env, DisasCo= ntext *s) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tcg_gen_addi_i32(addr, ad= dr, -((n - 1) * 4)); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 21)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* write back */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 23)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 24)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* pre increment= */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* post incremen= t */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0crement =3D 4; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 24)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* pre decrement= */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (n !=3D 1) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0crement = =3D -((n - 1) * 4); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* post decremen= t */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0crement =3D -(n = * 4); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (arm_feature(env, ARM_FEATURE= _ABORT_BU)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* base-updated abort mo= del: update base register > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 before an abort can= happen */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0crement +=3D (n - 1) * 4= ; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tmp =3D new_tmp(); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_addi_i32(tmp, ad= dr, crement); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0store_reg(s, rn, tmp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 j =3D 0; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 for(i=3D0;i<16;i++) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (insn & (1 << i)) { > @@ -7076,7 +7119,11 @@ static void disas_arm_insn(CPUState * env, DisasCo= ntext *s) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* load */ > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D gen_ld32(= addr, IS_USER(s)); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (i =3D=3D 15) = { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_bx(s= , tmp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ENAB= LE_ARCH_5) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= gen_bx(s, tmp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= store_reg(s, i, tmp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else if (user) = { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp2 =3D = tcg_const_i32(i); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_helpe= r_set_user_reg(tmp2, tmp); > @@ -7111,25 +7158,8 @@ static void disas_arm_insn(CPUState * env, DisasCo= ntext *s) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tcg_gen_addi_i32(= addr, addr, 4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 21)) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* write back */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 23)) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 24)) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* pre increment= */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* post incremen= t */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_addi_i32= (addr, addr, 4); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << 24)) { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* pre decrement= */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (n !=3D 1) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_= addi_i32(addr, addr, -((n - 1) * 4)); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* post decremen= t */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_addi_i32= (addr, addr, -(n * 4)); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!arm_feature(env, ARM_FEATURE_ABORT_= BU) && (insn & (1 << 21))) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_addi_i32(addr, addr, cre= ment); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 store_reg(s, rn, addr); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dead_tmp(addr); > @@ -7290,6 +7320,7 @@ static int disas_thumb2_insn(CPUState *env, DisasCo= ntext *s, uint16_t insn_hw1) > =A0 =A0 =A0 =A0 =A0 =A016-bit instructions to get correct prefetch abort = behavior. =A0*/ > =A0 =A0 =A0 =A0 insn =3D insn_hw1; > =A0 =A0 =A0 =A0 if ((insn & (1 << 12)) =3D=3D 0) { > + =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 /* Second half of blx. =A0*/ > =A0 =A0 =A0 =A0 =A0 =A0 offset =3D ((insn & 0x7ff) << 1); > =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D load_reg(s, 14); > @@ -7346,6 +7377,7 @@ static int disas_thumb2_insn(CPUState *env, DisasCo= ntext *s, uint16_t insn_hw1) > =A0 =A0 =A0 =A0 =A0 =A0 /* Other load/store, table branch. =A0*/ > =A0 =A0 =A0 =A0 =A0 =A0 if (insn & 0x01200000) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Load/store doubleword. =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (rn =3D=3D 15) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 addr =3D new_tmp(); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tcg_gen_movi_i32(addr, s->pc & ~3= ); > @@ -7516,7 +7548,7 @@ static int disas_thumb2_insn(CPUState *env, DisasCo= ntext *s, uint16_t insn_hw1) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (insn & (1 << 20)) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Load. =A0*/ > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D gen_ld32(addr, IS= _USER(s)); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (i =3D=3D 15) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (i =3D=3D 15 && ENABL= E_ARCH_5) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_bx(s, tmp); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 store_reg(s, i, t= mp); > @@ -7863,6 +7895,7 @@ static int disas_thumb2_insn(CPUState *env, DisasCo= ntext *s, uint16_t insn_hw1) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_jmp(s, offset); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* blx */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 offset &=3D ~(uint32_t)2; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_bx_im(s, offset); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > @@ -8227,7 +8260,7 @@ static int disas_thumb2_insn(CPUState *env, DisasCo= ntext *s, uint16_t insn_hw1) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case 2: tmp =3D gen_ld32(addr, user); bre= ak; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 default: goto illegal_op; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (rs =3D=3D 15) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (rs =3D=3D 15 && ENABLE_ARCH_5) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gen_bx(s, tmp); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 store_reg(s, rs, tmp); > @@ -8270,6 +8303,7 @@ static void disas_thumb_insn(CPUState *env, DisasCo= ntext *s) > =A0 =A0 TCGv tmp; > =A0 =A0 TCGv tmp2; > =A0 =A0 TCGv addr; > + =A0 =A0int crement; > > =A0 =A0 if (s->condexec_mask) { > =A0 =A0 =A0 =A0 cond =3D s->condexec_cond; > @@ -8402,6 +8436,7 @@ static void disas_thumb_insn(CPUState *env, DisasCo= ntext *s) > =A0 =A0 =A0 =A0 =A0 =A0 case 3:/* branch [and link] exchange thumb regist= er */ > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp =3D load_reg(s, rm); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (insn & (1 << 7)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ARCH(5); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 val =3D (uint32_t)s->pc | 1; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp2 =3D new_tmp(); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tcg_gen_movi_i32(tmp2, val); > @@ -8766,8 +8801,13 @@ static void disas_thumb_insn(CPUState *env, DisasC= ontext *s) > =A0 =A0 =A0 =A0 =A0 =A0 /* write back the new stack pointer */ > =A0 =A0 =A0 =A0 =A0 =A0 store_reg(s, 13, addr); > =A0 =A0 =A0 =A0 =A0 =A0 /* set the new PC value */ > - =A0 =A0 =A0 =A0 =A0 =A0if ((insn & 0x0900) =3D=3D 0x0900) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_bx(s, tmp); > + =A0 =A0 =A0 =A0 =A0 =A0if ((insn & 0x0900) =3D=3D 0x0900) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ENABLE_ARCH_5) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0gen_bx(s, tmp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0store_reg(s, 15, tmp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0} > =A0 =A0 =A0 =A0 =A0 =A0 break; > > =A0 =A0 =A0 =A0 case 1: case 3: case 9: case 11: /* czb */ > @@ -8856,6 +8896,19 @@ static void disas_thumb_insn(CPUState *env, DisasC= ontext *s) > =A0 =A0 =A0 =A0 /* load/store multiple */ > =A0 =A0 =A0 =A0 rn =3D (insn >> 8) & 0x7; > =A0 =A0 =A0 =A0 addr =3D load_reg(s, rn); > + =A0 =A0 =A0 =A0if (arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1= << rn)) =3D=3D 0) { > + =A0 =A0 =A0 =A0 =A0 =A0/* base-updated abort model: update base registe= r > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 before an abort can happen */ > + =A0 =A0 =A0 =A0 =A0 =A0crement =3D 0; > + =A0 =A0 =A0 =A0 =A0 =A0for (i =3D 0; i < 8; i++) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (insn & (1 << i)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0crement +=3D 4; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0tmp =3D new_tmp(); > + =A0 =A0 =A0 =A0 =A0 =A0tcg_gen_addi_i32(tmp, addr, crement); > + =A0 =A0 =A0 =A0 =A0 =A0store_reg(s, rn, tmp); > + =A0 =A0 =A0 =A0} > =A0 =A0 =A0 =A0 for (i =3D 0; i < 8; i++) { > =A0 =A0 =A0 =A0 =A0 =A0 if (insn & (1 << i)) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (insn & (1 << 11)) { > @@ -8872,7 +8925,7 @@ static void disas_thumb_insn(CPUState *env, DisasCo= ntext *s) > =A0 =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 /* Base register writeback. =A0*/ > - =A0 =A0 =A0 =A0if ((insn & (1 << rn)) =3D=3D 0) { > + =A0 =A0 =A0 =A0if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (= 1 << rn)) =3D=3D 0) { > =A0 =A0 =A0 =A0 =A0 =A0 store_reg(s, rn, addr); > =A0 =A0 =A0 =A0 } else { > =A0 =A0 =A0 =A0 =A0 =A0 dead_tmp(addr); > -- > 1.6.5.1.1367.gcd48 > > > > >