static void do_unaligned_access(CPUAlphaState *env, target_ulong addr, int is_write, int is_user, void *retaddr) { uint64_t pc; uint32_t insn; do_restore_state(env, retaddr); pc = env->pc; insn = cpu_ldl_code(env, pc); env->trap_arg0 = addr; env->trap_arg1 = insn >> 26; /* opcode */ env->trap_arg2 = (insn >> 21) & 31; /* dest regno */ env->exception_index = EXCP_UNALIGN; env->error_code = 0; cpu_loop_exit(env); }
void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { AlphaCPU *cpu = ALPHA_CPU(cs); CPUAlphaState *env = &cpu->env; uint64_t pc; uint32_t insn; if (retaddr) { cpu_restore_state(cs, retaddr); } pc = env->pc; insn = cpu_ldl_code(env, pc); env->trap_arg0 = addr; env->trap_arg1 = insn >> 26; /* opcode */ env->trap_arg2 = (insn >> 21) & 31; /* dest regno */ cs->exception_index = EXCP_UNALIGN; env->error_code = 0; cpu_loop_exit(cs); }
static void do_interrupt_all(CPUM68KState *env, int is_hw) { CPUState *cs; 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(env); return; case EXCP_HALT_INSN: if (semihosting_enabled && (env->sr & SR_S) != 0 && (env->pc & 3) == 0 && cpu_lduw_code(env, env->pc - 4) == 0x4e71 && cpu_ldl_code(env, env->pc) == 0x4e7bf000) { env->pc += 4; do_m68k_semihosting(env, env->dregs[0]); return; } cs = CPU(m68k_env_get_cpu(env)); cs->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(env); 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; cpu_stl_kernel(env, sp, retaddr); sp -= 4; cpu_stl_kernel(env, sp, fmt); env->aregs[7] = sp; /* Jump to vector. */ env->pc = cpu_ldl_kernel(env, env->vbr + vector); }
/* generate intermediate code for basic block 'tb'. */ void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb) { LM32CPU *cpu = lm32_env_get_cpu(env); CPUState *cs = CPU(cpu); struct DisasContext ctx, *dc = &ctx; uint32_t pc_start; uint32_t next_page_start; int num_insns; int max_insns; pc_start = tb->pc; dc->features = cpu->features; dc->num_breakpoints = cpu->num_breakpoints; dc->num_watchpoints = cpu->num_watchpoints; dc->tb = tb; dc->is_jmp = DISAS_NEXT; dc->pc = pc_start; dc->singlestep_enabled = cs->singlestep_enabled; if (pc_start & 3) { qemu_log_mask(LOG_GUEST_ERROR, "unaligned PC=%x. Ignoring lowest bits.\n", pc_start); pc_start &= ~3; } next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { max_insns = CF_COUNT_MASK; } if (max_insns > TCG_MAX_INSNS) { max_insns = TCG_MAX_INSNS; } gen_tb_start(tb); do { tcg_gen_insn_start(dc->pc); num_insns++; if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { tcg_gen_movi_tl(cpu_pc, dc->pc); t_gen_raise_exception(dc, EXCP_DEBUG); dc->is_jmp = DISAS_UPDATE; /* The address covered by the breakpoint must be included in [tb->pc, tb->pc + tb->size) in order to for it to be properly cleared -- thus we increment the PC here so that the logic setting tb->size below does the right thing. */ dc->pc += 4; break; } /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } decode(dc, cpu_ldl_code(env, dc->pc)); dc->pc += 4; } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep && (dc->pc < next_page_start) && num_insns < max_insns); if (tb->cflags & CF_LAST_IO) { gen_io_end(); } if (unlikely(cs->singlestep_enabled)) { if (dc->is_jmp == DISAS_NEXT) { tcg_gen_movi_tl(cpu_pc, dc->pc); } t_gen_raise_exception(dc, EXCP_DEBUG); } else { switch (dc->is_jmp) { case DISAS_NEXT: gen_goto_tb(dc, 1, dc->pc); break; default: case DISAS_JUMP: case DISAS_UPDATE: /* indicate that the hash table must be used to find the next TB */ tcg_gen_exit_tb(0); break; case DISAS_TB_JUMP: /* nothing more to generate */ break; } } gen_tb_end(tb, num_insns); tb->size = dc->pc - pc_start; tb->icount = num_insns; #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("\n"); log_target_disas(cs, pc_start, dc->pc - pc_start, 0); qemu_log("\nisize=%d osize=%d\n", dc->pc - pc_start, tcg_op_buf_count()); } #endif }