Commit 1a14026e authored by Blue Swirl's avatar Blue Swirl
Browse files

Allow NWINDOWS selection (CPU feature with model specific defaults)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4690 c046a42c-6fe2-441c-8c8c-71466251a162
parent 96d19126
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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;
    }
+1 −1
Original line number Diff line number Diff line
@@ -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);

+14 −14
Original line number Diff line number Diff line
@@ -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,7 +690,7 @@ static void restore_window(CPUSPARCState *env)
    env->wim = new_wim;
#ifdef TARGET_SPARC64
    env->canrestore++;
    if (env->cleanwin < NWINDOWS - 1)
    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);
+0 −1
Original line number Diff line number Diff line
@@ -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
+27 −6
Original line number Diff line number Diff line
@@ -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

Loading