diff options
author | balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-30 01:26:42 +0000 |
---|---|---|
committer | balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-04-30 01:26:42 +0000 |
commit | c1713132e07955819477a87a0ce830358e77a147 (patch) | |
tree | 343a836606f7444e68688a4019cce1221bd0cd1c /target-arm/translate.c | |
parent | 201a51fc386c0a2b55b13ad99589b1dfd1f39a5d (diff) |
Core features of ARM XScale processors. Main PXA270 and PXA255 peripherals.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2749 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 1631fcd312..65d234ae00 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -492,6 +492,34 @@ static inline void gen_mov_vreg_F0(int dp, int reg) gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg)); } +/* Disassemble system coprocessor instruction. Return nonzero if + instruction is not defined. */ +static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) +{ + uint32_t rd = (insn >> 12) & 0xf; + uint32_t cp = (insn >> 8) & 0xf; + if (IS_USER(s)) { + return 1; + } + + if (insn & (1 << 20)) { + if (!env->cp[cp].cp_read) + return 1; + gen_op_movl_T0_im((uint32_t) s->pc); + gen_op_movl_reg_TN[0][15](); + gen_op_movl_T0_cp(insn); + gen_movl_reg_T0(s, rd); + } else { + if (!env->cp[cp].cp_write) + return 1; + gen_op_movl_T0_im((uint32_t) s->pc); + gen_op_movl_reg_TN[0][15](); + gen_movl_T0_reg(s, rd); + gen_op_movl_cp_T0(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) @@ -1812,7 +1840,16 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) case 0xe: /* Coprocessor. */ op1 = (insn >> 8) & 0xf; + if (arm_feature(env, ARM_FEATURE_XSCALE) && + ((env->cp15.c15_cpar ^ 0x3fff) & (1 << op1))) + goto illegal_op; switch (op1) { + case 0 ... 1: + case 2 ... 9: + case 12 ... 14: + if (disas_cp_insn (env, s, insn)) + goto illegal_op; + break; case 10: case 11: if (disas_vfp_insn (env, s, insn)) |