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