Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ b6abf97d

History | View | Annotate | Download (7 kB)

1 8dd3dca3 aurel32
#include "hw/hw.h"
2 8dd3dca3 aurel32
#include "hw/boards.h"
3 8dd3dca3 aurel32
#include "hw/pc.h"
4 8dd3dca3 aurel32
#include "hw/isa.h"
5 8dd3dca3 aurel32
6 8dd3dca3 aurel32
#include "exec-all.h"
7 8dd3dca3 aurel32
8 8dd3dca3 aurel32
void register_machines(void)
9 8dd3dca3 aurel32
{
10 8dd3dca3 aurel32
    qemu_register_machine(&pc_machine);
11 8dd3dca3 aurel32
    qemu_register_machine(&isapc_machine);
12 8dd3dca3 aurel32
}
13 8dd3dca3 aurel32
14 8dd3dca3 aurel32
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
15 8dd3dca3 aurel32
{
16 8dd3dca3 aurel32
    qemu_put_be32(f, dt->selector);
17 8dd3dca3 aurel32
    qemu_put_betl(f, dt->base);
18 8dd3dca3 aurel32
    qemu_put_be32(f, dt->limit);
19 8dd3dca3 aurel32
    qemu_put_be32(f, dt->flags);
20 8dd3dca3 aurel32
}
21 8dd3dca3 aurel32
22 8dd3dca3 aurel32
static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
23 8dd3dca3 aurel32
{
24 8dd3dca3 aurel32
    dt->selector = qemu_get_be32(f);
25 8dd3dca3 aurel32
    dt->base = qemu_get_betl(f);
26 8dd3dca3 aurel32
    dt->limit = qemu_get_be32(f);
27 8dd3dca3 aurel32
    dt->flags = qemu_get_be32(f);
28 8dd3dca3 aurel32
}
29 8dd3dca3 aurel32
30 8dd3dca3 aurel32
void cpu_save(QEMUFile *f, void *opaque)
31 8dd3dca3 aurel32
{
32 8dd3dca3 aurel32
    CPUState *env = opaque;
33 8dd3dca3 aurel32
    uint16_t fptag, fpus, fpuc, fpregs_format;
34 8dd3dca3 aurel32
    uint32_t hflags;
35 7caa33f7 aurel32
    int32_t a20_mask;
36 8dd3dca3 aurel32
    int i;
37 8dd3dca3 aurel32
38 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++)
39 8dd3dca3 aurel32
        qemu_put_betls(f, &env->regs[i]);
40 8dd3dca3 aurel32
    qemu_put_betls(f, &env->eip);
41 8dd3dca3 aurel32
    qemu_put_betls(f, &env->eflags);
42 8dd3dca3 aurel32
    hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
43 8dd3dca3 aurel32
    qemu_put_be32s(f, &hflags);
44 8dd3dca3 aurel32
45 8dd3dca3 aurel32
    /* FPU */
46 8dd3dca3 aurel32
    fpuc = env->fpuc;
47 8dd3dca3 aurel32
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
48 8dd3dca3 aurel32
    fptag = 0;
49 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
50 8dd3dca3 aurel32
        fptag |= ((!env->fptags[i]) << i);
51 8dd3dca3 aurel32
    }
52 8dd3dca3 aurel32
53 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpuc);
54 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpus);
55 8dd3dca3 aurel32
    qemu_put_be16s(f, &fptag);
56 8dd3dca3 aurel32
57 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
58 8dd3dca3 aurel32
    fpregs_format = 0;
59 8dd3dca3 aurel32
#else
60 8dd3dca3 aurel32
    fpregs_format = 1;
61 8dd3dca3 aurel32
#endif
62 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpregs_format);
63 8dd3dca3 aurel32
64 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
65 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
66 8dd3dca3 aurel32
        {
67 8dd3dca3 aurel32
            uint64_t mant;
68 8dd3dca3 aurel32
            uint16_t exp;
69 8dd3dca3 aurel32
            /* we save the real CPU data (in case of MMX usage only 'mant'
70 8dd3dca3 aurel32
               contains the MMX register */
71 8dd3dca3 aurel32
            cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
72 8dd3dca3 aurel32
            qemu_put_be64(f, mant);
73 8dd3dca3 aurel32
            qemu_put_be16(f, exp);
74 8dd3dca3 aurel32
        }
75 8dd3dca3 aurel32
#else
76 8dd3dca3 aurel32
        /* if we use doubles for float emulation, we save the doubles to
77 8dd3dca3 aurel32
           avoid losing information in case of MMX usage. It can give
78 8dd3dca3 aurel32
           problems if the image is restored on a CPU where long
79 8dd3dca3 aurel32
           doubles are used instead. */
80 8dd3dca3 aurel32
        qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
81 8dd3dca3 aurel32
#endif
82 8dd3dca3 aurel32
    }
83 8dd3dca3 aurel32
84 8dd3dca3 aurel32
    for(i = 0; i < 6; i++)
