static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) { uint32_t rd; TCGv tmp, tmp2; /* M profile cores use memory mapped registers instead of cp15. */ if (arm_feature(env, ARM_FEATURE_M)) return 1; if ((insn & (1 << 25)) == 0) { if (insn & (1 << 20)) { /* mrrc */ return 1; } /* mcrr. Used for block cache operations, so implement as no-op. */ return 0; } if ((insn & (1 << 4)) == 0) { /* cdp */ return 1; } if (IS_USER(s) && !cp15_user_ok(insn)) { return 1; } if ((insn & 0x0fff0fff) == 0x0e070f90 || (insn & 0x0fff0fff) == 0x0e070f58) { /* Wait for interrupt. */ gen_set_pc_im(s->pc); s->is_jmp = DISAS_WFI; return 0; } rd = (insn >> 12) & 0xf; if (cp15_tls_load_store(env, s, insn, rd)) return 0; tmp2 = tcg_const_i32(insn); if (insn & ARM_CP_RW_BIT) { tmp = new_tmp(); gen_helper_get_cp15(tmp, cpu_env, tmp2); /* If the destination register is r15 then sets condition codes. */ if (rd != 15) store_reg(s, rd, tmp); else dead_tmp(tmp); } else { tmp = load_reg(s, rd); gen_helper_set_cp15(cpu_env, tmp2, tmp); dead_tmp(tmp); /* Normally we would always end the TB here, but Linux * arch/arm/mach-pxa/sleep.S expects two instructions following * an MMU enable to execute from cache. Imitate this behaviour. */ if (!arm_feature(env, ARM_FEATURE_XSCALE) || (insn & 0x0fff0fff) != 0x0e010f10) gen_lookup_tb(s); } tcg_temp_free_i32(tmp2); return 0; }