aboutsummaryrefslogtreecommitdiff
path: root/target-arm/translate.c
diff options
context:
space:
mode:
authorbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-30 01:26:42 +0000
committerbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-30 01:26:42 +0000
commitc1713132e07955819477a87a0ce830358e77a147 (patch)
tree343a836606f7444e68688a4019cce1221bd0cd1c /target-arm/translate.c
parent201a51fc386c0a2b55b13ad99589b1dfd1f39a5d (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.c37
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))