85 8dd3dca3 aurel32
        cpu_put_seg(f, &env->segs[i]);
86 8dd3dca3 aurel32
    cpu_put_seg(f, &env->ldt);
87 8dd3dca3 aurel32
    cpu_put_seg(f, &env->tr);
88 8dd3dca3 aurel32
    cpu_put_seg(f, &env->gdt);
89 8dd3dca3 aurel32
    cpu_put_seg(f, &env->idt);
90 8dd3dca3 aurel32
91 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->sysenter_cs);
92 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->sysenter_esp);
93 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->sysenter_eip);
94 8dd3dca3 aurel32
95 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[0]);
96 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[2]);
97 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[3]);
98 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[4]);
99 8dd3dca3 aurel32
100 8dd3dca3 aurel32
    for(i = 0; i < 8; i++)
101 8dd3dca3 aurel32
        qemu_put_betls(f, &env->dr[i]);
102 8dd3dca3 aurel32
103 8dd3dca3 aurel32
    /* MMU */
104 7caa33f7 aurel32
    a20_mask = (int32_t) env->a20_mask;
105 7caa33f7 aurel32
    qemu_put_be32s(f, &a20_mask);
106 8dd3dca3 aurel32
107 8dd3dca3 aurel32
    /* XMM */
108 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->mxcsr);
109 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++) {
110 8dd3dca3 aurel32
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
111 8dd3dca3 aurel32
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
112 8dd3dca3 aurel32
    }
113 8dd3dca3 aurel32
114 8dd3dca3 aurel32
#ifdef TARGET_X86_64
115 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->efer);
116 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->star);
117 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->lstar);
118 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->cstar);
119 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->fmask);
120 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->kernelgsbase);
121 8dd3dca3 aurel32
#endif
122 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->smbase);
123 8dd3dca3 aurel32
}
124 8dd3dca3 aurel32
125 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
126 8dd3dca3 aurel32
/* XXX: add that in a FPU generic layer */
127 8dd3dca3 aurel32
union x86_longdouble {
128 8dd3dca3 aurel32
    uint64_t mant;
129 8dd3dca3 aurel32
    uint16_t exp;
130 8dd3dca3 aurel32
};
131 8dd3dca3 aurel32
132 8dd3dca3 aurel32
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
133 8dd3dca3 aurel32
#define EXPBIAS1 1023
134 8dd3dca3 aurel32
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
135 8dd3dca3 aurel32
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
136 8dd3dca3 aurel32
137 8dd3dca3 aurel32
static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
138 8dd3dca3 aurel32
{
139 8dd3dca3 aurel32
    int e;
140 8dd3dca3 aurel32
    /* mantissa */
141 8dd3dca3 aurel32
    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
142 8dd3dca3 aurel32
    /* exponent + sign */
143 8dd3dca3 aurel32
    e = EXPD1(temp) - EXPBIAS1 + 16383;
144 8dd3dca3 aurel32
    e |= SIGND1(temp) >> 16;
145 8dd3dca3 aurel32
    p->exp = e;
146 8dd3dca3 aurel32
}
147 8dd3dca3 aurel32
#endif
148 8dd3dca3 aurel32
149 8dd3dca3 aurel32
int cpu_load(QEMUFile *f, void *opaque, int version_id)
150 8dd3dca3 aurel32
{
151 8dd3dca3 aurel32
    CPUState *env = opaque;
152 8dd3dca3 aurel32
    int i, guess_mmx;
153 8dd3dca3 aurel32
    uint32_t hflags;
154 8dd3dca3 aurel32
    uint16_t fpus, fpuc, fptag, fpregs_format;
155 7caa33f7 aurel32
    int32_t a20_mask;
156 8dd3dca3 aurel32
157 8dd3dca3 aurel32
    if (version_id != 3 && version_id != 4)
158 8dd3dca3 aurel32
        return -EINVAL;
159 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++)
160 8dd3dca3 aurel32
        qemu_get_betls(f, &env->regs[i]);
161 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eip);
162 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eflags);
163 8dd3dca3 aurel32
    qemu_get_be32s(f, &hflags);
164 8dd3dca3 aurel32
165 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpuc);
166 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpus);
167 8dd3dca3 aurel32
    qemu_get_be16s(f, &fptag);
168 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpregs_format);
169 8dd3dca3 aurel32
170 8dd3dca3 aurel32
    /* NOTE: we cannot always restore the FPU state if the image come
171 8dd3dca3 aurel32
       from a host with a different 'USE_X86LDOUBLE' define. We guess
172 8dd3dca3 aurel32
       if we are in an MMX state to restore correctly in that case. */
173 8dd3dca3 aurel32
    guess_mmx = ((fptag == 0xff) && (fpus & 0x3800) == 0);
174 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
175 8dd3dca3 aurel32
        uint64_t mant;
176 8dd3dca3 aurel32
        uint16_t exp;
177 8dd3dca3 aurel32
178 8dd3dca3 aurel32
        switch(fpregs_format) {
179 8dd3dca3 aurel32
        case 0:
180 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
181 8dd3dca3 aurel32
            exp = qemu_get_be16(f);
182 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
183 8dd3dca3 aurel32
            env->fpregs[i].d = cpu_set_fp80(mant, exp);
184 8dd3dca3 aurel32
#else
185 8dd3dca3 aurel32
            /* difficult case */
186 8dd3dca3 aurel32
            if (guess_mmx)
187 8dd3dca3 aurel32
                env->fpregs[i].mmx.MMX_Q(0) = mant;
188 8dd3dca3 aurel32
            else
189 8dd3dca3 aurel32
                env->fpregs[i].d = cpu_set_fp80(mant, exp);
190 8dd3dca3 aurel32
#endif
191 8dd3dca3 aurel32
            break;
192 8dd3dca3 aurel32
        case 1:
193 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
194 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
195 8dd3dca3 aurel32
            {
196 8dd3dca3 aurel32
                union x86_longdouble *p;
197 8dd3dca3 aurel32
                /* difficult case */
198 8dd3dca3 aurel32
                p = (void *)&env->fpregs[i];
199 8dd3dca3 aurel32
                if (guess_mmx) {
200 8dd3dca3 aurel32
                    p->mant = mant;
201 8dd3dca3 aurel32
                    p->exp = 0xffff;
202 8dd3dca3 aurel32
                } else {
203 8dd3dca3 aurel32
                    fp64_to_fp80(p, mant);
204 8dd3dca3 aurel32
                }
205 8dd3dca3 aurel32
            }
206 8dd3dca3 aurel32
#else
207 8dd3dca3 aurel32
            env->fpregs[i].mmx.MMX_Q(0) = mant;
208 8dd3dca3 aurel32
#endif
209 8dd3dca3 aurel32
            break;
210 8dd3dca3 aurel32
        default:
211 8dd3dca3 aurel32
            return -EINVAL;
212 8dd3dca3 aurel32
        }
213 8dd3dca3 aurel32
    }
214 8dd3dca3 aurel32
215 8dd3dca3 aurel32
    env->fpuc = fpuc;
216 8dd3dca3 aurel32
    /* XXX: restore FPU round state */
217 8dd3dca3 aurel32
    env->fpstt = (fpus >> 11) & 7;
218 8dd3dca3 aurel32
    env->fpus = fpus & ~0x3800;
219 8dd3dca3 aurel32
    fptag ^= 0xff;
220 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
221 8dd3dca3 aurel32
        env->fptags[i] = (fptag >> i) & 1;
222 8dd3dca3 aurel32
    }
223 8dd3dca3 aurel32
224 8dd3dca3 aurel32
    for(i = 0; i < 6; i++)
225 8dd3dca3 aurel32
        cpu_get_seg(f, &env->segs[i]);
226 8dd3dca3 aurel32
    cpu_get_seg(f, &env->ldt);
227 8dd3dca3 aurel32
    cpu_get_seg(f, &env->tr);
228 8dd3dca3 aurel32
    cpu_get_seg(f, &env->gdt);
229 8dd3dca3 aurel32
    cpu_get_seg(f, &env->idt);
230 8dd3dca3 aurel32
231 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->sysenter_cs);
232 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->sysenter_esp);
233 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->sysenter_eip);
234 8dd3dca3 aurel32
235 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[0]);
236 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[2]);
237 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[3]);
238 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[4]);
239 8dd3dca3 aurel32
240 8dd3dca3 aurel32
    for(i = 0; i < 8; i++)
241 8dd3dca3 aurel32
        qemu_get_betls(f, &env->dr[i]);
242 8dd3dca3 aurel32
243 8dd3dca3 aurel32
    /* MMU */
244 7caa33f7 aurel32
    qemu_get_be32s(f, &a20_mask);
245 7caa33f7 aurel32
    env->a20_mask = a20_mask;
246 8dd3dca3 aurel32
247 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->mxcsr);
248 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++) {
249 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
250 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
251 8dd3dca3 aurel32
    }
252 8dd3dca3 aurel32
253 8dd3dca3 aurel32
#ifdef TARGET_X86_64
254 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->efer);
255 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->star);
256 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->lstar);
257 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->cstar);
258 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->fmask);
259 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->kernelgsbase);
260 8dd3dca3 aurel32
#endif
261 8dd3dca3 aurel32
    if (version_id >= 4)
262 8dd3dca3 aurel32
        qemu_get_be32s(f, &env->smbase);
263 8dd3dca3 aurel32
264 8dd3dca3 aurel32
    /* XXX: compute hflags from scratch, except for CPL and IIF */
265 8dd3dca3 aurel32
    env->hflags = hflags;
266 8dd3dca3 aurel32
    tlb_flush(env, 1);
267 8dd3dca3 aurel32
    return 0;
268 8dd3dca3 aurel32
}