Nios2CPU *cpu_nios2_init(const char *cpu_model) { Nios2CPU *cpu; int i; cpu = NIOS2_CPU(object_new(TYPE_NIOS2_CPU)); cpu->env.reset_addr = RESET_ADDRESS; cpu->env.exception_addr = EXCEPTION_ADDRESS; cpu->env.fast_tlb_miss_addr = FAST_TLB_MISS_ADDRESS; cpu_reset(CPU(cpu)); qemu_init_vcpu(&cpu->env); cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); for (i = 0; i < NUM_CORE_REGS; i++) { cpu_R[i] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUNios2State, regs[i]), regnames[i]); } #define GEN_HELPER 2 #include "helper.h" return cpu; }
void nios2_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { Nios2CPU *cpu = NIOS2_CPU(cs); CPUNios2State *env = &cpu->env; int i; if (!env || !f) { return; } cpu_fprintf(f, "IN: PC=%x %s\n", env->regs[R_PC], lookup_symbol(env->regs[R_PC])); for (i = 0; i < NUM_CORE_REGS; i++) { cpu_fprintf(f, "%9s=%8.8x ", regnames[i], env->regs[i]); if ((i + 1) % 4 == 0) { cpu_fprintf(f, "\n"); } } cpu_fprintf(f, " mmu write: VPN=%05X PID %02X TLBACC %08X\n", env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK, (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4, env->mmu.tlbacc_wr); cpu_fprintf(f, "\n\n"); }
static void nios2_cpu_set_pc(CPUState *cs, vaddr value) { Nios2CPU *cpu = NIOS2_CPU(cs); CPUNios2State *env = &cpu->env; env->regs[R_PC] = value; }
static void altera_iic_realize(DeviceState *dev, Error **errp) { struct AlteraIIC *pv = ALTERA_IIC(dev); Error *err = NULL; pv->cpu = NIOS2_CPU(object_property_get_link(OBJECT(dev), "cpu", &err)); if (!pv->cpu) { error_setg(errp, "altera,iic: CPU link not found: %s", error_get_pretty(err)); return; } }
static void nios2_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); Nios2CPU *cpu = NIOS2_CPU(obj); CPUNios2State *env = &cpu->env; cs->env_ptr = env; #if !defined(CONFIG_USER_ONLY) mmu_init(env); #endif }
static bool nios2_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { Nios2CPU *cpu = NIOS2_CPU(cs); CPUNios2State *env = &cpu->env; if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->regs[CR_STATUS] & CR_STATUS_PIE)) { cs->exception_index = EXCP_IRQ; nios2_cpu_do_interrupt(cs); return true; } return false; }
static void nios2_generic_nommu_init(MachineState *machine) { Nios2CPU *cpu; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *phys_tcm = g_new(MemoryRegion, 1); MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1); MemoryRegion *phys_ram = g_new(MemoryRegion, 1); MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1); ram_addr_t tcm_base = 0x0; ram_addr_t tcm_size = 0x1000; /* 1 kiB, but QEMU limit is 4 kiB */ ram_addr_t ram_base = 0x10000000; ram_addr_t ram_size = 0x08000000; /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */ memory_region_init_ram(phys_tcm, NULL, "nios2.tcm", tcm_size, &error_abort); memory_region_init_alias(phys_tcm_alias, NULL, "nios2.tcm.alias", phys_tcm, 0, tcm_size); memory_region_add_subregion(address_space_mem, tcm_base, phys_tcm); memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base, phys_tcm_alias); /* Physical DRAM with alias at 0xc0000000 */ memory_region_init_ram(phys_ram, NULL, "nios2.ram", ram_size, &error_abort); memory_region_init_alias(phys_ram_alias, NULL, "nios2.ram.alias", phys_ram, 0, ram_size); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base, phys_ram_alias); cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU)); /* Remove MMU */ cpu->mmu_present = false; /* Reset vector is the first 32 bytes of RAM. */ cpu->reset_addr = ram_base; /* The interrupt vector comes right after reset. */ cpu->exception_addr = ram_base + 0x20; /* * The linker script does have a TLB miss memory region declared, * but this should never be used with no MMU. */ cpu->fast_tlb_miss_addr = 0x7fff400; nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename, BINARY_DEVICE_TREE_FILE, NULL); }
static int nios2_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { Nios2CPU *cpu = NIOS2_CPU(cs); CPUClass *cc = CPU_GET_CLASS(cs); CPUNios2State *env = &cpu->env; if (n > cc->gdb_num_core_regs) { return 0; } if (n < 32) { /* GP regs */ env->regs[n] = ldl_p(mem_buf); } else if (n == 32) { /* PC */ env->regs[R_PC] = ldl_p(mem_buf); } else if (n < 49) { /* Status regs */ env->regs[n - 1] = ldl_p(mem_buf); } return 4; }
static int nios2_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) { Nios2CPU *cpu = NIOS2_CPU(cs); CPUClass *cc = CPU_GET_CLASS(cs); CPUNios2State *env = &cpu->env; if (n > cc->gdb_num_core_regs) { return 0; } if (n < 32) { /* GP regs */ return gdb_get_reg32(mem_buf, env->regs[n]); } else if (n == 32) { /* PC */ return gdb_get_reg32(mem_buf, env->regs[R_PC]); } else if (n < 49) { /* Status regs */ return gdb_get_reg32(mem_buf, env->regs[n - 1]); } /* Invalid regs */ return 0; }
/* 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 }