diff --git a/target-mips/machine.c b/target-mips/machine.c index 15ce73cd4b..543778dc5d 100644 --- a/target-mips/machine.c +++ b/target-mips/machine.c @@ -1,6 +1,8 @@ #include "hw/hw.h" #include "hw/boards.h" +#include "exec-all.h" + void register_machines(void) { qemu_register_machine(&mips_malta_machine); @@ -10,11 +12,300 @@ void register_machines(void) qemu_register_machine(&mips_machine); } +static void save_tc(QEMUFile *f, TCState *tc) +{ + int i; + + /* Save active TC */ + for(i = 0; i < 32; i++) + qemu_put_betls(f, &tc->gpr[i]); + qemu_put_betls(f, &tc->PC); + for(i = 0; i < MIPS_DSP_ACC; i++) + qemu_put_betls(f, &tc->HI[i]); + for(i = 0; i < MIPS_DSP_ACC; i++) + qemu_put_betls(f, &tc->LO[i]); + for(i = 0; i < MIPS_DSP_ACC; i++) + qemu_put_betls(f, &tc->ACX[i]); + qemu_put_betls(f, &tc->DSPControl); + qemu_put_sbe32s(f, &tc->CP0_TCStatus); + qemu_put_sbe32s(f, &tc->CP0_TCBind); + qemu_put_betls(f, &tc->CP0_TCHalt); + qemu_put_betls(f, &tc->CP0_TCContext); + qemu_put_betls(f, &tc->CP0_TCSchedule); + qemu_put_betls(f, &tc->CP0_TCScheFBack); + qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus); +} + +static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu) +{ + int i; + + for(i = 0; i < 32; i++) + qemu_put_be64s(f, &fpu->fpr[i].d); + qemu_put_s8s(f, &fpu->fp_status.float_detect_tininess); + qemu_put_s8s(f, &fpu->fp_status.float_rounding_mode); + qemu_put_s8s(f, &fpu->fp_status.float_exception_flags); + qemu_put_be32s(f, &fpu->fcr0); + qemu_put_be32s(f, &fpu->fcr31); +} + void cpu_save(QEMUFile *f, void *opaque) { + CPUState *env = opaque; + int i; + + /* Save active TC */ + save_tc(f, &env->active_tc); + + /* Save active FPU */ + save_fpu(f, &env->active_fpu); + + /* Save MVP */ + qemu_put_sbe32s(f, &env->mvp->CP0_MVPControl); + qemu_put_sbe32s(f, &env->mvp->CP0_MVPConf0); + qemu_put_sbe32s(f, &env->mvp->CP0_MVPConf1); + + /* Save TLB */ + qemu_put_be32s(f, &env->tlb->nb_tlb); + qemu_put_be32s(f, &env->tlb->tlb_in_use); + for(i = 0; i < MIPS_TLB_MAX; i++) { + uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].G << 10) | + (env->tlb->mmu.r4k.tlb[i].C0 << 7) | + (env->tlb->mmu.r4k.tlb[i].C1 << 4) | + (env->tlb->mmu.r4k.tlb[i].V0 << 3) | + (env->tlb->mmu.r4k.tlb[i].V1 << 2) | + (env->tlb->mmu.r4k.tlb[i].D0 << 1) | + (env->tlb->mmu.r4k.tlb[i].D1 << 0)); + + qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].VPN); + qemu_put_be32s(f, &env->tlb->mmu.r4k.tlb[i].PageMask); + qemu_put_8s(f, &env->tlb->mmu.r4k.tlb[i].ASID); + qemu_put_be16s(f, &flags); + qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]); + qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]); + } + + /* Save CPU metastate */ + qemu_put_be32s(f, &env->current_tc); + qemu_put_be32s(f, &env->current_fpu); + qemu_put_sbe32s(f, &env->error_code); + qemu_put_be32s(f, &env->hflags); + qemu_put_betls(f, &env->btarget); + qemu_put_sbe32s(f, &env->bcond); + + /* Save remaining CP1 registers */ + qemu_put_sbe32s(f, &env->CP0_Index); + qemu_put_sbe32s(f, &env->CP0_Random); + qemu_put_sbe32s(f, &env->CP0_VPEControl); + qemu_put_sbe32s(f, &env->CP0_VPEConf0); + qemu_put_sbe32s(f, &env->CP0_VPEConf1); + qemu_put_betls(f, &env->CP0_YQMask); + qemu_put_betls(f, &env->CP0_VPESchedule); + qemu_put_betls(f, &env->CP0_VPEScheFBack); + qemu_put_sbe32s(f, &env->CP0_VPEOpt); + qemu_put_betls(f, &env->CP0_EntryLo0); + qemu_put_betls(f, &env->CP0_EntryLo1); + qemu_put_betls(f, &env->CP0_Context); + qemu_put_sbe32s(f, &env->CP0_PageMask); + qemu_put_sbe32s(f, &env->CP0_PageGrain); + qemu_put_sbe32s(f, &env->CP0_Wired); + qemu_put_sbe32s(f, &env->CP0_SRSConf0); + qemu_put_sbe32s(f, &env->CP0_SRSConf1); + qemu_put_sbe32s(f, &env->CP0_SRSConf2); + qemu_put_sbe32s(f, &env->CP0_SRSConf3); + qemu_put_sbe32s(f, &env->CP0_SRSConf4); + qemu_put_sbe32s(f, &env->CP0_HWREna); + qemu_put_betls(f, &env->CP0_BadVAddr); + qemu_put_sbe32s(f, &env->CP0_Count); + qemu_put_betls(f, &env->CP0_EntryHi); + qemu_put_sbe32s(f, &env->CP0_Compare); + qemu_put_sbe32s(f, &env->CP0_Status); + qemu_put_sbe32s(f, &env->CP0_IntCtl); + qemu_put_sbe32s(f, &env->CP0_SRSCtl); + qemu_put_sbe32s(f, &env->CP0_SRSMap); + qemu_put_sbe32s(f, &env->CP0_Cause); + qemu_put_betls(f, &env->CP0_EPC); + qemu_put_sbe32s(f, &env->CP0_PRid); + qemu_put_sbe32s(f, &env->CP0_EBase); + qemu_put_sbe32s(f, &env->CP0_Config0); + qemu_put_sbe32s(f, &env->CP0_Config1); + qemu_put_sbe32s(f, &env->CP0_Config2); + qemu_put_sbe32s(f, &env->CP0_Config3); + qemu_put_sbe32s(f, &env->CP0_Config6); + qemu_put_sbe32s(f, &env->CP0_Config7); + qemu_put_betls(f, &env->CP0_LLAddr); + for(i = 0; i < 8; i++) + qemu_put_betls(f, &env->CP0_WatchLo[i]); + for(i = 0; i < 8; i++) + qemu_put_sbe32s(f, &env->CP0_WatchHi[i]); + qemu_put_betls(f, &env->CP0_XContext); + qemu_put_sbe32s(f, &env->CP0_Framemask); + qemu_put_sbe32s(f, &env->CP0_Debug); + qemu_put_betls(f, &env->CP0_DEPC); + qemu_put_sbe32s(f, &env->CP0_Performance0); + qemu_put_sbe32s(f, &env->CP0_TagLo); + qemu_put_sbe32s(f, &env->CP0_DataLo); + qemu_put_sbe32s(f, &env->CP0_TagHi); + qemu_put_sbe32s(f, &env->CP0_DataHi); + qemu_put_betls(f, &env->CP0_ErrorEPC); + qemu_put_sbe32s(f, &env->CP0_DESAVE); + + /* Save inactive TC state */ + for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) + save_tc(f, &env->tcs[i]); + for (i = 0; i < MIPS_FPU_MAX; i++) + save_fpu(f, &env->fpus[i]); +} + +static void load_tc(QEMUFile *f, TCState *tc) +{ + int i; + + /* Save active TC */ + for(i = 0; i < 32; i++) + qemu_get_betls(f, &tc->gpr[i]); + qemu_get_betls(f, &tc->PC); + for(i = 0; i < MIPS_DSP_ACC; i++) + qemu_get_betls(f, &tc->HI[i]); + for(i = 0; i < MIPS_DSP_ACC; i++) + qemu_get_betls(f, &tc->LO[i]); + for(i = 0; i < MIPS_DSP_ACC; i++) + qemu_get_betls(f, &tc->ACX[i]); + qemu_get_betls(f, &tc->DSPControl); + qemu_get_sbe32s(f, &tc->CP0_TCStatus); + qemu_get_sbe32s(f, &tc->CP0_TCBind); + qemu_get_betls(f, &tc->CP0_TCHalt); + qemu_get_betls(f, &tc->CP0_TCContext); + qemu_get_betls(f, &tc->CP0_TCSchedule); + qemu_get_betls(f, &tc->CP0_TCScheFBack); + qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus); +} + +static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu) +{ + int i; + + for(i = 0; i < 32; i++) + qemu_get_be64s(f, &fpu->fpr[i].d); + qemu_get_s8s(f, &fpu->fp_status.float_detect_tininess); + qemu_get_s8s(f, &fpu->fp_status.float_rounding_mode); + qemu_get_s8s(f, &fpu->fp_status.float_exception_flags); + qemu_get_be32s(f, &fpu->fcr0); + qemu_get_be32s(f, &fpu->fcr31); } int cpu_load(QEMUFile *f, void *opaque, int version_id) { + CPUState *env = opaque; + int i; + + if (version_id != 3) + return -EINVAL; + + /* Load active TC */ + load_tc(f, &env->active_tc); + + /* Load active FPU */ + load_fpu(f, &env->active_fpu); + + /* Load MVP */ + qemu_get_sbe32s(f, &env->mvp->CP0_MVPControl); + qemu_get_sbe32s(f, &env->mvp->CP0_MVPConf0); + qemu_get_sbe32s(f, &env->mvp->CP0_MVPConf1); + + /* Load TLB */ + qemu_get_be32s(f, &env->tlb->nb_tlb); + qemu_get_be32s(f, &env->tlb->tlb_in_use); + for(i = 0; i < MIPS_TLB_MAX; i++) { + uint16_t flags; + + qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].VPN); + qemu_get_be32s(f, &env->tlb->mmu.r4k.tlb[i].PageMask); + qemu_get_8s(f, &env->tlb->mmu.r4k.tlb[i].ASID); + qemu_get_be16s(f, &flags); + env->tlb->mmu.r4k.tlb[i].G = (flags >> 10) & 1; + env->tlb->mmu.r4k.tlb[i].C0 = (flags >> 7) & 3; + env->tlb->mmu.r4k.tlb[i].C1 = (flags >> 4) & 3; + env->tlb->mmu.r4k.tlb[i].V0 = (flags >> 3) & 1; + env->tlb->mmu.r4k.tlb[i].V1 = (flags >> 2) & 1; + env->tlb->mmu.r4k.tlb[i].D0 = (flags >> 1) & 1; + env->tlb->mmu.r4k.tlb[i].D1 = (flags >> 0) & 1; + qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]); + qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]); + } + + /* Load CPU metastate */ + qemu_get_be32s(f, &env->current_tc); + qemu_get_be32s(f, &env->current_fpu); + qemu_get_sbe32s(f, &env->error_code); + qemu_get_be32s(f, &env->hflags); + qemu_get_betls(f, &env->btarget); + qemu_get_sbe32s(f, &env->bcond); + + /* Load remaining CP1 registers */ + qemu_get_sbe32s(f, &env->CP0_Index); + qemu_get_sbe32s(f, &env->CP0_Random); + qemu_get_sbe32s(f, &env->CP0_VPEControl); + qemu_get_sbe32s(f, &env->CP0_VPEConf0); + qemu_get_sbe32s(f, &env->CP0_VPEConf1); + qemu_get_betls(f, &env->CP0_YQMask); + qemu_get_betls(f, &env->CP0_VPESchedule); + qemu_get_betls(f, &env->CP0_VPEScheFBack); + qemu_get_sbe32s(f, &env->CP0_VPEOpt); + qemu_get_betls(f, &env->CP0_EntryLo0); + qemu_get_betls(f, &env->CP0_EntryLo1); + qemu_get_betls(f, &env->CP0_Context); + qemu_get_sbe32s(f, &env->CP0_PageMask); + qemu_get_sbe32s(f, &env->CP0_PageGrain); + qemu_get_sbe32s(f, &env->CP0_Wired); + qemu_get_sbe32s(f, &env->CP0_SRSConf0); + qemu_get_sbe32s(f, &env->CP0_SRSConf1); + qemu_get_sbe32s(f, &env->CP0_SRSConf2); + qemu_get_sbe32s(f, &env->CP0_SRSConf3); + qemu_get_sbe32s(f, &env->CP0_SRSConf4); + qemu_get_sbe32s(f, &env->CP0_HWREna); + qemu_get_betls(f, &env->CP0_BadVAddr); + qemu_get_sbe32s(f, &env->CP0_Count); + qemu_get_betls(f, &env->CP0_EntryHi); + qemu_get_sbe32s(f, &env->CP0_Compare); + qemu_get_sbe32s(f, &env->CP0_Status); + qemu_get_sbe32s(f, &env->CP0_IntCtl); + qemu_get_sbe32s(f, &env->CP0_SRSCtl); + qemu_get_sbe32s(f, &env->CP0_SRSMap); + qemu_get_sbe32s(f, &env->CP0_Cause); + qemu_get_betls(f, &env->CP0_EPC); + qemu_get_sbe32s(f, &env->CP0_PRid); + qemu_get_sbe32s(f, &env->CP0_EBase); + qemu_get_sbe32s(f, &env->CP0_Config0); + qemu_get_sbe32s(f, &env->CP0_Config1); + qemu_get_sbe32s(f, &env->CP0_Config2); + qemu_get_sbe32s(f, &env->CP0_Config3); + qemu_get_sbe32s(f, &env->CP0_Config6); + qemu_get_sbe32s(f, &env->CP0_Config7); + qemu_get_betls(f, &env->CP0_LLAddr); + for(i = 0; i < 8; i++) + qemu_get_betls(f, &env->CP0_WatchLo[i]); + for(i = 0; i < 8; i++) + qemu_get_sbe32s(f, &env->CP0_WatchHi[i]); + qemu_get_betls(f, &env->CP0_XContext); + qemu_get_sbe32s(f, &env->CP0_Framemask); + qemu_get_sbe32s(f, &env->CP0_Debug); + qemu_get_betls(f, &env->CP0_DEPC); + qemu_get_sbe32s(f, &env->CP0_Performance0); + qemu_get_sbe32s(f, &env->CP0_TagLo); + qemu_get_sbe32s(f, &env->CP0_DataLo); + qemu_get_sbe32s(f, &env->CP0_TagHi); + qemu_get_sbe32s(f, &env->CP0_DataHi); + qemu_get_betls(f, &env->CP0_ErrorEPC); + qemu_get_sbe32s(f, &env->CP0_DESAVE); + + /* Load inactive TC state */ + for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) + load_tc(f, &env->tcs[i]); + for (i = 0; i < MIPS_FPU_MAX; i++) + load_fpu(f, &env->fpus[i]); + + /* XXX: ensure compatiblity for halted bit ? */ + tlb_flush(env, 1); return 0; }