Hi, the attached file includes preliminary support for the Intel XScale CPU. I have also written code which emulates a Gumstix [1] system in QEMU - based on this processor - and got a Linux kernel up and running.
Could you please apply this patch to CVS? Comments? I will send further patches if this is all right so far... -- Thorsten [1] http://www.gumstix.org
diff -u -r qemu.orig/target-arm/cpu.h qemu.new/target-arm/cpu.h --- qemu.orig/target-arm/cpu.h 2006-02-20 01:33:36.000000000 +0100 +++ qemu.new/target-arm/cpu.h 2006-10-04 22:11:15.532962000 +0200 @@ -47,6 +47,8 @@ typedef struct CPUARMState { /* Regs for current mode. */ uint32_t regs[16]; + /* Accumulator for XScale, by now only ACC0 supported */ + uint64_t acc[8]; /* Frequently accessed CPSR bits are stored separately for efficiently. This contains all the other bits. Use cpsr_{read,write} to accless the whole CPSR. */ @@ -69,6 +71,14 @@ uint32_t QF; /* 0 or 1 */ int thumb; /* 0 = arm mode, 1 = thumb mode */ + + /* System control coprocessor (cp14) */ + struct { + uint32_t pmnc; /* Performance Monitor Control Register */ + uint32_t ccnt; /* Clock Counter Register */ + uint32_t pmn0; /* Performance Count Register 0 */ + uint32_t pmn1; /* Performance Count Register 1 */ + } cp14; /* System control coprocessor (cp15) */ struct { @@ -200,7 +210,8 @@ enum arm_features { ARM_FEATURE_VFP, - ARM_FEATURE_AUXCR /* ARM1026 Auxiliary control register. */ + ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */ + ARM_FEATURE_XSCALE /* Intel XScale extensions */ }; static inline int arm_feature(CPUARMState *env, int feature) @@ -212,6 +223,7 @@ #define ARM_CPUID_ARM1026 0x4106a262 #define ARM_CPUID_ARM926 0x41069265 +#define ARM_CPUID_PXA255 0x69052d00 #if defined(CONFIG_USER_ONLY) #define TARGET_PAGE_BITS 12 diff -u -r qemu.orig/target-arm/exec.h qemu.new/target-arm/exec.h --- qemu.orig/target-arm/exec.h 2005-11-26 11:38:39.000000000 +0100 +++ qemu.new/target-arm/exec.h 2006-07-05 16:00:25.000000000 +0200 @@ -53,6 +53,8 @@ void cpu_lock(void); void cpu_unlock(void); +void helper_set_cp14(CPUState *, uint32_t, uint32_t); +uint32_t helper_get_cp14(CPUState *, uint32_t); void helper_set_cp15(CPUState *, uint32_t, uint32_t); uint32_t helper_get_cp15(CPUState *, uint32_t); diff -u -r qemu.orig/target-arm/helper.c qemu.new/target-arm/helper.c --- qemu.orig/target-arm/helper.c 2006-09-09 16:36:26.000000000 +0200 +++ qemu.new/target-arm/helper.c 2006-10-04 22:12:11.995788000 +0200 @@ -40,6 +40,9 @@ { env->cp15.c0_cpuid = id; switch (id) { + case ARM_CPUID_PXA255: + set_feature(env, ARM_FEATURE_XSCALE); + break; case ARM_CPUID_ARM926: set_feature(env, ARM_FEATURE_VFP); env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090; @@ -322,13 +325,17 @@ phys_addr = (desc & 0xfffff000) | (address & 0xfff); ap = (desc >> (4 + ((address >> 13) & 6))) & 3; break; - case 3: /* 1k page. */ - if (type == 1) { - /* Page translation fault. */ - code = 7; - goto do_fault; + case 3: /* 1k page. */ + if (arm_feature(env, ARM_FEATURE_XSCALE)) { + phys_addr = (desc & 0xfffff000) | (address & 0xfff); + } else { + if (type == 1) { + /* Page translation fault. */ + code = 7; + goto do_fault; + } + phys_addr = (desc & 0xfffffc00) | (address & 0x3ff); } - phys_addr = (desc & 0xfffffc00) | (address & 0x3ff); ap = (desc >> 4) & 3; break; default: @@ -391,6 +398,62 @@ return phys_addr; } +void helper_set_cp14(CPUState *env, uint32_t insn, uint32_t val) +{ + uint32_t op2; + + op2 = (insn >> 5) & 7; + switch ((insn >> 16) & 0xf) { + case 0: /* Performance Monitor Control Register */ + env->cp14.pmnc = val; + printf("Performance registers unsupported!\n"); + break; + case 1: /* Performance Monitor Control Register */ + env->cp14.ccnt = val; + printf("Performance registers unsupported!\n"); + break; + case 2: /* Performance Monitor Control Register 0 */ + env->cp14.pmn0 = val; + printf("Performance registers unsupported!\n"); + break; + case 3: /* Performance Monitor Control Register 1 */ + env->cp14.pmn1 = val; + printf("Performance registers unsupported!\n"); + break; + } + return; +bad_reg: + /* ??? For debugging only. Should raise illegal instruction exception. */ + cpu_abort(env, "Unimplemented cp14 register read\n"); + return; +} + +uint32_t helper_get_cp14(CPUState *env, uint32_t insn) +{ + uint32_t op2; + + op2 = (insn >> 5) & 7; + switch ((insn >> 16) & 0xf) { + case 0: /* Performance Monitor Control Register */ + printf("Performance registers unsupported!\n"); + return env->cp14.pmnc; + case 1: /* Performance Monitor Control Register */ + printf("Performance registers unsupported!\n"); + return env->cp14.ccnt; + case 2: /* Performance Monitor Control Register 0 */ + printf("Performance registers unsupported!\n"); + return env->cp14.pmn0; + case 3: /* Performance Monitor Control Register 1 */ + printf("Performance registers unsupported!\n"); + return env->cp14.pmn1; + } + return 0; +bad_reg: + /* ??? For debugging only. Should raise illegal instruction exception. */ + cpu_abort(env, "Unimplemented cp14 register read\n"); + return 0; +} + void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val) { uint32_t op2; diff -u -r qemu.orig/target-arm/op.c qemu.new/target-arm/op.c --- qemu.orig/target-arm/op.c 2006-06-26 21:55:19.000000000 +0200 +++ qemu.new/target-arm/op.c 2006-10-04 23:29:19.499215000 +0200 @@ -85,6 +85,21 @@ #define SET_REG(x) REG = x & ~(uint32_t)1 #include "op_template.h" +void OPPROTO op_acc0_T0_T1(void) +{ + uint64_t res; + res = ((uint64_t)T0 << 32) | T1; + env->acc[0] = res; +} + +void OPPROTO op_T0_T1_acc0(void) +{ + uint64_t res; + res = env->acc[0]; + T0 = res >> 32; + T1 = res & 0xffffffff; +} + void OPPROTO op_bx_T0(void) { env->regs[15] = T0 & ~(uint32_t)1; @@ -1148,6 +1163,19 @@ T1 = (int32_t)T0 >> 31; } +void OPPROTO op_movl_cp14_T0(void) +{ + helper_set_cp14(env, PARAM1, T0); + FORCE_RET(); +} + +void OPPROTO op_movl_T0_cp14(void) +{ + T0 = helper_get_cp14(env, PARAM1); + FORCE_RET(); +} + + void OPPROTO op_movl_cp15_T0(void) { helper_set_cp15(env, PARAM1, T0); diff -u -r qemu.orig/target-arm/translate.c qemu.new/target-arm/translate.c --- qemu.orig/target-arm/translate.c 2006-06-14 16:36:07.000000000 +0200 +++ qemu.new/target-arm/translate.c 2006-10-04 22:59:51.695175000 +0200 @@ -490,6 +490,63 @@ gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg)); } +/* Disassemble system coprocessor (cp0) instruction. Return nonzero if + instruction is not defined. */ +static int disas_cp0_insn(DisasContext *s, uint32_t insn) +{ + uint32_t rdhi, rdlo; + if ((insn & 0x0fe00f10) == 0x0e200010) { + printf ("cp0 multiply\n"); + return 1; + } else if ((insn & 0x0fe00ff8) == 0x0c400000) { + rdhi = (insn >> 16) & 0xf; + rdlo = (insn >> 12) & 0xf; + if (insn & (1 << 20)) { + /* write ACC */ + gen_op_T0_T1_acc0; + gen_op_movl_TN_reg[0][rdhi](); + gen_op_movl_TN_reg[1][rdlo](); + } else { + /* read ACC */ + gen_op_movl_reg_TN[0][rdhi](); + gen_op_movl_reg_TN[1][rdlo](); + gen_op_acc0_T0_T1; + } + return 0; + } else printf("Unknown cp0 instruction\n"); + return 1; +} + +/* Disassemble system coprocessor (cp14) instruction. Return nonzero if + instruction is not defined. */ +static int disas_cp14_insn(DisasContext *s, uint32_t insn) +{ + uint32_t rd; + /* + xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR + MCR/MCR p,o,Rd,CRN,CRM,q + */ + + if (IS_USER(s)) { + return 1; + } + if ((insn & 0x0f000f00) == 0x0e000e00) { /* fixme */ + rd = (insn >> 12) & 0xf; + if (insn & (1 << 20)) { /* 0/1 Store/Load */ + gen_op_movl_T0_cp14(insn); + gen_movl_reg_T0(s, rd); + } else { + gen_movl_T0_reg(s, rd); + gen_op_movl_cp14_T0(insn); + } + return 0; + } else printf("Unknown cp14 instruction\n"); + return 1; + + printf("cp14 instruction %x\n",insn); + return 0; +} + /* Disassemble system coprocessor (cp15) instruction. Return nonzero if instruction is not defined. */ static int disas_cp15_insn(DisasContext *s, uint32_t insn) @@ -1795,11 +1852,19 @@ /* Coprocessor. */ op1 = (insn >> 8) & 0xf; switch (op1) { + case 0: + if (disas_cp0_insn (s, insn)) + goto illegal_op; + break; case 10: case 11: if (disas_vfp_insn (env, s, insn)) goto illegal_op; break; + case 14: + if (disas_cp14_insn (s, insn)) + goto illegal_op; + break; case 15: if (disas_cp15_insn (s, insn)) goto illegal_op;
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel