diff options
Diffstat (limited to 'target/sparc/cpu.c')
-rw-r--r-- | target/sparc/cpu.c | 190 |
1 files changed, 115 insertions, 75 deletions
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 21dd27796d..e820f50acf 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -25,17 +25,19 @@ #include "exec/exec-all.h" #include "hw/qdev-properties.h" #include "qapi/visitor.h" +#include "tcg/tcg.h" //#define DEBUG_FEATURES -static void sparc_cpu_reset(DeviceState *dev) +static void sparc_cpu_reset_hold(Object *obj) { - CPUState *s = CPU(dev); - SPARCCPU *cpu = SPARC_CPU(s); - SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu); - CPUSPARCState *env = &cpu->env; + CPUState *cs = CPU(obj); + SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj); + CPUSPARCState *env = cpu_env(cs); - scc->parent_reset(dev); + if (scc->parent_phases.hold) { + scc->parent_phases.hold(obj); + } memset(env, 0, offsetof(CPUSPARCState, end_reset_fields)); env->cwp = 0; @@ -43,7 +45,6 @@ static void sparc_cpu_reset(DeviceState *dev) 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; @@ -81,8 +82,7 @@ static void sparc_cpu_reset(DeviceState *dev) static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { if (interrupt_request & CPU_INTERRUPT_HARD) { - SPARCCPU *cpu = SPARC_CPU(cs); - CPUSPARCState *env = &cpu->env; + CPUSPARCState *env = cpu_env(cs); if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) { int pil = env->interrupt_index & 0xf; @@ -366,7 +366,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "Fujitsu MB86904", .iu_version = 0x04 << 24, /* Impl 0, ver 4 */ - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */ .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x00ffffc0, @@ -379,7 +379,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "Fujitsu MB86907", .iu_version = 0x05 << 24, /* Impl 0, ver 5 */ - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */ .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0xffffffc0, @@ -392,7 +392,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI MicroSparc I", .iu_version = 0x41000000, - .fpu_version = 4 << 17, + .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x41000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x007ffff0, @@ -400,14 +400,12 @@ static const sparc_def_t sparc_defs[] = { .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0x0000003f, .nwindows = 7, - .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL | - CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | - CPU_FEATURE_FMUL, + .features = CPU_FEATURE_MUL | CPU_FEATURE_DIV, }, { .name = "TI MicroSparc II", .iu_version = 0x42000000, - .fpu_version = 4 << 17, + .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x02000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x00ffffc0, @@ -420,7 +418,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI MicroSparc IIep", .iu_version = 0x42000000, - .fpu_version = 4 << 17, + .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x04000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x00ffffc0, @@ -433,7 +431,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 40", /* STP1020NPGA */ .iu_version = 0x41000000, /* SuperSPARC 2.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -446,7 +444,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 50", /* STP1020PGA */ .iu_version = 0x40000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -459,7 +457,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 51", .iu_version = 0x40000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -473,7 +471,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 60", /* STP1020APGA */ .iu_version = 0x40000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -486,7 +484,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc 61", .iu_version = 0x44000000, /* SuperSPARC 3.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -500,7 +498,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "TI SuperSparc II", .iu_version = 0x40000000, /* SuperSPARC II 1.x */ - .fpu_version = 0 << 17, + .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */ .mmu_bm = 0x00002000, .mmu_ctpr_mask = 0xffffffc0, @@ -514,7 +512,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "LEON2", .iu_version = 0xf2000000, - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0xf2000000, .mmu_bm = 0x00004000, .mmu_ctpr_mask = 0x007ffff0, @@ -527,7 +525,7 @@ static const sparc_def_t sparc_defs[] = { { .name = "LEON3", .iu_version = 0xf3000000, - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ + .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0xf3000000, .mmu_bm = 0x00000000, .mmu_ctpr_mask = 0xfffffffc, @@ -542,21 +540,20 @@ static const sparc_def_t sparc_defs[] = { #endif }; +/* This must match sparc_cpu_properties[]. */ static const char * const feature_name[] = { - "float", - "float128", - "swap", - "mul", - "div", - "flush", - "fsqrt", - "fmul", - "vis1", - "vis2", - "fsmuld", - "hypv", - "cmt", - "gl", + [CPU_FEATURE_BIT_FLOAT128] = "float128", +#ifdef TARGET_SPARC64 + [CPU_FEATURE_BIT_CMT] = "cmt", + [CPU_FEATURE_BIT_GL] = "gl", + [CPU_FEATURE_BIT_HYPV] = "hypv", + [CPU_FEATURE_BIT_VIS1] = "vis1", + [CPU_FEATURE_BIT_VIS2] = "vis2", +#else + [CPU_FEATURE_BIT_MUL] = "mul", + [CPU_FEATURE_BIT_DIV] = "div", + [CPU_FEATURE_BIT_FSMULD] = "fsmuld", +#endif }; static void print_features(uint32_t features, const char *prefix) @@ -577,9 +574,10 @@ void sparc_cpu_list(void) { unsigned int i; + qemu_printf("Available CPU types:\n"); for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) { - qemu_printf("Sparc %16s IU " TARGET_FMT_lx - " FPU %08x MMU %08x NWINS %d ", + qemu_printf(" %-20s (IU " TARGET_FMT_lx + " FPU %08x MMU %08x NWINS %d) ", sparc_defs[i].name, sparc_defs[i].iu_version, sparc_defs[i].fpu_version, @@ -614,8 +612,7 @@ static void cpu_print_cc(FILE *f, uint32_t cc) static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags) { - SPARCCPU *cpu = SPARC_CPU(cs); - CPUSPARCState *env = &cpu->env; + CPUSPARCState *env = cpu_env(cs); int i, x; qemu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, @@ -670,8 +667,8 @@ static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags) "cleanwin: %d cwp: %d\n", env->cansave, env->canrestore, env->otherwin, env->wstate, env->cleanwin, env->nwindows - 1 - env->cwp); - qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: " - TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs); + qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: %016x\n", + cpu_get_fsr(env), env->y, env->fprs); #else qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env)); @@ -680,7 +677,7 @@ static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags) env->psrps ? 'P' : '-', env->psret ? 'E' : '-', env->wim); qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n", - env->fsr, env->y); + cpu_get_fsr(env), env->y); #endif qemu_fprintf(f, "\n"); } @@ -693,22 +690,55 @@ static void sparc_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.npc = value + 4; } +static vaddr sparc_cpu_get_pc(CPUState *cs) +{ + SPARCCPU *cpu = SPARC_CPU(cs); + + return cpu->env.pc; +} + static void sparc_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { SPARCCPU *cpu = SPARC_CPU(cs); + tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL)); cpu->env.pc = tb->pc; cpu->env.npc = tb->cs_base; } static bool sparc_cpu_has_work(CPUState *cs) { - SPARCCPU *cpu = SPARC_CPU(cs); - CPUSPARCState *env = &cpu->env; - return (cs->interrupt_request & CPU_INTERRUPT_HARD) && - cpu_interrupts_enabled(env); + cpu_interrupts_enabled(cpu_env(cs)); +} + +static int sparc_cpu_mmu_index(CPUState *cs, bool ifetch) +{ + CPUSPARCState *env = cpu_env(cs); + +#ifndef TARGET_SPARC64 + if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ + return MMU_PHYS_IDX; + } else { + return env->psrs; + } +#else + /* IMMU or DMMU disabled. */ + if (ifetch + ? (env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0 + : (env->lsu & DMMU_E) == 0) { + return MMU_PHYS_IDX; + } else if (cpu_hypervisor_mode(env)) { + return MMU_PHYS_IDX; + } else if (env->tl > 0) { + return MMU_NUCLEUS_IDX; + } else if (cpu_supervisor_mode(env)) { + return MMU_KERNEL_IDX; + } else { + return MMU_USER_IDX; + } +#endif } static char *sparc_cpu_type_name(const char *cpu_model) @@ -742,17 +772,14 @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp) CPUState *cs = CPU(dev); SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev); Error *local_err = NULL; - SPARCCPU *cpu = SPARC_CPU(dev); - CPUSPARCState *env = &cpu->env; + CPUSPARCState *env = cpu_env(cs); #if defined(CONFIG_USER_ONLY) - if ((env->def.features & CPU_FEATURE_FLOAT)) { - env->def.features |= CPU_FEATURE_FLOAT128; - } + /* We are emulating the kernel, which will trap and emulate float128. */ + env->def.features |= CPU_FEATURE_FLOAT128; #endif env->version = env->def.iu_version; - env->fsr = env->def.fpu_version; env->nwindows = env->def.nwindows; #if !defined(TARGET_SPARC64) env->mmuregs[0] |= env->def.mmu_version; @@ -764,6 +791,7 @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp) env->version |= env->def.maxtl << 8; env->version |= env->def.nwindows - 1; #endif + cpu_put_fsr(env, 0); cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { @@ -782,8 +810,6 @@ static void sparc_cpu_initfn(Object *obj) SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj); CPUSPARCState *env = &cpu->env; - cpu_set_cpustate_pointers(cpu); - if (scc->cpu_def) { env->def = *scc->cpu_def; } @@ -826,21 +852,29 @@ static PropertyInfo qdev_prop_nwindows = { .set = sparc_set_nwindows, }; +/* This must match feature_name[]. */ static Property sparc_cpu_properties[] = { - DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false), - DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false), - DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false), - DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false), - DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false), - DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false), - DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false), - DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false), - DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false), - DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false), - DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false), - DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false), - DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false), - DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false), + DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_FLOAT128, false), +#ifdef TARGET_SPARC64 + DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_CMT, false), + DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_GL, false), + DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_HYPV, false), + DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_VIS1, false), + DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_VIS2, false), +#else + DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_MUL, false), + DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_DIV, false), + DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, + CPU_FEATURE_BIT_FSMULD, false), +#endif DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0, qdev_prop_uint64, target_ulong), DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0), @@ -862,12 +896,13 @@ static const struct SysemuCPUOps sparc_sysemu_ops = { #ifdef CONFIG_TCG #include "hw/core/tcg-cpu-ops.h" -static const struct TCGCPUOps sparc_tcg_ops = { +static const TCGCPUOps sparc_tcg_ops = { .initialize = sparc_tcg_init, .synchronize_from_tb = sparc_cpu_synchronize_from_tb, - .tlb_fill = sparc_cpu_tlb_fill, + .restore_state_to_opc = sparc_restore_state_to_opc, #ifndef CONFIG_USER_ONLY + .tlb_fill = sparc_cpu_tlb_fill, .cpu_exec_interrupt = sparc_cpu_exec_interrupt, .do_interrupt = sparc_cpu_do_interrupt, .do_transaction_failed = sparc_cpu_do_transaction_failed, @@ -881,21 +916,25 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data) SPARCCPUClass *scc = SPARC_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc); + ResettableClass *rc = RESETTABLE_CLASS(oc); device_class_set_parent_realize(dc, sparc_cpu_realizefn, &scc->parent_realize); device_class_set_props(dc, sparc_cpu_properties); - device_class_set_parent_reset(dc, sparc_cpu_reset, &scc->parent_reset); + resettable_class_set_parent_phases(rc, NULL, sparc_cpu_reset_hold, NULL, + &scc->parent_phases); cc->class_by_name = sparc_cpu_class_by_name; cc->parse_features = sparc_cpu_parse_features; cc->has_work = sparc_cpu_has_work; + cc->mmu_index = sparc_cpu_mmu_index; cc->dump_state = sparc_cpu_dump_state; #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) cc->memory_rw_debug = sparc_cpu_memory_rw_debug; #endif cc->set_pc = sparc_cpu_set_pc; + cc->get_pc = sparc_cpu_get_pc; cc->gdb_read_register = sparc_cpu_gdb_read_register; cc->gdb_write_register = sparc_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY @@ -915,6 +954,7 @@ static const TypeInfo sparc_cpu_type_info = { .name = TYPE_SPARC_CPU, .parent = TYPE_CPU, .instance_size = sizeof(SPARCCPU), + .instance_align = __alignof(SPARCCPU), .instance_init = sparc_cpu_initfn, .abstract = true, .class_size = sizeof(SPARCCPUClass), |