diff --git a/hw/sun4m.c b/hw/sun4m.c index 734b576aae..09c26270d3 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -404,7 +404,7 @@ static void sun4m_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size, qemu_register_reset(secondary_cpu_reset, env); env->halted = 1; } - register_savevm("cpu", i, 3, cpu_save, cpu_load, env); + register_savevm("cpu", i, 4, cpu_save, cpu_load, env); cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS); env->prom_addr = hwdef->slavio_base; } @@ -579,7 +579,7 @@ static void sun4c_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size, cpu_sparc_set_id(env, 0); qemu_register_reset(main_cpu_reset, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); + register_savevm("cpu", 0, 4, cpu_save, cpu_load, env); cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); env->prom_addr = hwdef->slavio_base; @@ -1391,7 +1391,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, qemu_register_reset(secondary_cpu_reset, env); env->halted = 1; } - register_savevm("cpu", i, 3, cpu_save, cpu_load, env); + register_savevm("cpu", i, 4, cpu_save, cpu_load, env); cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS); env->prom_addr = hwdef->slavio_base; } diff --git a/hw/sun4u.c b/hw/sun4u.c index 0cc04f97de..6e1dee9563 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -260,7 +260,7 @@ static void sun4u_init(ram_addr_t RAM_size, int vga_ram_size, bh = qemu_bh_new(hstick_irq, env); env->hstick = ptimer_init(bh); ptimer_set_period(env->hstick, 1ULL); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); + register_savevm("cpu", 0, 4, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); main_cpu_reset(env); diff --git a/linux-user/main.c b/linux-user/main.c index 21c2d3ba08..4bdec7e9bc 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -626,11 +626,11 @@ void cpu_loop(CPUARMState *env) can be found at http://www.sics.se/~psm/sparcstack.html */ static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) { - index = (index + cwp * 16) & (16 * NWINDOWS - 1); + index = (index + cwp * 16) % (16 * env->nwindows); /* wrap handling : if cwp is on the last window, then we use the registers 'after' the end */ - if (index < 8 && env->cwp == (NWINDOWS - 1)) - index += (16 * NWINDOWS); + if (index < 8 && env->cwp == env->nwindows - 1) + index += 16 * env->nwindows; return index; } @@ -656,12 +656,12 @@ static void save_window(CPUSPARCState *env) { #ifndef TARGET_SPARC64 unsigned int new_wim; - new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) & - ((1LL << NWINDOWS) - 1); - save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1)); + new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & + ((1LL << env->nwindows) - 1); + save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); env->wim = new_wim; #else - save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1)); + save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); env->cansave++; env->canrestore--; #endif @@ -672,11 +672,11 @@ static void restore_window(CPUSPARCState *env) unsigned int new_wim, i, cwp1; abi_ulong sp_ptr; - new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) & - ((1LL << NWINDOWS) - 1); + new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & + ((1LL << env->nwindows) - 1); /* restore the invalid window */ - cwp1 = (env->cwp + 1) & (NWINDOWS - 1); + cwp1 = cpu_cwp_inc(env, env->cwp + 1); sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; #if defined(DEBUG_WIN) printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n", @@ -690,8 +690,8 @@ static void restore_window(CPUSPARCState *env) env->wim = new_wim; #ifdef TARGET_SPARC64 env->canrestore++; - if (env->cleanwin < NWINDOWS - 1) - env->cleanwin++; + if (env->cleanwin < env->nwindows - 1) + env->cleanwin++; env->cansave--; #endif } @@ -703,14 +703,14 @@ static void flush_windows(CPUSPARCState *env) offset = 1; for(;;) { /* if restore would invoke restore_window(), then we can stop */ - cwp1 = (env->cwp + offset) & (NWINDOWS - 1); + cwp1 = cpu_cwp_inc(env, env->cwp + offset); if (env->wim & (1 << cwp1)) break; save_window_offset(env, cwp1); offset++; } /* set wim so that restore will reload the registers */ - cwp1 = (env->cwp + 1) & (NWINDOWS - 1); + cwp1 = cpu_cwp_inc(env, env->cwp + 1); env->wim = 1 << cwp1; #if defined(DEBUG_WIN) printf("flush_windows: nb=%d\n", offset - 1); diff --git a/target-sparc/TODO b/target-sparc/TODO index 5a4937ba0d..0e998e276c 100644 --- a/target-sparc/TODO +++ b/target-sparc/TODO @@ -6,7 +6,6 @@ CPU common: slot next page) - Atomical instructions - CPU features should match real CPUs (also ASI selection) - - Allow choosing of NWINDOWS (CPU model specific and as a CPU feature) - Optimizations/improvements: - Condition code/branch handling like x86, also for FPU? - Remove remaining explicit alignment checks diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index ad9aeb8671..f30a606c96 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -170,8 +170,9 @@ #define PG_MODIFIED_MASK (1 << PG_MODIFIED_BIT) #define PG_CACHE_MASK (1 << PG_CACHE_BIT) -/* 2 <= NWINDOWS <= 32. In QEMU it must also be a power of two. */ -#define NWINDOWS 8 +/* 3 <= NWINDOWS <= 32. */ +#define MIN_NWINDOWS 3 +#define MAX_NWINDOWS 32 #if !defined(TARGET_SPARC64) #define NB_MMU_MODES 2 @@ -222,8 +223,9 @@ typedef struct CPUSPARCState { uint32_t mmu_cxr_mask; uint32_t mmu_sfsr_mask; uint32_t mmu_trcr_mask; + uint32_t nwindows; /* NOTE: we allow 8 more registers to handle wrapping */ - target_ulong regbase[NWINDOWS * 16 + 8]; + target_ulong regbase[MAX_NWINDOWS * 16 + 8]; CPU_COMMON @@ -330,6 +332,20 @@ void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu); #ifndef NO_CPU_IO_DEFS void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); + +static inline int cpu_cwp_inc(CPUSPARCState *env1, int cwp) +{ + if (unlikely(cwp >= env1->nwindows)) + cwp -= env1->nwindows; + return cwp; +} + +static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) +{ + if (unlikely(cwp < 0)) + cwp += env1->nwindows; + return cwp; +} #endif #define PUT_PSR(env, val) do { int _tmp = val; \ @@ -348,9 +364,14 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); env->xcc = (_tmp >> 4) << 20; \ env->psr = (_tmp & 0xf) << 20; \ } while (0) -#define GET_CWP64(env) (NWINDOWS - 1 - (env)->cwp) -#define PUT_CWP64(env, val) \ - cpu_set_cwp(env, NWINDOWS - 1 - ((val) & (NWINDOWS - 1))) +#define GET_CWP64(env) (env->nwindows - 1 - (env)->cwp) + +static inline void PUT_CWP64(CPUSPARCState *env1, int cwp) +{ + if (unlikely(cwp >= env1->nwindows || cwp < 0)) + cwp = 0; + cpu_set_cwp(env1, env1->nwindows - 1 - cwp); +} #endif diff --git a/target-sparc/helper.c b/target-sparc/helper.c index bf74c0d293..7b87d592c4 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -47,6 +47,7 @@ struct sparc_def_t { uint32_t mmu_sfsr_mask; uint32_t mmu_trcr_mask; uint32_t features; + uint32_t nwindows; }; static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model); @@ -750,11 +751,11 @@ void do_interrupt(CPUState *env) change_pstate(PS_PEF | PS_PRIV | PS_AG); if (intno == TT_CLRWIN) - cpu_set_cwp(env, (env->cwp - 1) & (NWINDOWS - 1)); + cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); else if ((intno & 0x1c0) == TT_SPILL) - cpu_set_cwp(env, (env->cwp - env->cansave - 2) & (NWINDOWS - 1)); + cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); else if ((intno & 0x1c0) == TT_FILL) - cpu_set_cwp(env, (env->cwp + 1) & (NWINDOWS - 1)); + cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1)); env->tbr &= ~0x7fffULL; env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); if (env->tl < MAXTL - 1) { @@ -853,7 +854,7 @@ void do_interrupt(CPUState *env) } #endif env->psret = 0; - cwp = (env->cwp - 1) & (NWINDOWS - 1); + cwp = cpu_cwp_dec(env, env->cwp - 1); cpu_set_cwp(env, cwp); env->regwptr[9] = env->pc; env->regwptr[10] = env->npc; @@ -887,8 +888,8 @@ void cpu_reset(CPUSPARCState *env) #if defined(CONFIG_USER_ONLY) env->user_mode_only = 1; #ifdef TARGET_SPARC64 - env->cleanwin = NWINDOWS - 2; - env->cansave = NWINDOWS - 2; + 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 @@ -921,6 +922,7 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model) env->cpu_model_str = cpu_model; env->version = def->iu_version; env->fsr = def->fpu_version; + env->nwindows = def->nwindows; #if !defined(TARGET_SPARC64) env->mmu_bm = def->mmu_bm; env->mmu_ctpr_mask = def->mmu_ctpr_mask; @@ -929,6 +931,8 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model) env->mmu_trcr_mask = def->mmu_trcr_mask; env->mmuregs[0] |= def->mmu_version; cpu_sparc_set_id(env, 0); +#else + env->version |= def->nwindows - 1; #endif return 0; } @@ -970,121 +974,136 @@ static const sparc_def_t sparc_defs[] = { { .name = "Fujitsu Sparc64", .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 4, .features = CPU_DEFAULT_FEATURES, }, { .name = "Fujitsu Sparc64 III", .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 5, .features = CPU_DEFAULT_FEATURES, }, { .name = "Fujitsu Sparc64 IV", .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "Fujitsu Sparc64 V", .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc I", .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc II", .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc IIi", .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "TI UltraSparc IIe", .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc III", .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc III Cu", .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IIIi", .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IV", .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IV+", .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "Sun UltraSparc IIIi+", .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { .name = "NEC UltraSparc I", .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24) - | (MAXTL << 8) | (NWINDOWS - 1)), + | (MAXTL << 8)), .fpu_version = 0x00000000, .mmu_version = 0, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, #else @@ -1098,6 +1117,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 7, .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD, }, { @@ -1110,6 +1130,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0x00ffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1122,6 +1143,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1134,6 +1156,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | CPU_FEATURE_FSMULD, }, @@ -1147,6 +1170,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | CPU_FEATURE_FSMULD, }, @@ -1160,6 +1184,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | CPU_FEATURE_FSMULD, }, @@ -1173,6 +1198,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1185,6 +1211,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .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, @@ -1199,6 +1226,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0x00ffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1211,6 +1239,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x000000ff, .mmu_sfsr_mask = 0x00016bff, .mmu_trcr_mask = 0x00ffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1223,6 +1252,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1235,6 +1265,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1247,6 +1278,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1259,6 +1291,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1271,6 +1304,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000ffff, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1283,6 +1317,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1295,6 +1330,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1307,6 +1343,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | CPU_FEATURE_FSMULD, }, @@ -1320,6 +1357,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT | CPU_FEATURE_FSMULD, }, @@ -1333,6 +1371,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1345,6 +1384,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, { @@ -1357,6 +1397,7 @@ static const sparc_def_t sparc_defs[] = { .mmu_cxr_mask = 0x0000003f, .mmu_sfsr_mask = 0xffffffff, .mmu_trcr_mask = 0xffffffff, + .nwindows = 8, .features = CPU_DEFAULT_FEATURES, }, #endif @@ -1411,7 +1452,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model) uint32_t plus_features = 0; uint32_t minus_features = 0; long long iu_version; - uint32_t fpu_version, mmu_version; + uint32_t fpu_version, mmu_version, nwindows; for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) { if (strcasecmp(name, sparc_defs[i].name) == 0) { @@ -1467,6 +1508,19 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model) cpu_def->mmu_version = mmu_version; #ifdef DEBUG_FEATURES fprintf(stderr, "mmu_version %llx\n", mmu_version); +#endif + } else if (!strcmp(featurestr, "nwindows")) { + char *err; + + nwindows = strtol(val, &err, 0); + if (!*val || *err || nwindows > MAX_NWINDOWS || + nwindows < MIN_NWINDOWS) { + fprintf(stderr, "bad numerical value %s\n", val); + goto error; + } + cpu_def->nwindows = nwindows; +#ifdef DEBUG_FEATURES + fprintf(stderr, "nwindows %d\n", nwindows); #endif } else { fprintf(stderr, "unrecognized feature %s\n", featurestr); @@ -1497,11 +1551,12 @@ void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) unsigned int i; for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) { - (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x ", + (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ", sparc_defs[i].name, sparc_defs[i].iu_version, sparc_defs[i].fpu_version, - sparc_defs[i].mmu_version); + sparc_defs[i].mmu_version, + sparc_defs[i].nwindows); print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-"); print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES & @@ -1512,7 +1567,7 @@ void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) print_features(f, cpu_fprintf, -1, NULL); (*cpu_fprintf)(f, "\n"); (*cpu_fprintf)(f, "Numerical features (=): iu_version fpu_version " - "mmu_version\n"); + "mmu_version nwindows\n"); } #define GET_FLAG(a,b) ((env->psr & a)?b:'-') @@ -1558,7 +1613,7 @@ void cpu_dump_state(CPUState *env, FILE *f, cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d " "cleanwin %d cwp %d\n", env->cansave, env->canrestore, env->otherwin, env->wstate, - env->cleanwin, NWINDOWS - 1 - env->cwp); + env->cleanwin, env->nwindows - 1 - env->cwp); #else cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'), diff --git a/target-sparc/machine.c b/target-sparc/machine.c index 0e7a23e9f8..aaac30b1e8 100644 --- a/target-sparc/machine.c +++ b/target-sparc/machine.c @@ -31,7 +31,8 @@ void cpu_save(QEMUFile *f, void *opaque) for(i = 0; i < 8; i++) qemu_put_betls(f, &env->gregs[i]); - for(i = 0; i < NWINDOWS * 16; i++) + qemu_put_be32s(f, &env->nwindows); + for(i = 0; i < env->nwindows * 16; i++) qemu_put_betls(f, &env->regbase[i]); /* FPU */ @@ -65,9 +66,12 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) int i; uint32_t tmp; + if (version_id != 4) + return -EINVAL; for(i = 0; i < 8; i++) qemu_get_betls(f, &env->gregs[i]); - for(i = 0; i < NWINDOWS * 16; i++) + qemu_get_be32s(f, &env->nwindows); + for(i = 0; i < env->nwindows * 16; i++) qemu_get_betls(f, &env->regbase[i]); /* FPU */ diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 3c04fe54f9..7b28f72b81 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -2178,7 +2178,7 @@ void helper_rett(void) raise_exception(TT_ILL_INSN); env->psret = 1; - cwp = (env->cwp + 1) & (NWINDOWS - 1); + cwp = cpu_cwp_inc(env, env->cwp + 1) ; if (env->wim & (1 << cwp)) { raise_exception(TT_WIN_UNF); } @@ -2399,7 +2399,7 @@ void helper_save(void) { uint32_t cwp; - cwp = (env->cwp - 1) & (NWINDOWS - 1); + cwp = cpu_cwp_dec(env, env->cwp - 1); if (env->wim & (1 << cwp)) { raise_exception(TT_WIN_OVF); } @@ -2410,7 +2410,7 @@ void helper_restore(void) { uint32_t cwp; - cwp = (env->cwp + 1) & (NWINDOWS - 1); + cwp = cpu_cwp_inc(env, env->cwp + 1); if (env->wim & (1 << cwp)) { raise_exception(TT_WIN_UNF); } @@ -2419,7 +2419,7 @@ void helper_restore(void) void helper_wrpsr(target_ulong new_psr) { - if ((new_psr & PSR_CWP) >= NWINDOWS) + if ((new_psr & PSR_CWP) >= env->nwindows) raise_exception(TT_ILL_INSN); else PUT_PSR(env, new_psr); @@ -2437,7 +2437,7 @@ void helper_save(void) { uint32_t cwp; - cwp = (env->cwp - 1) & (NWINDOWS - 1); + cwp = cpu_cwp_dec(env, env->cwp - 1); if (env->cansave == 0) { raise_exception(TT_SPILL | (env->otherwin != 0 ? (TT_WOTHER | ((env->wstate & 0x38) >> 1)): @@ -2458,7 +2458,7 @@ void helper_restore(void) { uint32_t cwp; - cwp = (env->cwp + 1) & (NWINDOWS - 1); + cwp = cpu_cwp_inc(env, env->cwp + 1); if (env->canrestore == 0) { raise_exception(TT_FILL | (env->otherwin != 0 ? (TT_WOTHER | ((env->wstate & 0x38) >> 1)): @@ -2472,7 +2472,7 @@ void helper_restore(void) void helper_flushw(void) { - if (env->cansave != NWINDOWS - 2) { + if (env->cansave != env->nwindows - 2) { raise_exception(TT_SPILL | (env->otherwin != 0 ? (TT_WOTHER | ((env->wstate & 0x38) >> 1)): ((env->wstate & 0x7) << 2))); @@ -2491,7 +2491,7 @@ void helper_saved(void) void helper_restored(void) { env->canrestore++; - if (env->cleanwin < NWINDOWS - 1) + if (env->cleanwin < env->nwindows - 1) env->cleanwin++; if (env->otherwin == 0) env->cansave--; @@ -2622,12 +2622,12 @@ void helper_retry(void) void cpu_set_cwp(CPUState *env1, int new_cwp) { /* put the modified wrap registers at their proper location */ - if (env1->cwp == (NWINDOWS - 1)) - memcpy32(env1->regbase, env1->regbase + NWINDOWS * 16); + if (env1->cwp == env->nwindows - 1) + memcpy32(env1->regbase, env1->regbase + env->nwindows * 16); env1->cwp = new_cwp; /* put the wrap registers at their temporary location */ - if (new_cwp == (NWINDOWS - 1)) - memcpy32(env1->regbase + NWINDOWS * 16, env1->regbase); + if (new_cwp == env->nwindows - 1) + memcpy32(env1->regbase + env->nwindows * 16, env1->regbase); env1->regwptr = env1->regbase + (new_cwp * 16); } diff --git a/target-sparc/translate.c b/target-sparc/translate.c index eb0ab3343f..999378a6d0 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3442,8 +3442,6 @@ static void disas_sparc_insn(DisasContext * dc) goto illegal_insn; } #else - tcg_gen_andi_tl(cpu_dst, cpu_dst, - ((1 << NWINDOWS) - 1)); tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst); tcg_gen_st_i32(cpu_tmp32, cpu_env, offsetof(CPUSPARCState, wim));