static void ser_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct etrax_serial *s = opaque; uint32_t value = val64; unsigned char ch = val64; D(CPUCRISState *env = s->env); D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value)); addr >>= 2; switch (addr) { case RW_DOUT: qemu_chr_fe_write(s->chr, &ch, 1); s->regs[R_INTR] |= 3; s->pending_tx = 1; s->regs[addr] = value; break; case RW_ACK_INTR: if (s->pending_tx) { value &= ~1; s->pending_tx = 0; D(qemu_log("fixedup value=%x r_intr=%x\n", value, s->regs[R_INTR])); } s->regs[addr] = value; s->regs[R_INTR] &= ~value; D(printf("r_intr=%x\n", s->regs[R_INTR])); break; default: s->regs[addr] = value; break; } ser_update_irq(s); }
static void tdk_write(struct PHY *phy, unsigned int req, unsigned int data) { int regnum; regnum = req & 0x1f; DPHY(qemu_log("%s reg[%d] = %x\n", __func__, regnum, data)); switch (regnum) { default: phy->regs[regnum] = data; break; } /* Unconditionally clear regs[BMCR][BMCR_RESET] */ phy->regs[0] &= ~0x8000; }
void helper_put(uint32_t id, uint32_t ctrl, uint32_t data) { int test = ctrl & STREAM_TEST; int atomic = ctrl & STREAM_ATOMIC; int control = ctrl & STREAM_CONTROL; int nonblock = ctrl & STREAM_NONBLOCK; int exception = ctrl & STREAM_EXCEPTION; qemu_log("Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n", id, data, test ? "t" : "", nonblock ? "n" : "", exception ? "e" : "", control ? "c" : "", atomic ? "a" : ""); }
uint32_t HELPER(retw)(uint32_t pc) { int n = (env->regs[0] >> 30) & 0x3; int m = 0; uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env); uint32_t windowstart = env->sregs[WINDOW_START]; uint32_t ret_pc = 0; if (windowstart & windowstart_bit(windowbase - 1, env)) { m = 1; } else if (windowstart & windowstart_bit(windowbase - 2, env)) { m = 2; } else if (windowstart & windowstart_bit(windowbase - 3, env)) { m = 3; } if (n == 0 || (m != 0 && m != n) || ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) != 0) { qemu_log("Illegal retw instruction(pc = %08x), " "PS = %08x, m = %d, n = %d\n", pc, env->sregs[PS], m, n); HELPER(exception_cause)(pc, ILLEGAL_INSTRUCTION_CAUSE); } else { int owb = windowbase; ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff); rotate_window(-n); if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) { env->sregs[WINDOW_START] &= ~windowstart_bit(owb, env); } else { /* window underflow */ env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) | (windowbase << PS_OWB_SHIFT) | PS_EXCM; env->sregs[EPC1] = env->pc = pc; if (n == 1) { HELPER(exception)(EXC_WINDOW_UNDERFLOW4); } else if (n == 2) { HELPER(exception)(EXC_WINDOW_UNDERFLOW8); } else if (n == 3) { HELPER(exception)(EXC_WINDOW_UNDERFLOW12); } } } return ret_pc; }
int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { XtensaCPU *cpu = XTENSA_CPU(cs); CPUXtensaState *env = &cpu->env; uint32_t tmp; const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n; if (n < 0 || n >= env->config->gdb_regmap.num_regs) { return 0; } tmp = ldl_p(mem_buf); switch (reg->type) { case 9: /*pc*/ env->pc = tmp; break; case 1: /*ar*/ env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp; xtensa_sync_window_from_phys(env); break; case 2: /*SR*/ env->sregs[reg->targno & 0xff] = tmp; break; case 3: /*UR*/ env->uregs[reg->targno & 0xff] = tmp; break; case 4: /*f*/ env->fregs[reg->targno & 0x0f] = make_float32(tmp); break; case 8: /*a*/ env->regs[reg->targno & 0x0f] = tmp; break; default: qemu_log("%s to reg %d of unsupported type %d\n", __func__, n, reg->type); return 0; } return 4; }
uint32_t helper_get(uint32_t id, uint32_t ctrl) { int test = ctrl & STREAM_TEST; int atomic = ctrl & STREAM_ATOMIC; int control = ctrl & STREAM_CONTROL; int nonblock = ctrl & STREAM_NONBLOCK; int exception = ctrl & STREAM_EXCEPTION; qemu_log("Unhandled stream get from stream-id=%d %s%s%s%s%s\n", id, test ? "t" : "", nonblock ? "n" : "", exception ? "e" : "", control ? "c" : "", atomic ? "a" : ""); return 0xdead0000 | id; }
static void xtensa_set_irq(void *opaque, int irq, int active) { CPUXtensaState *env = opaque; if (irq >= env->config->ninterrupt) { qemu_log("%s: bad IRQ %d\n", __func__, irq); } else { uint32_t irq_bit = 1 << irq; if (active) { env->sregs[INTSET] |= irq_bit; } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) { env->sregs[INTSET] &= ~irq_bit; } check_interrupts(env); } }
/* CPUClass::reset() */ static void s390_cpu_reset(CPUState *s) { S390CPU *cpu = S390_CPU(s); S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); CPUS390XState *env = &cpu->env; if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); log_cpu_state(env, 0); } scc->parent_reset(s); memset(env, 0, offsetof(CPUS390XState, breakpoints)); /* FIXME: reset vector? */ tlb_flush(env, 1); s390_add_running_cpu(env); }
void cpu_reset(CPUM68KState *env) { if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); log_cpu_state(env, 0); } memset(env, 0, offsetof(CPUM68KState, breakpoints)); #if !defined (CONFIG_USER_ONLY) env->sr = 0x2700; #endif m68k_switch_sp(env); /* ??? FP regs should be initialized to NaN. */ env->cc_op = CC_OP_FLAGS; /* TODO: We should set PC from the interrupt vector. */ env->pc = 0; tlb_flush(env, 1); }
/* CPUClass::reset() */ static void lm32_cpu_reset(CPUState *s) { LM32CPU *cpu = LM32_CPU(s); LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu); CPULM32State *env = &cpu->env; if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); log_cpu_state(env, 0); } lcc->parent_reset(s); tlb_flush(env, 1); /* reset cpu state */ memset(env, 0, offsetof(CPULM32State, breakpoints)); }
void cpu_reset(CPUAVR32State *env) { if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset\n"); log_cpu_state(env, 0); } memset(env, 0, offsetof(CPUAVR32State, breakpoints)); #if defined (CONFIG_USER_ONLY) env->sreg.sr = AVR32_SR_M_MASK & (AVR32_SR_M_APP << AVR32_SR_M_OFFSET); /* SN: TBD - Should we enable interrupts?? */ #else /* Supervisor mode with interrupts disabled. */ env->sreg.sr = (AVR32_SR_M_MASK & (AVR32_SR_M_SUP << AVR32_SR_M_OFFSET)) | AVR32_SR_GM_MASK | AVR32_SR_EM_MASK; #endif tlb_flush(env, 1); }
/* CPUClass::reset() */ static void mips_cpu_reset(CPUState *s) { MIPSCPU *cpu = MIPS_CPU(s); MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu); CPUMIPSState *env = &cpu->env; if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); log_cpu_state(env, 0); } mcc->parent_reset(s); memset(env, 0, offsetof(CPUMIPSState, breakpoints)); tlb_flush(env, 1); cpu_state_reset(env); }
static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size) { SiFivePLICState *plic = opaque; /* writes must be 4 byte words */ if ((addr & 0x3) != 0) { goto err; } if (addr >= plic->priority_base && /* 4 bytes per source */ addr < plic->priority_base + (plic->num_sources << 2)) { uint32_t irq = (addr - plic->priority_base) >> 2; if (RISCV_DEBUG_PLIC) { qemu_log("plic: read priority: irq=%d priority=%d\n", irq, plic->source_priority[irq]); } return plic->source_priority[irq]; } else if (addr >= plic->pending_base && /* 1 bit per source */
void cpu_reset(CPUSPARCState *env) { if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); log_cpu_state(env, 0); } tlb_flush(env, 1); env->cwp = 0; #ifndef TARGET_SPARC64 env->wim = 1; #endif env->regwptr = env->regbase + (env->cwp * 16); CC_OP = CC_OP_FLAGS; #if defined(CONFIG_USER_ONLY) #ifdef TARGET_SPARC64 env->cleanwin = env->nwindows - 2; env->cansave = env->nwindows - 2; env->pstate = PS_RMO | PS_PEF | PS_IE; env->asi = 0x82; /* Primary no-fault */ #endif #else #if !defined(TARGET_SPARC64) env->psret = 0; env->psrs = 1; env->psrps = 1; #endif #ifdef TARGET_SPARC64 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG; env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0; env->tl = env->maxtl; cpu_tsptr(env)->tt = TT_POWER_ON_RESET; env->lsu = 0; #else env->mmuregs[0] &= ~(MMU_E | MMU_NF); env->mmuregs[0] |= env->def->mmu_bm; #endif env->pc = 0; env->npc = env->pc + 4; #endif env->cache_control = 0; }
static void serial_receive(void *opaque, const uint8_t *buf, int size) { struct etrax_serial *s = opaque; int i; /* Got a byte. */ if (s->rx_fifo_len >= 16) { qemu_log("WARNING: UART dropped char.\n"); return; } for (i = 0; i < size; i++) { s->rx_fifo[s->rx_fifo_pos] = buf[i]; s->rx_fifo_pos++; s->rx_fifo_pos &= 15; s->rx_fifo_len++; } ser_update_irq(s); }
static void openrisc_sim_init(QEMUMachineInitArgs *args) { ram_addr_t ram_size = args->ram_size; const char *cpu_model = args->cpu_model; const char *kernel_filename = args->kernel_filename; OpenRISCCPU *cpu = NULL; MemoryRegion *ram; int n; if (!cpu_model) { cpu_model = "or1200"; } for (n = 0; n < smp_cpus; n++) { cpu = cpu_openrisc_init(cpu_model); if (cpu == NULL) { qemu_log("Unable to find CPU defineition!\n"); exit(1); } qemu_register_reset(main_cpu_reset, cpu); main_cpu_reset(cpu); } ram = g_malloc(sizeof(*ram)); memory_region_init_ram(ram, "openrisc.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); cpu_openrisc_pic_init(cpu); cpu_openrisc_clock_init(cpu); serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); if (nd_table[0].used) { openrisc_sim_net_init(get_system_memory(), 0x92000000, 0x92000400, cpu->env.irq[4], nd_table); } cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu); }
uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c) { uint32_t d, cf = 1, ncf; if (c) cf = env->sregs[SR_MSR] >> 31; assert(cf == 0 || cf == 1); d = b + ~a + cf; if (!k) { ncf = compute_carry(b, ~a, cf); assert(ncf == 0 || ncf == 1); if (ncf) env->sregs[SR_MSR] |= MSR_C | MSR_CC; else env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC); } D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n", d, a, b, cf, ncf, k, c)); return d; }
void tlb_fill(CPUXtensaState *env, target_ulong vaddr, int is_write, int mmu_idx, uintptr_t retaddr) { uint32_t paddr; uint32_t page_size; unsigned access; int ret = xtensa_get_physical_addr(env, true, vaddr, is_write, mmu_idx, &paddr, &page_size, &access); qemu_log("%s(%08x, %d, %d) -> %08x, ret = %d\n", __func__, vaddr, is_write, mmu_idx, paddr, ret); if (ret == 0) { tlb_set_page(env, vaddr & TARGET_PAGE_MASK, paddr & TARGET_PAGE_MASK, access, mmu_idx, page_size); } else { cpu_restore_state(env, retaddr); HELPER(exception_cause_vaddr)(env, env->pc, ret, vaddr); } }
int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) { XtensaCPU *cpu = XTENSA_CPU(cs); CPUXtensaState *env = &cpu->env; const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n; if (n < 0 || n >= env->config->gdb_regmap.num_regs) { return 0; } switch (reg->type) { case 9: /*pc*/ return gdb_get_reg32(mem_buf, env->pc); case 1: /*ar*/ xtensa_sync_phys_from_window(env); return gdb_get_reg32(mem_buf, env->phys_regs[(reg->targno & 0xff) % env->config->nareg]); case 2: /*SR*/ return gdb_get_reg32(mem_buf, env->sregs[reg->targno & 0xff]); case 3: /*UR*/ return gdb_get_reg32(mem_buf, env->uregs[reg->targno & 0xff]); case 4: /*f*/ return gdb_get_reg32(mem_buf, float32_val(env->fregs[reg->targno & 0x0f])); case 8: /*a*/ return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]); default: qemu_log("%s from reg %d of unsupported type %d\n", __func__, n, reg->type); return 0; } }
static uint32_t uart_readl (void *opaque, target_phys_addr_t addr) { struct xlx_uartlite *s = opaque; uint32_t r = 0; addr >>= 2; switch (addr) { case R_RX: r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 7]; if (s->rx_fifo_len) s->rx_fifo_len--; uart_update_status(s); uart_update_irq(s); break; default: if (addr < ARRAY_SIZE(s->regs)) r = s->regs[addr]; DUART(qemu_log("%s addr=%x v=%x\n", __func__, addr, r)); break; } return r; }
/* CPUClass::reset() */ static void nios2_cpu_reset(CPUState *cs) { Nios2CPU *cpu = NIOS2_CPU(cs); Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(cpu); CPUNios2State *env = &cpu->env; if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", cs->cpu_index); log_cpu_state(cs, 0); } ncc->parent_reset(cs); memset(env->regs, 0, sizeof(uint32_t) * NUM_CORE_REGS); env->regs[R_PC] = cpu->reset_addr; #if defined(CONFIG_USER_ONLY) /* Start in user mode with interrupts enabled. */ env->regs[CR_STATUS] = CR_STATUS_U | CR_STATUS_PIE; #else env->regs[CR_STATUS] = 0; #endif }
void HELPER(sacf)(CPUS390XState *env, uint64_t a1) { HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1); switch (a1 & 0xf00) { case 0x000: env->psw.mask &= ~PSW_MASK_ASC; env->psw.mask |= PSW_ASC_PRIMARY; break; case 0x100: env->psw.mask &= ~PSW_MASK_ASC; env->psw.mask |= PSW_ASC_SECONDARY; break; case 0x300: env->psw.mask &= ~PSW_MASK_ASC; env->psw.mask |= PSW_ASC_HOME; break; default: qemu_log("unknown sacf mode: %" PRIx64 "\n", a1); program_interrupt(env, PGM_SPECIFICATION, 2); break; } }
/* CPUClass::reset() */ static void m68k_cpu_reset(CPUState *s) { M68kCPU *cpu = M68K_CPU(s); M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu); CPUM68KState *env = &cpu->env; if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); log_cpu_state(env, 0); } mcc->parent_reset(s); memset(env, 0, offsetof(CPUM68KState, breakpoints)); #if !defined(CONFIG_USER_ONLY) env->sr = 0x2700; #endif m68k_switch_sp(env); /* ??? FP regs should be initialized to NaN. */ env->cc_op = CC_OP_FLAGS; /* TODO: We should set PC from the interrupt vector. */ env->pc = 0; tlb_flush(env, 1); }
void helper_debug(CPUMBState *env) { int i; qemu_log("PC=%8.8x\n", env->sregs[SR_PC]); qemu_log("rmsr=%x resr=%x rear=%x debug[%x] imm=%x iflags=%x\n", env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], env->debug, env->imm, env->iflags); qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n", env->btaken, env->btarget, (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", (env->sregs[SR_MSR] & MSR_EIP), (env->sregs[SR_MSR] & MSR_IE)); for (i = 0; i < 32; i++) { qemu_log("r%2.2d=%8.8x ", i, env->regs[i]); if ((i + 1) % 4 == 0) qemu_log("\n"); } qemu_log("\n\n"); }
/* generate intermediate code for basic block 'tb'. */ static void gen_intermediate_code_internal( CPUNios2State *env, TranslationBlock *tb, int search_pc) { DisasContext dc1, *dc = &dc1; int num_insns; int max_insns; uint32_t next_page_start; int j, lj = -1; uint16_t *gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; /* Initialize DC */ dc->env = env; dc->cpu_R = cpu_R; dc->is_jmp = DISAS_NEXT; dc->pc = tb->pc; dc->tb = tb; /* Dump the CPU state to the log */ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("--------------\n"); log_cpu_state(env, 0); } /* Set up instruction counts */ num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { max_insns = CF_COUNT_MASK; } next_page_start = (tb->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; gen_icount_start(); do { /* Mark instruction start with associated PC */ if (search_pc) { j = gen_opc_ptr - gen_opc_buf; if (lj < j) { lj++; while (lj < j) { gen_opc_instr_start[lj++] = 0; } } gen_opc_pc[lj] = dc->pc; gen_opc_instr_start[lj] = 1; gen_opc_icount[lj] = num_insns; } LOG_DIS("%8.8x:\t", dc->pc); if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } /* Decode an instruction */ handle_instruction(dc); dc->pc += 4; num_insns++; /* Translation stops when a conditional branch is encountered. * Otherwise the subsequent code could get translated several times. * Also stop translation when a page boundary is reached. This * ensures prefetch aborts occur at the right place. */ } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && !env->singlestep_enabled && !singlestep && dc->pc < next_page_start && num_insns < max_insns); if (tb->cflags & CF_LAST_IO) { gen_io_end(); } /* Indicate where the next block should start */ switch (dc->is_jmp) { case DISAS_NEXT: /* Save the current PC back into the CPU register */ tcg_gen_movi_tl(cpu_R[R_PC], dc->pc); tcg_gen_exit_tb(0); break; default: case DISAS_JUMP: case DISAS_UPDATE: /* The jump will already have updated the PC register */ tcg_gen_exit_tb(0); break; case DISAS_TB_JUMP: /* nothing more to generate */ break; } /* End off the block */ gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; /* Mark instruction starts for the final generated instruction */ if (search_pc) { j = gen_opc_ptr - gen_opc_buf; lj++; while (lj <= j) { gen_opc_instr_start[lj++] = 0; } } else { tb->size = dc->pc - tb->pc; tb->icount = num_insns; } #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("----------------\n"); qemu_log("IN: %s\n", lookup_symbol(tb->pc)); log_target_disas(tb->pc, dc->pc - tb->pc, 0); qemu_log("\nisize=%d osize=%td\n", dc->pc - tb->pc, gen_opc_ptr - gen_opc_buf); } #endif }
int cpu_mb_handle_mmu_fault (CPUMBState *env, target_ulong address, int rw, int mmu_idx) { unsigned int hit; unsigned int mmu_available; int r = 1; int prot; mmu_available = 0; if (env->pvr.regs[0] & PVR0_USE_MMU) { mmu_available = 1; if ((env->pvr.regs[0] & PVR0_PVR_FULL_MASK) && (env->pvr.regs[11] & PVR11_USE_MMU) != PVR11_USE_MMU) { mmu_available = 0; } } /* Translate if the MMU is available and enabled. */ if (mmu_available && (env->sregs[SR_MSR] & MSR_VM)) { target_ulong vaddr, paddr; struct microblaze_mmu_lookup lu; hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx); if (hit) { vaddr = address & TARGET_PAGE_MASK; paddr = lu.paddr + vaddr - lu.vaddr; DMMU(qemu_log("MMU map mmu=%d v=%x p=%x prot=%x\n", mmu_idx, vaddr, paddr, lu.prot)); tlb_set_page(env, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE); r = 0; } else { env->sregs[SR_EAR] = address; DMMU(qemu_log("mmu=%d miss v=%x\n", mmu_idx, address)); switch (lu.err) { case ERR_PROT: env->sregs[SR_ESR] = rw == 2 ? 17 : 16; env->sregs[SR_ESR] |= (rw == 1) << 10; break; case ERR_MISS: env->sregs[SR_ESR] = rw == 2 ? 19 : 18; env->sregs[SR_ESR] |= (rw == 1) << 10; break; default: abort(); break; } if (env->exception_index == EXCP_MMU) { cpu_abort(env, "recursive faults\n"); } /* TLB miss. */ env->exception_index = EXCP_MMU; } } else { /* MMU disabled or not available. */ address &= TARGET_PAGE_MASK; prot = PAGE_BITS; tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE); r = 0; } return r; }
void do_interrupt(CPUMBState *env) { uint32_t t; /* IMM flag cannot propagate across a branch and into the dslot. */ assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG))); assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG))); /* assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions. */ env->res_addr = RES_ADDR_NONE; switch (env->exception_index) { case EXCP_HW_EXCP: if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) { qemu_log("Exception raised on system without exceptions!\n"); return; } env->regs[17] = env->sregs[SR_PC] + 4; env->sregs[SR_ESR] &= ~(1 << 12); /* Exception breaks branch + dslot sequence? */ if (env->iflags & D_FLAG) { env->sregs[SR_ESR] |= 1 << 12 ; env->sregs[SR_BTR] = env->btarget; } /* Disable the MMU. */ t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); env->sregs[SR_MSR] |= t; /* Exception in progress. */ env->sregs[SR_MSR] |= MSR_EIP; qemu_log_mask(CPU_LOG_INT, "hw exception at pc=%x ear=%x esr=%x iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_EAR], env->sregs[SR_ESR], env->iflags); log_cpu_state_mask(CPU_LOG_INT, env, 0); env->iflags &= ~(IMM_FLAG | D_FLAG); env->sregs[SR_PC] = 0x20; break; case EXCP_MMU: env->regs[17] = env->sregs[SR_PC]; env->sregs[SR_ESR] &= ~(1 << 12); /* Exception breaks branch + dslot sequence? */ if (env->iflags & D_FLAG) { D(qemu_log("D_FLAG set at exception bimm=%d\n", env->bimm)); env->sregs[SR_ESR] |= 1 << 12 ; env->sregs[SR_BTR] = env->btarget; /* Reexecute the branch. */ env->regs[17] -= 4; /* was the branch immprefixed?. */ if (env->bimm) { qemu_log_mask(CPU_LOG_INT, "bimm exception at pc=%x iflags=%x\n", env->sregs[SR_PC], env->iflags); env->regs[17] -= 4; log_cpu_state_mask(CPU_LOG_INT, env, 0); } } else if (env->iflags & IMM_FLAG) { D(qemu_log("IMM_FLAG set at exception\n")); env->regs[17] -= 4; } /* Disable the MMU. */ t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); env->sregs[SR_MSR] |= t; /* Exception in progress. */ env->sregs[SR_MSR] |= MSR_EIP; qemu_log_mask(CPU_LOG_INT, "exception at pc=%x ear=%x iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags); log_cpu_state_mask(CPU_LOG_INT, env, 0); env->iflags &= ~(IMM_FLAG | D_FLAG); env->sregs[SR_PC] = 0x20; break; case EXCP_IRQ: assert(!(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))); assert(env->sregs[SR_MSR] & MSR_IE); assert(!(env->iflags & D_FLAG)); t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; #if 0 #include "disas.h" /* Useful instrumentation when debugging interrupt issues in either the models or in sw. */ { const char *sym; sym = lookup_symbol(env->sregs[SR_PC]); if (sym && (!strcmp("netif_rx", sym) || !strcmp("process_backlog", sym))) { qemu_log( "interrupt at pc=%x msr=%x %x iflags=%x sym=%s\n", env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags, sym); log_cpu_state(env, 0); } } #endif qemu_log_mask(CPU_LOG_INT, "interrupt at pc=%x msr=%x %x iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM \ | MSR_UM | MSR_IE); env->sregs[SR_MSR] |= t; env->regs[14] = env->sregs[SR_PC]; env->sregs[SR_PC] = 0x10; //log_cpu_state_mask(CPU_LOG_INT, env, 0); break; case EXCP_BREAK: case EXCP_HW_BREAK: assert(!(env->iflags & IMM_FLAG)); assert(!(env->iflags & D_FLAG)); t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; qemu_log_mask(CPU_LOG_INT, "break at pc=%x msr=%x %x iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); log_cpu_state_mask(CPU_LOG_INT, env, 0); env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); env->sregs[SR_MSR] |= t; env->sregs[SR_MSR] |= MSR_BIP; if (env->exception_index == EXCP_HW_BREAK) { env->regs[16] = env->sregs[SR_PC]; env->sregs[SR_MSR] |= MSR_BIP; env->sregs[SR_PC] = 0x18; } else env->sregs[SR_PC] = env->btarget; break; default: cpu_abort(env, "unhandled exception type=%d\n", env->exception_index); break; } }
void sparc_cpu_do_interrupt(CPUState *cs) { SPARCCPU *cpu = SPARC_CPU(cs); CPUSPARCState *env = &cpu->env; int intno = cs->exception_index; trap_state *tsptr; /* Compute PSR before exposing state. */ if (env->cc_op != CC_OP_FLAGS) { cpu_get_psr(env); } #ifdef DEBUG_PCALL if (qemu_loglevel_mask(CPU_LOG_INT)) { static int count; const char *name; if (intno < 0 || intno >= 0x180) { name = "Unknown"; } else if (intno >= 0x100) { name = "Trap Instruction"; } else if (intno >= 0xc0) { name = "Window Fill"; } else if (intno >= 0x80) { name = "Window Spill"; } else { name = excp_names[intno]; if (!name) { name = "Unknown"; } } qemu_log("%6d: %s (v=%04x)\n", count, name, intno); log_cpu_state(cs, 0); #if 0 { int i; uint8_t *ptr; qemu_log(" code="); ptr = (uint8_t *)env->pc; for (i = 0; i < 16; i++) { qemu_log(" %02x", ldub(ptr + i)); } qemu_log("\n"); } #endif count++; } #endif #if !defined(CONFIG_USER_ONLY) if (env->tl >= env->maxtl) { cpu_abort(cs, "Trap 0x%04x while trap level (%d) >= MAXTL (%d)," " Error state", cs->exception_index, env->tl, env->maxtl); return; } #endif if (env->tl < env->maxtl - 1) { env->tl++; } else { env->pstate |= PS_RED; if (env->tl < env->maxtl) { env->tl++; } } tsptr = cpu_tsptr(env); tsptr->tstate = (cpu_get_ccr(env) << 32) | ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) | cpu_get_cwp64(env); tsptr->tpc = env->pc; tsptr->tnpc = env->npc; tsptr->tt = intno; switch (intno) { case TT_IVEC: cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG); break; case TT_TFAULT: case TT_DFAULT: case TT_TMISS ... TT_TMISS + 3: case TT_DMISS ... TT_DMISS + 3: case TT_DPROT ... TT_DPROT + 3: cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG); break; default: cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG); break; } if (intno == TT_CLRWIN) { cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); } else if ((intno & 0x1c0) == TT_SPILL) { cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); } else if ((intno & 0x1c0) == TT_FILL) { cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1)); } env->tbr &= ~0x7fffULL; env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); env->pc = env->tbr; env->npc = env->pc + 4; cs->exception_index = -1; }
void cpu_unassigned_access(CPUNios2State *env1, target_phys_addr_t addr, int is_write, int is_exec, int is_asi, int size) { qemu_log("unassigned access to %08X\n", addr); }
/* NOTE: must be called outside the CPU execute loop */ void cpu_reset(CPUX86State *env) { int i; if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP); } memset(env, 0, offsetof(CPUX86State, breakpoints)); tlb_flush(env, 1); env->old_exception = -1; /* init to reset state */ #ifdef CONFIG_SOFTMMU env->hflags |= HF_SOFTMMU_MASK; #endif env->hflags2 |= HF2_GIF_MASK; cpu_x86_update_cr0(env, 0x60000010); env->a20_mask = ~0x0; env->smbase = 0x30000; env->idt.limit = 0xffff; env->gdt.limit = 0xffff; env->ldt.limit = 0xffff; env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT); env->tr.limit = 0xffff; env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT); cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); env->eip = 0xfff0; env->regs[R_EDX] = env->cpuid_version; env->eflags = 0x2; /* FPU init */ for(i = 0;i < 8; i++) env->fptags[i] = 1; env->fpuc = 0x37f; env->mxcsr = 0x1f80; memset(env->dr, 0, sizeof(env->dr)); env->dr[6] = DR6_FIXED_1; env->dr[7] = DR7_FIXED_1; cpu_breakpoint_remove_all(env, BP_CPU); cpu_watchpoint_remove_all(env, BP_CPU); env->mcg_status = 0; }