nand: boot code cleanup
[qemu/mini2440.git] / target-i386 / machine.c
blob1b0d36d404fda474c4481d0ace40ecb07fff88b3
1 #include "hw/hw.h"
2 #include "hw/boards.h"
3 #include "hw/pc.h"
4 #include "hw/isa.h"
6 #include "exec-all.h"
8 void register_machines(void)
10 qemu_register_machine(&pc_machine);
11 qemu_register_machine(&isapc_machine);
12 #ifdef CONFIG_XEN
13 qemu_register_machine(&xenpv_machine);
14 #endif
17 static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
19 qemu_put_be32(f, dt->selector);
20 qemu_put_betl(f, dt->base);
21 qemu_put_be32(f, dt->limit);
22 qemu_put_be32(f, dt->flags);
25 static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
27 dt->selector = qemu_get_be32(f);
28 dt->base = qemu_get_betl(f);
29 dt->limit = qemu_get_be32(f);
30 dt->flags = qemu_get_be32(f);
33 void cpu_save(QEMUFile *f, void *opaque)
35 CPUState *env = opaque;
36 uint16_t fptag, fpus, fpuc, fpregs_format;
37 uint32_t hflags;
38 int32_t a20_mask;
39 int i;
41 for(i = 0; i < CPU_NB_REGS; i++)
42 qemu_put_betls(f, &env->regs[i]);
43 qemu_put_betls(f, &env->eip);
44 qemu_put_betls(f, &env->eflags);
45 hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
46 qemu_put_be32s(f, &hflags);
48 /* FPU */
49 fpuc = env->fpuc;
50 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
51 fptag = 0;
52 for(i = 0; i < 8; i++) {
53 fptag |= ((!env->fptags[i]) << i);
56 qemu_put_be16s(f, &fpuc);
57 qemu_put_be16s(f, &fpus);
58 qemu_put_be16s(f, &fptag);
60 #ifdef USE_X86LDOUBLE
61 fpregs_format = 0;
62 #else
63 fpregs_format = 1;
64 #endif
65 qemu_put_be16s(f, &fpregs_format);
67 for(i = 0; i < 8; i++) {
68 #ifdef USE_X86LDOUBLE
70 uint64_t mant;
71 uint16_t exp;
72 /* we save the real CPU data (in case of MMX usage only 'mant'
73 contains the MMX register */
74 cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
75 qemu_put_be64(f, mant);
76 qemu_put_be16(f, exp);
78 #else
79 /* if we use doubles for float emulation, we save the doubles to
80 avoid losing information in case of MMX usage. It can give
81 problems if the image is restored on a CPU where long
82 doubles are used instead. */
83 qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
84 #endif
87 for(i = 0; i < 6; i++)
88 cpu_put_seg(f, &env->segs[i]);
89 cpu_put_seg(f, &env->ldt);
90 cpu_put_seg(f, &env->tr);
91 cpu_put_seg(f, &env->gdt);
92 cpu_put_seg(f, &env->idt);
94 qemu_put_be32s(f, &env->sysenter_cs);
95 qemu_put_betls(f, &env->sysenter_esp);
96 qemu_put_betls(f, &env->sysenter_eip);
98 qemu_put_betls(f, &env->cr[0]);
99 qemu_put_betls(f, &env->cr[2]);
100 qemu_put_betls(f, &env->cr[3]);
101 qemu_put_betls(f, &env->cr[4]);
103 for(i = 0; i < 8; i++)
104 qemu_put_betls(f, &env->dr[i]);
106 /* MMU */
107 a20_mask = (int32_t) env->a20_mask;
108 qemu_put_sbe32s(f, &a20_mask);
110 /* XMM */
111 qemu_put_be32s(f, &env->mxcsr);
112 for(i = 0; i < CPU_NB_REGS; i++) {
113 qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
114 qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
117 #ifdef TARGET_X86_64
118 qemu_put_be64s(f, &env->efer);
119 qemu_put_be64s(f, &env->star);
120 qemu_put_be64s(f, &env->lstar);
121 qemu_put_be64s(f, &env->cstar);
122 qemu_put_be64s(f, &env->fmask);
123 qemu_put_be64s(f, &env->kernelgsbase);
124 #endif
125 qemu_put_be32s(f, &env->smbase);
127 qemu_put_be64s(f, &env->pat);
128 qemu_put_be32s(f, &env->hflags2);
130 qemu_put_be64s(f, &env->vm_hsave);
131 qemu_put_be64s(f, &env->vm_vmcb);
132 qemu_put_be64s(f, &env->tsc_offset);
133 qemu_put_be64s(f, &env->intercept);
134 qemu_put_be16s(f, &env->intercept_cr_read);
135 qemu_put_be16s(f, &env->intercept_cr_write);
136 qemu_put_be16s(f, &env->intercept_dr_read);
137 qemu_put_be16s(f, &env->intercept_dr_write);
138 qemu_put_be32s(f, &env->intercept_exceptions);
139 qemu_put_8s(f, &env->v_tpr);
141 /* MTRRs */
142 for(i = 0; i < 11; i++)
143 qemu_put_be64s(f, &env->mtrr_fixed[i]);
144 qemu_put_be64s(f, &env->mtrr_deftype);
145 for(i = 0; i < 8; i++) {
146 qemu_put_be64s(f, &env->mtrr_var[i].base);
147 qemu_put_be64s(f, &env->mtrr_var[i].mask);
151 #ifdef USE_X86LDOUBLE
152 /* XXX: add that in a FPU generic layer */
153 union x86_longdouble {
154 uint64_t mant;
155 uint16_t exp;
158 #define MANTD1(fp) (fp & ((1LL << 52) - 1))
159 #define EXPBIAS1 1023
160 #define EXPD1(fp) ((fp >> 52) & 0x7FF)
161 #define SIGND1(fp) ((fp >> 32) & 0x80000000)
163 static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
165 int e;
166 /* mantissa */
167 p->mant = (MANTD1(temp) << 11) | (1LL << 63);
168 /* exponent + sign */
169 e = EXPD1(temp) - EXPBIAS1 + 16383;
170 e |= SIGND1(temp) >> 16;
171 p->exp = e;
173 #endif
175 int cpu_load(QEMUFile *f, void *opaque, int version_id)
177 CPUState *env = opaque;
178 int i, guess_mmx;
179 uint32_t hflags;
180 uint16_t fpus, fpuc, fptag, fpregs_format;
181 int32_t a20_mask;
183 if (version_id != 3 && version_id != 4 && version_id != 5
184 && version_id != 6 && version_id != 7 && version_id != 8)
185 return -EINVAL;
186 for(i = 0; i < CPU_NB_REGS; i++)
187 qemu_get_betls(f, &env->regs[i]);
188 qemu_get_betls(f, &env->eip);
189 qemu_get_betls(f, &env->eflags);
190 qemu_get_be32s(f, &hflags);
192 qemu_get_be16s(f, &fpuc);
193 qemu_get_be16s(f, &fpus);
194 qemu_get_be16s(f, &fptag);
195 qemu_get_be16s(f, &fpregs_format);
197 /* NOTE: we cannot always restore the FPU state if the image come
198 from a host with a different 'USE_X86LDOUBLE' define. We guess
199 if we are in an MMX state to restore correctly in that case. */
200 guess_mmx = ((fptag == 0xff) && (fpus & 0x3800) == 0);
201 for(i = 0; i < 8; i++) {
202 uint64_t mant;
203 uint16_t exp;
205 switch(fpregs_format) {
206 case 0:
207 mant = qemu_get_be64(f);
208 exp = qemu_get_be16(f);
209 #ifdef USE_X86LDOUBLE
210 env->fpregs[i].d = cpu_set_fp80(mant, exp);
211 #else
212 /* difficult case */
213 if (guess_mmx)
214 env->fpregs[i].mmx.MMX_Q(0) = mant;
215 else
216 env->fpregs[i].d = cpu_set_fp80(mant, exp);
217 #endif
218 break;
219 case 1:
220 mant = qemu_get_be64(f);
221 #ifdef USE_X86LDOUBLE
223 union x86_longdouble *p;
224 /* difficult case */
225 p = (void *)&env->fpregs[i];
226 if (guess_mmx) {
227 p->mant = mant;
228 p->exp = 0xffff;
229 } else {
230 fp64_to_fp80(p, mant);
233 #else
234 env->fpregs[i].mmx.MMX_Q(0) = mant;
235 #endif
236 break;
237 default:
238 return -EINVAL;
242 env->fpuc = fpuc;
243 /* XXX: restore FPU round state */
244 env->fpstt = (fpus >> 11) & 7;
245 env->fpus = fpus & ~0x3800;
246 fptag ^= 0xff;
247 for(i = 0; i < 8; i++) {
248 env->fptags[i] = (fptag >> i) & 1;
251 for(i = 0; i < 6; i++)
252 cpu_get_seg(f, &env->segs[i]);
253 cpu_get_seg(f, &env->ldt);
254 cpu_get_seg(f, &env->tr);
255 cpu_get_seg(f, &env->gdt);
256 cpu_get_seg(f, &env->idt);
258 qemu_get_be32s(f, &env->sysenter_cs);
259 if (version_id >= 7) {
260 qemu_get_betls(f, &env->sysenter_esp);
261 qemu_get_betls(f, &env->sysenter_eip);
262 } else {
263 env->sysenter_esp = qemu_get_be32(f);
264 env->sysenter_eip = qemu_get_be32(f);
267 qemu_get_betls(f, &env->cr[0]);
268 qemu_get_betls(f, &env->cr[2]);
269 qemu_get_betls(f, &env->cr[3]);
270 qemu_get_betls(f, &env->cr[4]);
272 for(i = 0; i < 8; i++)
273 qemu_get_betls(f, &env->dr[i]);
274 cpu_breakpoint_remove_all(env, BP_CPU);
275 cpu_watchpoint_remove_all(env, BP_CPU);
276 for (i = 0; i < 4; i++)
277 hw_breakpoint_insert(env, i);
279 /* MMU */
280 qemu_get_sbe32s(f, &a20_mask);
281 env->a20_mask = a20_mask;
283 qemu_get_be32s(f, &env->mxcsr);
284 for(i = 0; i < CPU_NB_REGS; i++) {
285 qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
286 qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
289 #ifdef TARGET_X86_64
290 qemu_get_be64s(f, &env->efer);
291 qemu_get_be64s(f, &env->star);
292 qemu_get_be64s(f, &env->lstar);
293 qemu_get_be64s(f, &env->cstar);
294 qemu_get_be64s(f, &env->fmask);
295 qemu_get_be64s(f, &env->kernelgsbase);
296 #endif
297 if (version_id >= 4) {
298 qemu_get_be32s(f, &env->smbase);
300 if (version_id >= 5) {
301 qemu_get_be64s(f, &env->pat);
302 qemu_get_be32s(f, &env->hflags2);
303 if (version_id < 6)
304 qemu_get_be32s(f, &env->halted);
306 qemu_get_be64s(f, &env->vm_hsave);
307 qemu_get_be64s(f, &env->vm_vmcb);
308 qemu_get_be64s(f, &env->tsc_offset);
309 qemu_get_be64s(f, &env->intercept);
310 qemu_get_be16s(f, &env->intercept_cr_read);
311 qemu_get_be16s(f, &env->intercept_cr_write);
312 qemu_get_be16s(f, &env->intercept_dr_read);
313 qemu_get_be16s(f, &env->intercept_dr_write);
314 qemu_get_be32s(f, &env->intercept_exceptions);
315 qemu_get_8s(f, &env->v_tpr);
318 if (version_id >= 8) {
319 /* MTRRs */
320 for(i = 0; i < 11; i++)
321 qemu_get_be64s(f, &env->mtrr_fixed[i]);
322 qemu_get_be64s(f, &env->mtrr_deftype);
323 for(i = 0; i < 8; i++) {
324 qemu_get_be64s(f, &env->mtrr_var[i].base);
325 qemu_get_be64s(f, &env->mtrr_var[i].mask);
329 /* XXX: ensure compatiblity for halted bit ? */
330 /* XXX: compute redundant hflags bits */
331 env->hflags = hflags;
332 tlb_flush(env, 1);
333 return 0;