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 int dec10_dip(DisasContext *dc) { int insn_len = 2; uint32_t imm; LOG_DIS("dip pc=%x opcode=%d r%d r%d\n", dc->pc, dc->opcode, dc->src, dc->dst); if (dc->src == 15) { imm = ldl_code(dc->pc + 2); tcg_gen_movi_tl(cpu_PR[PR_PREFIX], imm); if (dc->postinc) insn_len += 4; tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len - 2); } else { gen_load(dc, cpu_PR[PR_PREFIX], cpu_R[dc->src], 4, 0); if (dc->postinc) tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], 4); } cris_set_prefix(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); }
static unsigned int dec10_ind(DisasContext *dc) { unsigned int insn_len = 2; unsigned int size = dec10_size(dc->size); uint32_t imm; int32_t simm; TCGv t[2]; if (dc->size != 3) { switch (dc->opcode) { case CRISV10_IND_MOVE_M_R: return dec10_ind_move_m_r(dc, size); break; case CRISV10_IND_MOVE_R_M: return dec10_ind_move_r_m(dc, size); break; case CRISV10_IND_CMP: LOG_DIS("cmp size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); insn_len += dec10_ind_alu(dc, CC_OP_CMP, size); break; case CRISV10_IND_TEST: LOG_DIS("test size=%d op=%d %d\n", size, dc->src, dc->dst); cris_evaluate_flags(dc); cris_cc_mask(dc, CC_MASK_NZVC); cris_alu_m_alloc_temps(t); insn_len += dec10_prep_move_m(dc, 0, size, t[0]); tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3); cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst], t[0], tcg_const_tl(0), size); cris_alu_m_free_temps(t); break; case CRISV10_IND_ADD: LOG_DIS("add size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); insn_len += dec10_ind_alu(dc, CC_OP_ADD, size); break; case CRISV10_IND_SUB: LOG_DIS("sub size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); insn_len += dec10_ind_alu(dc, CC_OP_SUB, size); break; case CRISV10_IND_BOUND: LOG_DIS("bound size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); insn_len += dec10_ind_bound(dc, size); break; case CRISV10_IND_AND: LOG_DIS("and size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); insn_len += dec10_ind_alu(dc, CC_OP_AND, size); break; case CRISV10_IND_OR: LOG_DIS("or size=%d op=%d %d\n", size, dc->src, dc->dst); cris_cc_mask(dc, CC_MASK_NZVC); insn_len += dec10_ind_alu(dc, CC_OP_OR, size); break; case CRISV10_IND_MOVX: insn_len = dec10_alux_m(dc, CC_OP_MOVE); break; case CRISV10_IND_ADDX: insn_len = dec10_alux_m(dc, CC_OP_ADD); break; case CRISV10_IND_SUBX: insn_len = dec10_alux_m(dc, CC_OP_SUB); break; case CRISV10_IND_CMPX: insn_len = dec10_alux_m(dc, CC_OP_CMP); break; case CRISV10_IND_MUL: /* This is a reg insn coded in the mem indir space. */ LOG_DIS("mul pc=%x opcode=%d\n", dc->pc, dc->opcode); cris_cc_mask(dc, CC_MASK_NZVC); dec10_reg_mul(dc, size, dc->ir & (1 << 10)); break; case CRISV10_IND_BDAP_M: insn_len = dec10_bdap_m(dc, size); break; default: LOG_DIS("pc=%x var-ind.%d %d r%d r%d\n", dc->pc, size, dc->opcode, dc->src, dc->dst); cpu_abort(dc->env, "Unhandled opcode"); break; } return insn_len; } switch (dc->opcode) { case CRISV10_IND_MOVE_M_SPR: insn_len = dec10_ind_move_m_pr(dc); break; case CRISV10_IND_MOVE_SPR_M: insn_len = dec10_ind_move_pr_m(dc); break; case CRISV10_IND_JUMP_M: if (dc->src == 15) { LOG_DIS("jump.%d %d r%d r%d direct\n", size, dc->opcode, dc->src, dc->dst); imm = ldl_code(dc->pc + 2); if (dc->mode == CRISV10_MODE_AUTOINC) insn_len += size; t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len)); dc->jmp_pc = imm; cris_prepare_jmp(dc, JMP_DIRECT); dc->delayed_branch--; /* v10 has no dslot here. */ } else { if (dc->dst == 14) { LOG_DIS("break %d\n", dc->src); cris_evaluate_flags(dc); tcg_gen_movi_tl(env_pc, dc->pc + 2); t_gen_raise_exception(EXCP_BREAK); dc->is_jmp = DISAS_UPDATE; return insn_len; } LOG_DIS("%d: jump.%d %d r%d r%d\n", __LINE__, size, dc->opcode, dc->src, dc->dst); t[0] = tcg_temp_new(); t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len)); crisv10_prepare_memaddr(dc, t[0], size); gen_load(dc, env_btarget, t[0], 4, 0); insn_len += crisv10_post_memaddr(dc, size); cris_prepare_jmp(dc, JMP_INDIRECT); dc->delayed_branch--; /* v10 has no dslot here. */ tcg_temp_free(t[0]); } break; case CRISV10_IND_MOVEM_R_M: LOG_DIS("movem_r_m pc=%x opcode=%d r%d r%d\n", dc->pc, dc->opcode, dc->dst, dc->src); dec10_movem_r_m(dc); break; case CRISV10_IND_MOVEM_M_R: LOG_DIS("movem_m_r pc=%x opcode=%d\n", dc->pc, dc->opcode); dec10_movem_m_r(dc); break; case CRISV10_IND_JUMP_R: LOG_DIS("jmp pc=%x opcode=%d r%d r%d\n", dc->pc, dc->opcode, dc->dst, dc->src); tcg_gen_mov_tl(env_btarget, cpu_R[dc->src]); t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len)); cris_prepare_jmp(dc, JMP_INDIRECT); dc->delayed_branch--; /* v10 has no dslot here. */ break; case CRISV10_IND_MOVX: insn_len = dec10_alux_m(dc, CC_OP_MOVE); break; case CRISV10_IND_ADDX: insn_len = dec10_alux_m(dc, CC_OP_ADD); break; case CRISV10_IND_SUBX: insn_len = dec10_alux_m(dc, CC_OP_SUB); break; case CRISV10_IND_CMPX: insn_len = dec10_alux_m(dc, CC_OP_CMP); break; case CRISV10_IND_DIP: insn_len = dec10_dip(dc); break; case CRISV10_IND_BCC_M: cris_cc_mask(dc, 0); imm = ldsw_code(dc->pc + 2); simm = (int16_t)imm; simm += 4; LOG_DIS("bcc_m: b%s %x\n", cc_name(dc->cond), dc->pc + simm); cris_prepare_cc_branch(dc, simm, dc->cond); insn_len = 4; break; default: LOG_DIS("ERROR pc=%x opcode=%d\n", dc->pc, dc->opcode); cpu_abort(dc->env, "Unhandled opcode"); break; } return insn_len; }