static int dec10_prep_move_m(DisasContext *dc, int s_ext, int memsize, TCGv dst) { unsigned int rs; uint32_t imm; int is_imm; int insn_len = 0; rs = dc->src; is_imm = rs == 15 && !(dc->tb_flags & PFIX_FLAG); LOG_DIS("rs=%d rd=%d is_imm=%d mode=%d pfix=%d\n", rs, dc->dst, is_imm, dc->mode, dc->tb_flags & PFIX_FLAG); /* Load [$rs] onto T1. */ if (is_imm) { if (memsize != 4) { if (s_ext) { if (memsize == 1) imm = ldsb_code(dc->pc + 2); else imm = ldsw_code(dc->pc + 2); } else { if (memsize == 1) imm = ldub_code(dc->pc + 2); else imm = lduw_code(dc->pc + 2); } } else imm = ldl_code(dc->pc + 2); tcg_gen_movi_tl(dst, imm); if (dc->mode == CRISV10_MODE_AUTOINC) { insn_len += memsize; if (memsize == 1) insn_len++; tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len); } } else { TCGv addr; addr = tcg_temp_new(); cris_flush_cc_state(dc); crisv10_prepare_memaddr(dc, addr, memsize); gen_load(dc, dst, addr, memsize, 0); if (s_ext) t_gen_sext(dst, dst, memsize); else t_gen_zext(dst, dst, memsize); insn_len += crisv10_post_memaddr(dc, memsize); tcg_temp_free(addr); } if (dc->mode == CRISV10_MODE_INDIRECT && (dc->tb_flags & PFIX_FLAG)) { dc->dst = dc->src; } return insn_len; }
static unsigned int crisv10_decoder(DisasContext *dc) { unsigned int insn_len = 2; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) tcg_gen_debug_insn_start(dc->pc); /* Load a halfword onto the instruction register. */ dc->ir = lduw_code(dc->pc); /* Now decode it. */ dc->opcode = EXTRACT_FIELD(dc->ir, 6, 9); dc->mode = EXTRACT_FIELD(dc->ir, 10, 11); dc->src = EXTRACT_FIELD(dc->ir, 0, 3); dc->size = EXTRACT_FIELD(dc->ir, 4, 5); dc->cond = dc->dst = EXTRACT_FIELD(dc->ir, 12, 15); dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10); dc->clear_prefix = 1; /* FIXME: What if this insn insn't 2 in length?? */ if (dc->src == 15 || dc->dst == 15) tcg_gen_movi_tl(cpu_R[15], dc->pc + 2); switch (dc->mode) { case CRISV10_MODE_QIMMEDIATE: insn_len = dec10_quick_imm(dc); break; case CRISV10_MODE_REG: insn_len = dec10_reg(dc); break; case CRISV10_MODE_AUTOINC: case CRISV10_MODE_INDIRECT: insn_len = dec10_ind(dc); break; } if (dc->clear_prefix && dc->tb_flags & PFIX_FLAG) { dc->tb_flags &= ~PFIX_FLAG; tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~PFIX_FLAG); if (dc->tb_flags != dc->tb->flags) { dc->cpustate_changed = 1; } } /* CRISv10 locks out interrupts on dslots. */ if (dc->delayed_branch == 2) { cris_lock_irq(dc); } return insn_len; }
void do_interrupt(int is_hw) { uint32_t sp; uint32_t fmt; uint32_t retaddr; uint32_t vector; fmt = 0; retaddr = env->pc; if (!is_hw) { switch (env->exception_index) { case EXCP_RTE: /* Return from an exception. */ do_rte(); return; case EXCP_HALT_INSN: if (semihosting_enabled && (env->sr & SR_S) != 0 && (env->pc & 3) == 0 && lduw_code(env->pc - 4) == 0x4e71 && ldl_code(env->pc) == 0x4e7bf000) { env->pc += 4; do_m68k_semihosting(env, env->dregs[0]); return; } env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(); return; } if (env->exception_index >= EXCP_TRAP0 && env->exception_index <= EXCP_TRAP15) { /* Move the PC after the trap instruction. */ retaddr += 2; } } vector = env->exception_index << 2; sp = env->aregs[7]; fmt |= 0x40000000; fmt |= (sp & 3) << 28; fmt |= vector << 16; fmt |= env->sr; env->sr |= SR_S; if (is_hw) { env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); env->sr &= ~SR_M; } m68k_switch_sp(env); /* ??? This could cause MMU faults. */ sp &= ~3; sp -= 4; stl_kernel(sp, retaddr); sp -= 4; stl_kernel(sp, fmt); env->aregs[7] = sp; /* Jump to vector. */ env->pc = ldl_kernel(env->vbr + vector); }