1#include "hw/hw.h"
2#include "hw/boards.h"
3
4#include "cpu.h"
5
6static void save_tc(QEMUFile *f, TCState *tc)
7{
8    int i;
9
10    /* Save active TC */
11    for(i = 0; i < 32; i++)
12        qemu_put_betls(f, &tc->gpr[i]);
13    qemu_put_betls(f, &tc->PC);
14    for(i = 0; i < MIPS_DSP_ACC; i++)
15        qemu_put_betls(f, &tc->HI[i]);
16    for(i = 0; i < MIPS_DSP_ACC; i++)
17        qemu_put_betls(f, &tc->LO[i]);
18    for(i = 0; i < MIPS_DSP_ACC; i++)
19        qemu_put_betls(f, &tc->ACX[i]);
20    qemu_put_betls(f, &tc->DSPControl);
21    qemu_put_sbe32s(f, &tc->CP0_TCStatus);
22    qemu_put_sbe32s(f, &tc->CP0_TCBind);
23    qemu_put_betls(f, &tc->CP0_TCHalt);
24    qemu_put_betls(f, &tc->CP0_TCContext);
25    qemu_put_betls(f, &tc->CP0_TCSchedule);
26    qemu_put_betls(f, &tc->CP0_TCScheFBack);
27    qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
28}
29
30static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
31{
32    int i;
33
34    for(i = 0; i < 32; i++)
35        qemu_put_be64s(f, &fpu->fpr[i].d);
36    qemu_put_s8s(f, &fpu->fp_status.float_detect_tininess);
37    qemu_put_s8s(f, &fpu->fp_status.float_rounding_mode);
38    qemu_put_s8s(f, &fpu->fp_status.float_exception_flags);
39    qemu_put_be32s(f, &fpu->fcr0);
40    qemu_put_be32s(f, &fpu->fcr31);
41}
42
43void cpu_save(QEMUFile *f, void *opaque)
44{
45    CPUMIPSState *env = opaque;
46    int i;
47
48    /* Save active TC */
49    save_tc(f, &env->active_tc);
50
51    /* Save active FPU */
52    save_fpu(f, &env->active_fpu);
53
54    /* Save MVP */
55    qemu_put_sbe32s(f, &env->mvp->CP0_MVPControl);
56    qemu_put_sbe32s(f, &env->mvp->CP0_MVPConf0);
57    qemu_put_sbe32s(f, &env->mvp->CP0_MVPConf1);
58
59    /* Save TLB */
60    qemu_put_be32s(f, &env->tlb->nb_tlb);
61    for(i = 0; i < MIPS_TLB_MAX; i++) {
62        uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].G << 10) |
63                          (env->tlb->mmu.r4k.tlb[i].C0 << 7) |
64                          (env->tlb->mmu.r4k.tlb[i].C1 << 4) |
65                          (env->tlb->mmu.r4k.tlb[i].V0 << 3) |
66                          (env->tlb->mmu.r4k.tlb[i].V1 << 2) |
67                          (env->tlb->mmu.r4k.tlb[i].D0 << 1) |
68                          (env->tlb->mmu.r4k.tlb[i].D1 << 0));
69        uint8_t asid;
70
71        qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].VPN);
72        qemu_put_be32s(f, &env->tlb->mmu.r4k.tlb[i].PageMask);
73        asid = env->tlb->mmu.r4k.tlb[i].ASID;
74        qemu_put_8s(f, &asid);
75        qemu_put_be16s(f, &flags);
76        qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]);
77        qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]);
78    }
79
80    /* Save CPU metastate */
81    qemu_put_be32s(f, &env->current_tc);
82    qemu_put_be32s(f, &env->current_fpu);
83    qemu_put_sbe32s(f, &env->error_code);
84    qemu_put_be32s(f, &env->hflags);
85    qemu_put_betls(f, &env->btarget);
86    i = env->bcond;
87    qemu_put_sbe32s(f, &i);
88
89    /* Save remaining CP1 registers */
90    qemu_put_sbe32s(f, &env->CP0_Index);
91    qemu_put_sbe32s(f, &env->CP0_Random);
92    qemu_put_sbe32s(f, &env->CP0_VPEControl);
93    qemu_put_sbe32s(f, &env->CP0_VPEConf0);
94    qemu_put_sbe32s(f, &env->CP0_VPEConf1);
95    qemu_put_betls(f, &env->CP0_YQMask);
96    qemu_put_betls(f, &env->CP0_VPESchedule);
97    qemu_put_betls(f, &env->CP0_VPEScheFBack);
98    qemu_put_sbe32s(f, &env->CP0_VPEOpt);
99    qemu_put_betls(f, &env->CP0_EntryLo0);
100    qemu_put_betls(f, &env->CP0_EntryLo1);
101    qemu_put_betls(f, &env->CP0_Context);
102    qemu_put_sbe32s(f, &env->CP0_PageMask);
103    qemu_put_sbe32s(f, &env->CP0_PageGrain);
104    qemu_put_sbe32s(f, &env->CP0_Wired);
105    qemu_put_sbe32s(f, &env->CP0_SRSConf0);
106    qemu_put_sbe32s(f, &env->CP0_SRSConf1);
107    qemu_put_sbe32s(f, &env->CP0_SRSConf2);
108    qemu_put_sbe32s(f, &env->CP0_SRSConf3);
109    qemu_put_sbe32s(f, &env->CP0_SRSConf4);
110    qemu_put_sbe32s(f, &env->CP0_HWREna);
111    qemu_put_betls(f, &env->CP0_BadVAddr);
112    qemu_put_sbe32s(f, &env->CP0_Count);
113    qemu_put_betls(f, &env->CP0_EntryHi);
114    qemu_put_sbe32s(f, &env->CP0_Compare);
115    qemu_put_sbe32s(f, &env->CP0_Status);
116    qemu_put_sbe32s(f, &env->CP0_IntCtl);
117    qemu_put_sbe32s(f, &env->CP0_SRSCtl);
118    qemu_put_sbe32s(f, &env->CP0_SRSMap);
119    qemu_put_sbe32s(f, &env->CP0_Cause);
120    qemu_put_betls(f, &env->CP0_EPC);
121    qemu_put_sbe32s(f, &env->CP0_PRid);
122    qemu_put_sbe32s(f, &env->CP0_EBase);
123    qemu_put_sbe32s(f, &env->CP0_Config0);
124    qemu_put_sbe32s(f, &env->CP0_Config1);
125    qemu_put_sbe32s(f, &env->CP0_Config2);
126    qemu_put_sbe32s(f, &env->CP0_Config3);
127    qemu_put_sbe32s(f, &env->CP0_Config6);
128    qemu_put_sbe32s(f, &env->CP0_Config7);
129    qemu_put_betls(f, &env->lladdr);
130    for(i = 0; i < 8; i++)
131        qemu_put_betls(f, &env->CP0_WatchLo[i]);
132    for(i = 0; i < 8; i++)
133        qemu_put_sbe32s(f, &env->CP0_WatchHi[i]);
134    qemu_put_betls(f, &env->CP0_XContext);
135    qemu_put_sbe32s(f, &env->CP0_Framemask);
136    qemu_put_sbe32s(f, &env->CP0_Debug);
137    qemu_put_betls(f, &env->CP0_DEPC);
138    qemu_put_sbe32s(f, &env->CP0_Performance0);
139    qemu_put_sbe32s(f, &env->CP0_TagLo);
140    qemu_put_sbe32s(f, &env->CP0_DataLo);
141    qemu_put_sbe32s(f, &env->CP0_TagHi);
142    qemu_put_sbe32s(f, &env->CP0_DataHi);
143    qemu_put_betls(f, &env->CP0_ErrorEPC);
144    qemu_put_sbe32s(f, &env->CP0_DESAVE);
145
146    /* Save inactive TC state */
147    for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
148        save_tc(f, &env->tcs[i]);
149    for (i = 0; i < MIPS_FPU_MAX; i++)
150        save_fpu(f, &env->fpus[i]);
151}
152
153static void load_tc(QEMUFile *f, TCState *tc)
154{
155    int i;
156
157    /* Save active TC */
158    for(i = 0; i < 32; i++)
159        qemu_get_betls(f, &tc->gpr[i]);
160    qemu_get_betls(f, &tc->PC);
161    for(i = 0; i < MIPS_DSP_ACC; i++)
162        qemu_get_betls(f, &tc->HI[i]);
163    for(i = 0; i < MIPS_DSP_ACC; i++)
164        qemu_get_betls(f, &tc->LO[i]);
165    for(i = 0; i < MIPS_DSP_ACC; i++)
166        qemu_get_betls(f, &tc->ACX[i]);
167    qemu_get_betls(f, &tc->DSPControl);
168    qemu_get_sbe32s(f, &tc->CP0_TCStatus);
169    qemu_get_sbe32s(f, &tc->CP0_TCBind);
170    qemu_get_betls(f, &tc->CP0_TCHalt);
171    qemu_get_betls(f, &tc->CP0_TCContext);
172    qemu_get_betls(f, &tc->CP0_TCSchedule);
173    qemu_get_betls(f, &tc->CP0_TCScheFBack);
174    qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
175}
176
177static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
178{
179    int i;
180
181    for(i = 0; i < 32; i++)
182        qemu_get_be64s(f, &fpu->fpr[i].d);
183    qemu_get_s8s(f, &fpu->fp_status.float_detect_tininess);
184    qemu_get_s8s(f, &fpu->fp_status.float_rounding_mode);
185    qemu_get_s8s(f, &fpu->fp_status.float_exception_flags);
186    qemu_get_be32s(f, &fpu->fcr0);
187    qemu_get_be32s(f, &fpu->fcr31);
188}
189
190int cpu_load(QEMUFile *f, void *opaque, int version_id)
191{
192    CPUMIPSState *env = opaque;
193    int i;
194
195    if (version_id != 3)
196        return -EINVAL;
197
198    /* Load active TC */
199    load_tc(f, &env->active_tc);
200
201    /* Load active FPU */
202    load_fpu(f, &env->active_fpu);
203
204    /* Load MVP */
205    qemu_get_sbe32s(f, &env->mvp->CP0_MVPControl);
206    qemu_get_sbe32s(f, &env->mvp->CP0_MVPConf0);
207    qemu_get_sbe32s(f, &env->mvp->CP0_MVPConf1);
208
209    /* Load TLB */
210    qemu_get_be32s(f, &env->tlb->nb_tlb);
211    for(i = 0; i < MIPS_TLB_MAX; i++) {
212        uint16_t flags;
213        uint8_t asid;
214
215        qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].VPN);
216        qemu_get_be32s(f, &env->tlb->mmu.r4k.tlb[i].PageMask);
217        qemu_get_8s(f, &asid);
218        env->tlb->mmu.r4k.tlb[i].ASID = asid;
219        qemu_get_be16s(f, &flags);
220        env->tlb->mmu.r4k.tlb[i].G = (flags >> 10) & 1;
221        env->tlb->mmu.r4k.tlb[i].C0 = (flags >> 7) & 3;
222        env->tlb->mmu.r4k.tlb[i].C1 = (flags >> 4) & 3;
223        env->tlb->mmu.r4k.tlb[i].V0 = (flags >> 3) & 1;
224        env->tlb->mmu.r4k.tlb[i].V1 = (flags >> 2) & 1;
225        env->tlb->mmu.r4k.tlb[i].D0 = (flags >> 1) & 1;
226        env->tlb->mmu.r4k.tlb[i].D1 = (flags >> 0) & 1;
227        qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]);
228        qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]);
229    }
230
231    /* Load CPU metastate */
232    qemu_get_be32s(f, &env->current_tc);
233    qemu_get_be32s(f, &env->current_fpu);
234    qemu_get_sbe32s(f, &env->error_code);
235    qemu_get_be32s(f, &env->hflags);
236    qemu_get_betls(f, &env->btarget);
237    qemu_get_sbe32s(f, &i);
238    env->bcond = i;
239
240    /* Load remaining CP1 registers */
241    qemu_get_sbe32s(f, &env->CP0_Index);
242    qemu_get_sbe32s(f, &env->CP0_Random);
243    qemu_get_sbe32s(f, &env->CP0_VPEControl);
244    qemu_get_sbe32s(f, &env->CP0_VPEConf0);
245    qemu_get_sbe32s(f, &env->CP0_VPEConf1);
246    qemu_get_betls(f, &env->CP0_YQMask);
247    qemu_get_betls(f, &env->CP0_VPESchedule);
248    qemu_get_betls(f, &env->CP0_VPEScheFBack);
249    qemu_get_sbe32s(f, &env->CP0_VPEOpt);
250    qemu_get_betls(f, &env->CP0_EntryLo0);
251    qemu_get_betls(f, &env->CP0_EntryLo1);
252    qemu_get_betls(f, &env->CP0_Context);
253    qemu_get_sbe32s(f, &env->CP0_PageMask);
254    qemu_get_sbe32s(f, &env->CP0_PageGrain);
255    qemu_get_sbe32s(f, &env->CP0_Wired);
256    qemu_get_sbe32s(f, &env->CP0_SRSConf0);
257    qemu_get_sbe32s(f, &env->CP0_SRSConf1);
258    qemu_get_sbe32s(f, &env->CP0_SRSConf2);
259    qemu_get_sbe32s(f, &env->CP0_SRSConf3);
260    qemu_get_sbe32s(f, &env->CP0_SRSConf4);
261    qemu_get_sbe32s(f, &env->CP0_HWREna);
262    qemu_get_betls(f, &env->CP0_BadVAddr);
263    qemu_get_sbe32s(f, &env->CP0_Count);
264    qemu_get_betls(f, &env->CP0_EntryHi);
265    qemu_get_sbe32s(f, &env->CP0_Compare);
266    qemu_get_sbe32s(f, &env->CP0_Status);
267    qemu_get_sbe32s(f, &env->CP0_IntCtl);
268    qemu_get_sbe32s(f, &env->CP0_SRSCtl);
269    qemu_get_sbe32s(f, &env->CP0_SRSMap);
270    qemu_get_sbe32s(f, &env->CP0_Cause);
271    qemu_get_betls(f, &env->CP0_EPC);
272    qemu_get_sbe32s(f, &env->CP0_PRid);
273    qemu_get_sbe32s(f, &env->CP0_EBase);
274    qemu_get_sbe32s(f, &env->CP0_Config0);
275    qemu_get_sbe32s(f, &env->CP0_Config1);
276    qemu_get_sbe32s(f, &env->CP0_Config2);
277    qemu_get_sbe32s(f, &env->CP0_Config3);
278    qemu_get_sbe32s(f, &env->CP0_Config6);
279    qemu_get_sbe32s(f, &env->CP0_Config7);
280    qemu_get_betls(f, &env->lladdr);
281    for(i = 0; i < 8; i++)
282        qemu_get_betls(f, &env->CP0_WatchLo[i]);
283    for(i = 0; i < 8; i++)
284        qemu_get_sbe32s(f, &env->CP0_WatchHi[i]);
285    qemu_get_betls(f, &env->CP0_XContext);
286    qemu_get_sbe32s(f, &env->CP0_Framemask);
287    qemu_get_sbe32s(f, &env->CP0_Debug);
288    qemu_get_betls(f, &env->CP0_DEPC);
289    qemu_get_sbe32s(f, &env->CP0_Performance0);
290    qemu_get_sbe32s(f, &env->CP0_TagLo);
291    qemu_get_sbe32s(f, &env->CP0_DataLo);
292    qemu_get_sbe32s(f, &env->CP0_TagHi);
293    qemu_get_sbe32s(f, &env->CP0_DataHi);
294    qemu_get_betls(f, &env->CP0_ErrorEPC);
295    qemu_get_sbe32s(f, &env->CP0_DESAVE);
296
297    /* Load inactive TC state */
298    for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
299        load_tc(f, &env->tcs[i]);
300    for (i = 0; i < MIPS_FPU_MAX; i++)
301        load_fpu(f, &env->fpus[i]);
302
303    /* XXX: ensure compatiblity for halted bit ? */
304    tlb_flush(env, 1);
305    return 0;
306}
307