8f4efc5588
sparc64 timer has tick counter which can be set and read, and tick compare value used as deadline to fire timer interrupt. The timer is not used as periodic timer, instead deadline is set each time new timer interrupt is needed. v3 -> v4: - coding style v2 -> v3: - added missing timer debug output macro - CPUTimer struct and typedef moved to cpu.h - change CPU_SAVE_VERSION to 6, older save formats not supported v1 -> v2: - new conversion helpers cpu_to_timer_ticks and timer_to_cpu_ticks - save offset from clock source to implement cpu_tick_set_count - renamed struct sun4u_timer to CPUTimer - load and save cpu timers v0 -> v1: - coding style Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
200 lines
6.0 KiB
C
200 lines
6.0 KiB
C
#include "hw/hw.h"
|
|
#include "hw/boards.h"
|
|
#include "qemu-timer.h"
|
|
|
|
#include "exec-all.h"
|
|
|
|
void cpu_save(QEMUFile *f, void *opaque)
|
|
{
|
|
CPUState *env = opaque;
|
|
int i;
|
|
uint32_t tmp;
|
|
|
|
// if env->cwp == env->nwindows - 1, this will set the ins of the last
|
|
// window as the outs of the first window
|
|
cpu_set_cwp(env, env->cwp);
|
|
|
|
for(i = 0; i < 8; i++)
|
|
qemu_put_betls(f, &env->gregs[i]);
|
|
qemu_put_be32s(f, &env->nwindows);
|
|
for(i = 0; i < env->nwindows * 16; i++)
|
|
qemu_put_betls(f, &env->regbase[i]);
|
|
|
|
/* FPU */
|
|
for(i = 0; i < TARGET_FPREGS; i++) {
|
|
union {
|
|
float32 f;
|
|
uint32_t i;
|
|
} u;
|
|
u.f = env->fpr[i];
|
|
qemu_put_be32(f, u.i);
|
|
}
|
|
|
|
qemu_put_betls(f, &env->pc);
|
|
qemu_put_betls(f, &env->npc);
|
|
qemu_put_betls(f, &env->y);
|
|
tmp = GET_PSR(env);
|
|
qemu_put_be32(f, tmp);
|
|
qemu_put_betls(f, &env->fsr);
|
|
qemu_put_betls(f, &env->tbr);
|
|
tmp = env->interrupt_index;
|
|
qemu_put_be32(f, tmp);
|
|
qemu_put_be32s(f, &env->pil_in);
|
|
#ifndef TARGET_SPARC64
|
|
qemu_put_be32s(f, &env->wim);
|
|
/* MMU */
|
|
for (i = 0; i < 32; i++)
|
|
qemu_put_be32s(f, &env->mmuregs[i]);
|
|
#else
|
|
qemu_put_be64s(f, &env->lsu);
|
|
for (i = 0; i < 16; i++) {
|
|
qemu_put_be64s(f, &env->immuregs[i]);
|
|
qemu_put_be64s(f, &env->dmmuregs[i]);
|
|
}
|
|
for (i = 0; i < 64; i++) {
|
|
qemu_put_be64s(f, &env->itlb[i].tag);
|
|
qemu_put_be64s(f, &env->itlb[i].tte);
|
|
qemu_put_be64s(f, &env->dtlb[i].tag);
|
|
qemu_put_be64s(f, &env->dtlb[i].tte);
|
|
}
|
|
qemu_put_be32s(f, &env->mmu_version);
|
|
for (i = 0; i < MAXTL_MAX; i++) {
|
|
qemu_put_be64s(f, &env->ts[i].tpc);
|
|
qemu_put_be64s(f, &env->ts[i].tnpc);
|
|
qemu_put_be64s(f, &env->ts[i].tstate);
|
|
qemu_put_be32s(f, &env->ts[i].tt);
|
|
}
|
|
qemu_put_be32s(f, &env->xcc);
|
|
qemu_put_be32s(f, &env->asi);
|
|
qemu_put_be32s(f, &env->pstate);
|
|
qemu_put_be32s(f, &env->tl);
|
|
qemu_put_be32s(f, &env->cansave);
|
|
qemu_put_be32s(f, &env->canrestore);
|
|
qemu_put_be32s(f, &env->otherwin);
|
|
qemu_put_be32s(f, &env->wstate);
|
|
qemu_put_be32s(f, &env->cleanwin);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_put_be64s(f, &env->agregs[i]);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_put_be64s(f, &env->bgregs[i]);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_put_be64s(f, &env->igregs[i]);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_put_be64s(f, &env->mgregs[i]);
|
|
qemu_put_be64s(f, &env->fprs);
|
|
qemu_put_be64s(f, &env->tick_cmpr);
|
|
qemu_put_be64s(f, &env->stick_cmpr);
|
|
cpu_put_timer(f, env->tick);
|
|
cpu_put_timer(f, env->stick);
|
|
qemu_put_be64s(f, &env->gsr);
|
|
qemu_put_be32s(f, &env->gl);
|
|
qemu_put_be64s(f, &env->hpstate);
|
|
for (i = 0; i < MAXTL_MAX; i++)
|
|
qemu_put_be64s(f, &env->htstate[i]);
|
|
qemu_put_be64s(f, &env->hintp);
|
|
qemu_put_be64s(f, &env->htba);
|
|
qemu_put_be64s(f, &env->hver);
|
|
qemu_put_be64s(f, &env->hstick_cmpr);
|
|
qemu_put_be64s(f, &env->ssr);
|
|
cpu_put_timer(f, env->hstick);
|
|
#endif
|
|
}
|
|
|
|
int cpu_load(QEMUFile *f, void *opaque, int version_id)
|
|
{
|
|
CPUState *env = opaque;
|
|
int i;
|
|
uint32_t tmp;
|
|
|
|
if (version_id < 6)
|
|
return -EINVAL;
|
|
for(i = 0; i < 8; i++)
|
|
qemu_get_betls(f, &env->gregs[i]);
|
|
qemu_get_be32s(f, &env->nwindows);
|
|
for(i = 0; i < env->nwindows * 16; i++)
|
|
qemu_get_betls(f, &env->regbase[i]);
|
|
|
|
/* FPU */
|
|
for(i = 0; i < TARGET_FPREGS; i++) {
|
|
union {
|
|
float32 f;
|
|
uint32_t i;
|
|
} u;
|
|
u.i = qemu_get_be32(f);
|
|
env->fpr[i] = u.f;
|
|
}
|
|
|
|
qemu_get_betls(f, &env->pc);
|
|
qemu_get_betls(f, &env->npc);
|
|
qemu_get_betls(f, &env->y);
|
|
tmp = qemu_get_be32(f);
|
|
env->cwp = 0; /* needed to ensure that the wrapping registers are
|
|
correctly updated */
|
|
PUT_PSR(env, tmp);
|
|
qemu_get_betls(f, &env->fsr);
|
|
qemu_get_betls(f, &env->tbr);
|
|
tmp = qemu_get_be32(f);
|
|
env->interrupt_index = tmp;
|
|
qemu_get_be32s(f, &env->pil_in);
|
|
#ifndef TARGET_SPARC64
|
|
qemu_get_be32s(f, &env->wim);
|
|
/* MMU */
|
|
for (i = 0; i < 32; i++)
|
|
qemu_get_be32s(f, &env->mmuregs[i]);
|
|
#else
|
|
qemu_get_be64s(f, &env->lsu);
|
|
for (i = 0; i < 16; i++) {
|
|
qemu_get_be64s(f, &env->immuregs[i]);
|
|
qemu_get_be64s(f, &env->dmmuregs[i]);
|
|
}
|
|
for (i = 0; i < 64; i++) {
|
|
qemu_get_be64s(f, &env->itlb[i].tag);
|
|
qemu_get_be64s(f, &env->itlb[i].tte);
|
|
qemu_get_be64s(f, &env->dtlb[i].tag);
|
|
qemu_get_be64s(f, &env->dtlb[i].tte);
|
|
}
|
|
qemu_get_be32s(f, &env->mmu_version);
|
|
for (i = 0; i < MAXTL_MAX; i++) {
|
|
qemu_get_be64s(f, &env->ts[i].tpc);
|
|
qemu_get_be64s(f, &env->ts[i].tnpc);
|
|
qemu_get_be64s(f, &env->ts[i].tstate);
|
|
qemu_get_be32s(f, &env->ts[i].tt);
|
|
}
|
|
qemu_get_be32s(f, &env->xcc);
|
|
qemu_get_be32s(f, &env->asi);
|
|
qemu_get_be32s(f, &env->pstate);
|
|
qemu_get_be32s(f, &env->tl);
|
|
qemu_get_be32s(f, &env->cansave);
|
|
qemu_get_be32s(f, &env->canrestore);
|
|
qemu_get_be32s(f, &env->otherwin);
|
|
qemu_get_be32s(f, &env->wstate);
|
|
qemu_get_be32s(f, &env->cleanwin);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_get_be64s(f, &env->agregs[i]);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_get_be64s(f, &env->bgregs[i]);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_get_be64s(f, &env->igregs[i]);
|
|
for (i = 0; i < 8; i++)
|
|
qemu_get_be64s(f, &env->mgregs[i]);
|
|
qemu_get_be64s(f, &env->fprs);
|
|
qemu_get_be64s(f, &env->tick_cmpr);
|
|
qemu_get_be64s(f, &env->stick_cmpr);
|
|
cpu_get_timer(f, env->tick);
|
|
cpu_get_timer(f, env->stick);
|
|
qemu_get_be64s(f, &env->gsr);
|
|
qemu_get_be32s(f, &env->gl);
|
|
qemu_get_be64s(f, &env->hpstate);
|
|
for (i = 0; i < MAXTL_MAX; i++)
|
|
qemu_get_be64s(f, &env->htstate[i]);
|
|
qemu_get_be64s(f, &env->hintp);
|
|
qemu_get_be64s(f, &env->htba);
|
|
qemu_get_be64s(f, &env->hver);
|
|
qemu_get_be64s(f, &env->hstick_cmpr);
|
|
qemu_get_be64s(f, &env->ssr);
|
|
cpu_get_timer(f, env->hstick);
|
|
#endif
|
|
tlb_flush(env, 1);
|
|
return 0;
|
|
}
|