~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to target-i386/op_helper.c

  • Committer: pbrook
  • Date: 2006-10-22 00:18:54 UTC
  • Revision ID: git-v1:e6e5906b6e0a81718066ca43aef57515026c6624
ColdFire target.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2196 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  i386 helpers
3
 
 *
4
 
 *  Copyright (c) 2003 Fabrice Bellard
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
 */
20
 
#define CPU_NO_GLOBAL_REGS
21
 
#include "exec.h"
22
 
#include "host-utils.h"
23
 
 
24
 
//#define DEBUG_PCALL
25
 
 
26
 
#if 0
27
 
#define raise_exception_err(a, b)\
28
 
do {\
29
 
    if (logfile)\
30
 
        fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
31
 
    (raise_exception_err)(a, b);\
32
 
} while (0)
33
 
#endif
34
 
 
35
 
const uint8_t parity_table[256] = {
36
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
37
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
38
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
40
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
41
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
42
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
44
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
47
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
52
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
53
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
55
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
56
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
57
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
58
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
59
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
60
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
61
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
62
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
63
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
64
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
65
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
66
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
67
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
68
 
};
69
 
 
70
 
/* modulo 17 table */
71
 
const uint8_t rclw_table[32] = {
72
 
    0, 1, 2, 3, 4, 5, 6, 7,
73
 
    8, 9,10,11,12,13,14,15,
74
 
   16, 0, 1, 2, 3, 4, 5, 6,
75
 
    7, 8, 9,10,11,12,13,14,
76
 
};
77
 
 
78
 
/* modulo 9 table */
79
 
const uint8_t rclb_table[32] = {
80
 
    0, 1, 2, 3, 4, 5, 6, 7,
81
 
    8, 0, 1, 2, 3, 4, 5, 6,
82
 
    7, 8, 0, 1, 2, 3, 4, 5,
83
 
    6, 7, 8, 0, 1, 2, 3, 4,
84
 
};
85
 
 
86
 
const CPU86_LDouble f15rk[7] =
87
 
{
88
 
    0.00000000000000000000L,
89
 
    1.00000000000000000000L,
90
 
    3.14159265358979323851L,  /*pi*/
91
 
    0.30102999566398119523L,  /*lg2*/
92
 
    0.69314718055994530943L,  /*ln2*/
93
 
    1.44269504088896340739L,  /*l2e*/
94
 
    3.32192809488736234781L,  /*l2t*/
95
 
};
96
 
 
97
 
/* broken thread support */
98
 
 
99
 
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
100
 
 
101
 
void helper_lock(void)
102
 
{
103
 
    spin_lock(&global_cpu_lock);
104
 
}
105
 
 
106
 
void helper_unlock(void)
107
 
{
108
 
    spin_unlock(&global_cpu_lock);
109
 
}
110
 
 
111
 
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
112
 
{
113
 
    load_eflags(t0, update_mask);
114
 
}
115
 
 
116
 
target_ulong helper_read_eflags(void)
117
 
{
118
 
    uint32_t eflags;
119
 
    eflags = cc_table[CC_OP].compute_all();
120
 
    eflags |= (DF & DF_MASK);
121
 
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
122
 
    return eflags;
123
 
}
124
 
 
125
 
/* return non zero if error */
126
 
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
127
 
                               int selector)
128
 
{
129
 
    SegmentCache *dt;
130
 
    int index;
131
 
    target_ulong ptr;
132
 
 
133
 
    if (selector & 0x4)
134
 
        dt = &env->ldt;
135
 
    else
136
 
        dt = &env->gdt;
137
 
    index = selector & ~7;
138
 
    if ((index + 7) > dt->limit)
139
 
        return -1;
140
 
    ptr = dt->base + index;
141
 
    *e1_ptr = ldl_kernel(ptr);
142
 
    *e2_ptr = ldl_kernel(ptr + 4);
143
 
    return 0;
144
 
}
145
 
 
146
 
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
147
 
{
148
 
    unsigned int limit;
149
 
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
150
 
    if (e2 & DESC_G_MASK)
151
 
        limit = (limit << 12) | 0xfff;
152
 
    return limit;
153
 
}
154
 
 
155
 
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
156
 
{
157
 
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
158
 
}
159
 
 
160
 
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
161
 
{
162
 
    sc->base = get_seg_base(e1, e2);
163
 
    sc->limit = get_seg_limit(e1, e2);
164
 
    sc->flags = e2;
165
 
}
166
 
 
167
 
/* init the segment cache in vm86 mode. */
168
 
static inline void load_seg_vm(int seg, int selector)
169
 
{
170
 
    selector &= 0xffff;
171
 
    cpu_x86_load_seg_cache(env, seg, selector,
172
 
                           (selector << 4), 0xffff, 0);
173
 
}
174
 
 
175
 
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
176
 
                                       uint32_t *esp_ptr, int dpl)
177
 
{
178
 
    int type, index, shift;
179
 
 
180
 
#if 0
181
 
    {
182
 
        int i;
183
 
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
184
 
        for(i=0;i<env->tr.limit;i++) {
185
 
            printf("%02x ", env->tr.base[i]);
186
 
            if ((i & 7) == 7) printf("\n");
187
 
        }
188
 
        printf("\n");
189
 
    }
190
 
#endif
191
 
 
192
 
    if (!(env->tr.flags & DESC_P_MASK))
193
 
        cpu_abort(env, "invalid tss");
194
 
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
195
 
    if ((type & 7) != 1)
196
 
        cpu_abort(env, "invalid tss type");
197
 
    shift = type >> 3;
198
 
    index = (dpl * 4 + 2) << shift;
199
 
    if (index + (4 << shift) - 1 > env->tr.limit)
200
 
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
201
 
    if (shift == 0) {
202
 
        *esp_ptr = lduw_kernel(env->tr.base + index);
203
 
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
204
 
    } else {
205
 
        *esp_ptr = ldl_kernel(env->tr.base + index);
206
 
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
207
 
    }
208
 
}
209
 
 
210
 
/* XXX: merge with load_seg() */
211
 
static void tss_load_seg(int seg_reg, int selector)
212
 
{
213
 
    uint32_t e1, e2;
214
 
    int rpl, dpl, cpl;
215
 
 
216
 
    if ((selector & 0xfffc) != 0) {
217
 
        if (load_segment(&e1, &e2, selector) != 0)
218
 
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
219
 
        if (!(e2 & DESC_S_MASK))
220
 
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
221
 
        rpl = selector & 3;
222
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
223
 
        cpl = env->hflags & HF_CPL_MASK;
224
 
        if (seg_reg == R_CS) {
225
 
            if (!(e2 & DESC_CS_MASK))
226
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
227
 
            /* XXX: is it correct ? */
228
 
            if (dpl != rpl)
229
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
230
 
            if ((e2 & DESC_C_MASK) && dpl > rpl)
231
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
232
 
        } else if (seg_reg == R_SS) {
233
 
            /* SS must be writable data */
234
 
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
235
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
236
 
            if (dpl != cpl || dpl != rpl)
237
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
238
 
        } else {
239
 
            /* not readable code */
240
 
            if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
241
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
242
 
            /* if data or non conforming code, checks the rights */
243
 
            if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
244
 
                if (dpl < cpl || dpl < rpl)
245
 
                    raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
246
 
            }
247
 
        }
248
 
        if (!(e2 & DESC_P_MASK))
249
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
250
 
        cpu_x86_load_seg_cache(env, seg_reg, selector,
251
 
                       get_seg_base(e1, e2),
252
 
                       get_seg_limit(e1, e2),
253
 
                       e2);
254
 
    } else {
255
 
        if (seg_reg == R_SS || seg_reg == R_CS)
256
 
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
257
 
    }
258
 
}
259
 
 
260
 
#define SWITCH_TSS_JMP  0
261
 
#define SWITCH_TSS_IRET 1
262
 
#define SWITCH_TSS_CALL 2
263
 
 
264
 
/* XXX: restore CPU state in registers (PowerPC case) */
265
 
static void switch_tss(int tss_selector,
266
 
                       uint32_t e1, uint32_t e2, int source,
267
 
                       uint32_t next_eip)
268
 
{
269
 
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
270
 
    target_ulong tss_base;
271
 
    uint32_t new_regs[8], new_segs[6];
272
 
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
273
 
    uint32_t old_eflags, eflags_mask;
274
 
    SegmentCache *dt;
275
 
    int index;
276
 
    target_ulong ptr;
277
 
 
278
 
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
279
 
#ifdef DEBUG_PCALL
280
 
    if (loglevel & CPU_LOG_PCALL)
281
 
        fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
282
 
#endif
283
 
 
284
 
    /* if task gate, we read the TSS segment and we load it */
285
 
    if (type == 5) {
286
 
        if (!(e2 & DESC_P_MASK))
287
 
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
288
 
        tss_selector = e1 >> 16;
289
 
        if (tss_selector & 4)
290
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
291
 
        if (load_segment(&e1, &e2, tss_selector) != 0)
292
 
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
293
 
        if (e2 & DESC_S_MASK)
294
 
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
295
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
296
 
        if ((type & 7) != 1)
297
 
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
298
 
    }
299
 
 
300
 
    if (!(e2 & DESC_P_MASK))
301
 
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
302
 
 
303
 
    if (type & 8)
304
 
        tss_limit_max = 103;
305
 
    else
306
 
        tss_limit_max = 43;
307
 
    tss_limit = get_seg_limit(e1, e2);
308
 
    tss_base = get_seg_base(e1, e2);
309
 
    if ((tss_selector & 4) != 0 ||
310
 
        tss_limit < tss_limit_max)
311
 
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
312
 
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
313
 
    if (old_type & 8)
314
 
        old_tss_limit_max = 103;
315
 
    else
316
 
        old_tss_limit_max = 43;
317
 
 
318
 
    /* read all the registers from the new TSS */
319
 
    if (type & 8) {
320
 
        /* 32 bit */
321
 
        new_cr3 = ldl_kernel(tss_base + 0x1c);
322
 
        new_eip = ldl_kernel(tss_base + 0x20);
323
 
        new_eflags = ldl_kernel(tss_base + 0x24);
324
 
        for(i = 0; i < 8; i++)
325
 
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
326
 
        for(i = 0; i < 6; i++)
327
 
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
328
 
        new_ldt = lduw_kernel(tss_base + 0x60);
329
 
        new_trap = ldl_kernel(tss_base + 0x64);
330
 
    } else {
331
 
        /* 16 bit */
332
 
        new_cr3 = 0;
333
 
        new_eip = lduw_kernel(tss_base + 0x0e);
334
 
        new_eflags = lduw_kernel(tss_base + 0x10);
335
 
        for(i = 0; i < 8; i++)
336
 
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
337
 
        for(i = 0; i < 4; i++)
338
 
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
339
 
        new_ldt = lduw_kernel(tss_base + 0x2a);
340
 
        new_segs[R_FS] = 0;
341
 
        new_segs[R_GS] = 0;
342
 
        new_trap = 0;
343
 
    }
344
 
 
345
 
    /* NOTE: we must avoid memory exceptions during the task switch,
346
 
       so we make dummy accesses before */
347
 
    /* XXX: it can still fail in some cases, so a bigger hack is
348
 
       necessary to valid the TLB after having done the accesses */
349
 
 
350
 
    v1 = ldub_kernel(env->tr.base);
351
 
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
352
 
    stb_kernel(env->tr.base, v1);
353
 
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
354
 
 
355
 
    /* clear busy bit (it is restartable) */
356
 
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
357
 
        target_ulong ptr;
358
 
        uint32_t e2;
359
 
        ptr = env->gdt.base + (env->tr.selector & ~7);
360
 
        e2 = ldl_kernel(ptr + 4);
361
 
        e2 &= ~DESC_TSS_BUSY_MASK;
362
 
        stl_kernel(ptr + 4, e2);
363
 
    }
364
 
    old_eflags = compute_eflags();
365
 
    if (source == SWITCH_TSS_IRET)
366
 
        old_eflags &= ~NT_MASK;
367
 
 
368
 
    /* save the current state in the old TSS */
369
 
    if (type & 8) {
370
 
        /* 32 bit */
371
 
        stl_kernel(env->tr.base + 0x20, next_eip);
372
 
        stl_kernel(env->tr.base + 0x24, old_eflags);
373
 
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
374
 
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
375
 
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
376
 
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
377
 
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
378
 
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
379
 
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
380
 
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
381
 
        for(i = 0; i < 6; i++)
382
 
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
383
 
    } else {
384
 
        /* 16 bit */
385
 
        stw_kernel(env->tr.base + 0x0e, next_eip);
386
 
        stw_kernel(env->tr.base + 0x10, old_eflags);
387
 
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
388
 
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
389
 
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
390
 
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
391
 
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
392
 
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
393
 
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
394
 
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
395
 
        for(i = 0; i < 4; i++)
396
 
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
397
 
    }
398
 
 
399
 
    /* now if an exception occurs, it will occurs in the next task
400
 
       context */
401
 
 
402
 
    if (source == SWITCH_TSS_CALL) {
403
 
        stw_kernel(tss_base, env->tr.selector);
404
 
        new_eflags |= NT_MASK;
405
 
    }
406
 
 
407
 
    /* set busy bit */
408
 
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
409
 
        target_ulong ptr;
410
 
        uint32_t e2;
411
 
        ptr = env->gdt.base + (tss_selector & ~7);
412
 
        e2 = ldl_kernel(ptr + 4);
413
 
        e2 |= DESC_TSS_BUSY_MASK;
414
 
        stl_kernel(ptr + 4, e2);
415
 
    }
416
 
 
417
 
    /* set the new CPU state */
418
 
    /* from this point, any exception which occurs can give problems */
419
 
    env->cr[0] |= CR0_TS_MASK;
420
 
    env->hflags |= HF_TS_MASK;
421
 
    env->tr.selector = tss_selector;
422
 
    env->tr.base = tss_base;
423
 
    env->tr.limit = tss_limit;
424
 
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
425
 
 
426
 
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
427
 
        cpu_x86_update_cr3(env, new_cr3);
428
 
    }
429
 
 
430
 
    /* load all registers without an exception, then reload them with
431
 
       possible exception */
432
 
    env->eip = new_eip;
433
 
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
434
 
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
435
 
    if (!(type & 8))
436
 
        eflags_mask &= 0xffff;
437
 
    load_eflags(new_eflags, eflags_mask);
438
 
    /* XXX: what to do in 16 bit case ? */
439
 
    EAX = new_regs[0];
440
 
    ECX = new_regs[1];
441
 
    EDX = new_regs[2];
442
 
    EBX = new_regs[3];
443
 
    ESP = new_regs[4];
444
 
    EBP = new_regs[5];
445
 
    ESI = new_regs[6];
446
 
    EDI = new_regs[7];
447
 
    if (new_eflags & VM_MASK) {
448
 
        for(i = 0; i < 6; i++)
449
 
            load_seg_vm(i, new_segs[i]);
450
 
        /* in vm86, CPL is always 3 */
451
 
        cpu_x86_set_cpl(env, 3);
452
 
    } else {
453
 
        /* CPL is set the RPL of CS */
454
 
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
455
 
        /* first just selectors as the rest may trigger exceptions */
456
 
        for(i = 0; i < 6; i++)
457
 
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
458
 
    }
459
 
 
460
 
    env->ldt.selector = new_ldt & ~4;
461
 
    env->ldt.base = 0;
462
 
    env->ldt.limit = 0;
463
 
    env->ldt.flags = 0;
464
 
 
465
 
    /* load the LDT */
466
 
    if (new_ldt & 4)
467
 
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
468
 
 
469
 
    if ((new_ldt & 0xfffc) != 0) {
470
 
        dt = &env->gdt;
471
 
        index = new_ldt & ~7;
472
 
        if ((index + 7) > dt->limit)
473
 
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
474
 
        ptr = dt->base + index;
475
 
        e1 = ldl_kernel(ptr);
476
 
        e2 = ldl_kernel(ptr + 4);
477
 
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
478
 
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
479
 
        if (!(e2 & DESC_P_MASK))
480
 
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
481
 
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
482
 
    }
483
 
 
484
 
    /* load the segments */
485
 
    if (!(new_eflags & VM_MASK)) {
486
 
        tss_load_seg(R_CS, new_segs[R_CS]);
487
 
        tss_load_seg(R_SS, new_segs[R_SS]);
488
 
        tss_load_seg(R_ES, new_segs[R_ES]);
489
 
        tss_load_seg(R_DS, new_segs[R_DS]);
490
 
        tss_load_seg(R_FS, new_segs[R_FS]);
491
 
        tss_load_seg(R_GS, new_segs[R_GS]);
492
 
    }
493
 
 
494
 
    /* check that EIP is in the CS segment limits */
495
 
    if (new_eip > env->segs[R_CS].limit) {
496
 
        /* XXX: different exception if CALL ? */
497
 
        raise_exception_err(EXCP0D_GPF, 0);
498
 
    }
499
 
}
500
 
 
501
 
/* check if Port I/O is allowed in TSS */
502
 
static inline void check_io(int addr, int size)
503
 
{
504
 
    int io_offset, val, mask;
505
 
 
506
 
    /* TSS must be a valid 32 bit one */
507
 
    if (!(env->tr.flags & DESC_P_MASK) ||
508
 
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
509
 
        env->tr.limit < 103)
510
 
        goto fail;
511
 
    io_offset = lduw_kernel(env->tr.base + 0x66);
512
 
    io_offset += (addr >> 3);
513
 
    /* Note: the check needs two bytes */
514
 
    if ((io_offset + 1) > env->tr.limit)
515
 
        goto fail;
516
 
    val = lduw_kernel(env->tr.base + io_offset);
517
 
    val >>= (addr & 7);
518
 
    mask = (1 << size) - 1;
519
 
    /* all bits must be zero to allow the I/O */
520
 
    if ((val & mask) != 0) {
521
 
    fail:
522
 
        raise_exception_err(EXCP0D_GPF, 0);
523
 
    }
524
 
}
525
 
 
526
 
void helper_check_iob(uint32_t t0)
527
 
{
528
 
    check_io(t0, 1);
529
 
}
530
 
 
531
 
void helper_check_iow(uint32_t t0)
532
 
{
533
 
    check_io(t0, 2);
534
 
}
535
 
 
536
 
void helper_check_iol(uint32_t t0)
537
 
{
538
 
    check_io(t0, 4);
539
 
}
540
 
 
541
 
void helper_outb(uint32_t port, uint32_t data)
542
 
{
543
 
    cpu_outb(env, port, data & 0xff);
544
 
}
545
 
 
546
 
target_ulong helper_inb(uint32_t port)
547
 
{
548
 
    return cpu_inb(env, port);
549
 
}
550
 
 
551
 
void helper_outw(uint32_t port, uint32_t data)
552
 
{
553
 
    cpu_outw(env, port, data & 0xffff);
554
 
}
555
 
 
556
 
target_ulong helper_inw(uint32_t port)
557
 
{
558
 
    return cpu_inw(env, port);
559
 
}
560
 
 
561
 
void helper_outl(uint32_t port, uint32_t data)
562
 
{
563
 
    cpu_outl(env, port, data);
564
 
}
565
 
 
566
 
target_ulong helper_inl(uint32_t port)
567
 
{
568
 
    return cpu_inl(env, port);
569
 
}
570
 
 
571
 
static inline unsigned int get_sp_mask(unsigned int e2)
572
 
{
573
 
    if (e2 & DESC_B_MASK)
574
 
        return 0xffffffff;
575
 
    else
576
 
        return 0xffff;
577
 
}
578
 
 
579
 
#ifdef TARGET_X86_64
580
 
#define SET_ESP(val, sp_mask)\
581
 
do {\
582
 
    if ((sp_mask) == 0xffff)\
583
 
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
584
 
    else if ((sp_mask) == 0xffffffffLL)\
585
 
        ESP = (uint32_t)(val);\
586
 
    else\
587
 
        ESP = (val);\
588
 
} while (0)
589
 
#else
590
 
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
591
 
#endif
592
 
 
593
 
/* XXX: add a is_user flag to have proper security support */
594
 
#define PUSHW(ssp, sp, sp_mask, val)\
595
 
{\
596
 
    sp -= 2;\
597
 
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
598
 
}
599
 
 
600
 
#define PUSHL(ssp, sp, sp_mask, val)\
601
 
{\
602
 
    sp -= 4;\
603
 
    stl_kernel((ssp) + (sp & (sp_mask)), (val));\
604
 
}
605
 
 
606
 
#define POPW(ssp, sp, sp_mask, val)\
607
 
{\
608
 
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
609
 
    sp += 2;\
610
 
}
611
 
 
612
 
#define POPL(ssp, sp, sp_mask, val)\
613
 
{\
614
 
    val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
615
 
    sp += 4;\
616
 
}
617
 
 
618
 
/* protected mode interrupt */
619
 
static void do_interrupt_protected(int intno, int is_int, int error_code,
620
 
                                   unsigned int next_eip, int is_hw)
621
 
{
622
 
    SegmentCache *dt;
623
 
    target_ulong ptr, ssp;
624
 
    int type, dpl, selector, ss_dpl, cpl;
625
 
    int has_error_code, new_stack, shift;
626
 
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
627
 
    uint32_t old_eip, sp_mask;
628
 
 
629
 
    has_error_code = 0;
630
 
    if (!is_int && !is_hw) {
631
 
        switch(intno) {
632
 
        case 8:
633
 
        case 10:
634
 
        case 11:
635
 
        case 12:
636
 
        case 13:
637
 
        case 14:
638
 
        case 17:
639
 
            has_error_code = 1;
640
 
            break;
641
 
        }
642
 
    }
643
 
    if (is_int)
644
 
        old_eip = next_eip;
645
 
    else
646
 
        old_eip = env->eip;
647
 
 
648
 
    dt = &env->idt;
649
 
    if (intno * 8 + 7 > dt->limit)
650
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
651
 
    ptr = dt->base + intno * 8;
652
 
    e1 = ldl_kernel(ptr);
653
 
    e2 = ldl_kernel(ptr + 4);
654
 
    /* check gate type */
655
 
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
656
 
    switch(type) {
657
 
    case 5: /* task gate */
658
 
        /* must do that check here to return the correct error code */
659
 
        if (!(e2 & DESC_P_MASK))
660
 
            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
661
 
        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
662
 
        if (has_error_code) {
663
 
            int type;
664
 
            uint32_t mask;
665
 
            /* push the error code */
666
 
            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
667
 
            shift = type >> 3;
668
 
            if (env->segs[R_SS].flags & DESC_B_MASK)
669
 
                mask = 0xffffffff;
670
 
            else
671
 
                mask = 0xffff;
672
 
            esp = (ESP - (2 << shift)) & mask;
673
 
            ssp = env->segs[R_SS].base + esp;
674
 
            if (shift)
675
 
                stl_kernel(ssp, error_code);
676
 
            else
677
 
                stw_kernel(ssp, error_code);
678
 
            SET_ESP(esp, mask);
679
 
        }
680
 
        return;
681
 
    case 6: /* 286 interrupt gate */
682
 
    case 7: /* 286 trap gate */
683
 
    case 14: /* 386 interrupt gate */
684
 
    case 15: /* 386 trap gate */
685
 
        break;
686
 
    default:
687
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
688
 
        break;
689
 
    }
690
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
691
 
    cpl = env->hflags & HF_CPL_MASK;
692
 
    /* check privilege if software int */
693
 
    if (is_int && dpl < cpl)
694
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
695
 
    /* check valid bit */
696
 
    if (!(e2 & DESC_P_MASK))
697
 
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
698
 
    selector = e1 >> 16;
699
 
    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
700
 
    if ((selector & 0xfffc) == 0)
701
 
        raise_exception_err(EXCP0D_GPF, 0);
702
 
 
703
 
    if (load_segment(&e1, &e2, selector) != 0)
704
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
705
 
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
706
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
707
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
708
 
    if (dpl > cpl)
709
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
710
 
    if (!(e2 & DESC_P_MASK))
711
 
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
712
 
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
713
 
        /* to inner privilege */
714
 
        get_ss_esp_from_tss(&ss, &esp, dpl);
715
 
        if ((ss & 0xfffc) == 0)
716
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
717
 
        if ((ss & 3) != dpl)
718
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
719
 
        if (load_segment(&ss_e1, &ss_e2, ss) != 0)
720
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
721
 
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
722
 
        if (ss_dpl != dpl)
723
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
724
 
        if (!(ss_e2 & DESC_S_MASK) ||
725
 
            (ss_e2 & DESC_CS_MASK) ||
726
 
            !(ss_e2 & DESC_W_MASK))
727
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
728
 
        if (!(ss_e2 & DESC_P_MASK))
729
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
730
 
        new_stack = 1;
731
 
        sp_mask = get_sp_mask(ss_e2);
732
 
        ssp = get_seg_base(ss_e1, ss_e2);
733
 
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
734
 
        /* to same privilege */
735
 
        if (env->eflags & VM_MASK)
736
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
737
 
        new_stack = 0;
738
 
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
739
 
        ssp = env->segs[R_SS].base;
740
 
        esp = ESP;
741
 
        dpl = cpl;
742
 
    } else {
743
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
744
 
        new_stack = 0; /* avoid warning */
745
 
        sp_mask = 0; /* avoid warning */
746
 
        ssp = 0; /* avoid warning */
747
 
        esp = 0; /* avoid warning */
748
 
    }
749
 
 
750
 
    shift = type >> 3;
751
 
 
752
 
#if 0
753
 
    /* XXX: check that enough room is available */
754
 
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
755
 
    if (env->eflags & VM_MASK)
756
 
        push_size += 8;
757
 
    push_size <<= shift;
758
 
#endif
759
 
    if (shift == 1) {
760
 
        if (new_stack) {
761
 
            if (env->eflags & VM_MASK) {
762
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
763
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
764
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
765
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
766
 
            }
767
 
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
768
 
            PUSHL(ssp, esp, sp_mask, ESP);
769
 
        }
770
 
        PUSHL(ssp, esp, sp_mask, compute_eflags());
771
 
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
772
 
        PUSHL(ssp, esp, sp_mask, old_eip);
773
 
        if (has_error_code) {
774
 
            PUSHL(ssp, esp, sp_mask, error_code);
775
 
        }
776
 
    } else {
777
 
        if (new_stack) {
778
 
            if (env->eflags & VM_MASK) {
779
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
780
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
781
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
782
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
783
 
            }
784
 
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
785
 
            PUSHW(ssp, esp, sp_mask, ESP);
786
 
        }
787
 
        PUSHW(ssp, esp, sp_mask, compute_eflags());
788
 
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
789
 
        PUSHW(ssp, esp, sp_mask, old_eip);
790
 
        if (has_error_code) {
791
 
            PUSHW(ssp, esp, sp_mask, error_code);
792
 
        }
793
 
    }
794
 
 
795
 
    if (new_stack) {
796
 
        if (env->eflags & VM_MASK) {
797
 
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
798
 
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
799
 
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
800
 
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
801
 
        }
802
 
        ss = (ss & ~3) | dpl;
803
 
        cpu_x86_load_seg_cache(env, R_SS, ss,
804
 
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
805
 
    }
806
 
    SET_ESP(esp, sp_mask);
807
 
 
808
 
    selector = (selector & ~3) | dpl;
809
 
    cpu_x86_load_seg_cache(env, R_CS, selector,
810
 
                   get_seg_base(e1, e2),
811
 
                   get_seg_limit(e1, e2),
812
 
                   e2);
813
 
    cpu_x86_set_cpl(env, dpl);
814
 
    env->eip = offset;
815
 
 
816
 
    /* interrupt gate clear IF mask */
817
 
    if ((type & 1) == 0) {
818
 
        env->eflags &= ~IF_MASK;
819
 
    }
820
 
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
821
 
}
822
 
 
823
 
#ifdef TARGET_X86_64
824
 
 
825
 
#define PUSHQ(sp, val)\
826
 
{\
827
 
    sp -= 8;\
828
 
    stq_kernel(sp, (val));\
829
 
}
830
 
 
831
 
#define POPQ(sp, val)\
832
 
{\
833
 
    val = ldq_kernel(sp);\
834
 
    sp += 8;\
835
 
}
836
 
 
837
 
static inline target_ulong get_rsp_from_tss(int level)
838
 
{
839
 
    int index;
840
 
 
841
 
#if 0
842
 
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
843
 
           env->tr.base, env->tr.limit);
844
 
#endif
845
 
 
846
 
    if (!(env->tr.flags & DESC_P_MASK))
847
 
        cpu_abort(env, "invalid tss");
848
 
    index = 8 * level + 4;
849
 
    if ((index + 7) > env->tr.limit)
850
 
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
851
 
    return ldq_kernel(env->tr.base + index);
852
 
}
853
 
 
854
 
/* 64 bit interrupt */
855
 
static void do_interrupt64(int intno, int is_int, int error_code,
856
 
                           target_ulong next_eip, int is_hw)
857
 
{
858
 
    SegmentCache *dt;
859
 
    target_ulong ptr;
860
 
    int type, dpl, selector, cpl, ist;
861
 
    int has_error_code, new_stack;
862
 
    uint32_t e1, e2, e3, ss;
863
 
    target_ulong old_eip, esp, offset;
864
 
 
865
 
    has_error_code = 0;
866
 
    if (!is_int && !is_hw) {
867
 
        switch(intno) {
868
 
        case 8:
869
 
        case 10:
870
 
        case 11:
871
 
        case 12:
872
 
        case 13:
873
 
        case 14:
874
 
        case 17:
875
 
            has_error_code = 1;
876
 
            break;
877
 
        }
878
 
    }
879
 
    if (is_int)
880
 
        old_eip = next_eip;
881
 
    else
882
 
        old_eip = env->eip;
883
 
 
884
 
    dt = &env->idt;
885
 
    if (intno * 16 + 15 > dt->limit)
886
 
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
887
 
    ptr = dt->base + intno * 16;
888
 
    e1 = ldl_kernel(ptr);
889
 
    e2 = ldl_kernel(ptr + 4);
890
 
    e3 = ldl_kernel(ptr + 8);
891
 
    /* check gate type */
892
 
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
893
 
    switch(type) {
894
 
    case 14: /* 386 interrupt gate */
895
 
    case 15: /* 386 trap gate */
896
 
        break;
897
 
    default:
898
 
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
899
 
        break;
900
 
    }
901
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
902
 
    cpl = env->hflags & HF_CPL_MASK;
903
 
    /* check privilege if software int */
904
 
    if (is_int && dpl < cpl)
905
 
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
906
 
    /* check valid bit */
907
 
    if (!(e2 & DESC_P_MASK))
908
 
        raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
909
 
    selector = e1 >> 16;
910
 
    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
911
 
    ist = e2 & 7;
912
 
    if ((selector & 0xfffc) == 0)
913
 
        raise_exception_err(EXCP0D_GPF, 0);
914
 
 
915
 
    if (load_segment(&e1, &e2, selector) != 0)
916
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
917
 
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
918
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
919
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
920
 
    if (dpl > cpl)
921
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
922
 
    if (!(e2 & DESC_P_MASK))
923
 
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
924
 
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
925
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
926
 
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
927
 
        /* to inner privilege */
928
 
        if (ist != 0)
929
 
            esp = get_rsp_from_tss(ist + 3);
930
 
        else
931
 
            esp = get_rsp_from_tss(dpl);
932
 
        esp &= ~0xfLL; /* align stack */
933
 
        ss = 0;
934
 
        new_stack = 1;
935
 
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
936
 
        /* to same privilege */
937
 
        if (env->eflags & VM_MASK)
938
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
939
 
        new_stack = 0;
940
 
        if (ist != 0)
941
 
            esp = get_rsp_from_tss(ist + 3);
942
 
        else
943
 
            esp = ESP;
944
 
        esp &= ~0xfLL; /* align stack */
945
 
        dpl = cpl;
946
 
    } else {
947
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
948
 
        new_stack = 0; /* avoid warning */
949
 
        esp = 0; /* avoid warning */
950
 
    }
951
 
 
952
 
    PUSHQ(esp, env->segs[R_SS].selector);
953
 
    PUSHQ(esp, ESP);
954
 
    PUSHQ(esp, compute_eflags());
955
 
    PUSHQ(esp, env->segs[R_CS].selector);
956
 
    PUSHQ(esp, old_eip);
957
 
    if (has_error_code) {
958
 
        PUSHQ(esp, error_code);
959
 
    }
960
 
 
961
 
    if (new_stack) {
962
 
        ss = 0 | dpl;
963
 
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
964
 
    }
965
 
    ESP = esp;
966
 
 
967
 
    selector = (selector & ~3) | dpl;
968
 
    cpu_x86_load_seg_cache(env, R_CS, selector,
969
 
                   get_seg_base(e1, e2),
970
 
                   get_seg_limit(e1, e2),
971
 
                   e2);
972
 
    cpu_x86_set_cpl(env, dpl);
973
 
    env->eip = offset;
974
 
 
975
 
    /* interrupt gate clear IF mask */
976
 
    if ((type & 1) == 0) {
977
 
        env->eflags &= ~IF_MASK;
978
 
    }
979
 
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
980
 
}
981
 
#endif
982
 
 
983
 
#if defined(CONFIG_USER_ONLY)
984
 
void helper_syscall(int next_eip_addend)
985
 
{
986
 
    env->exception_index = EXCP_SYSCALL;
987
 
    env->exception_next_eip = env->eip + next_eip_addend;
988
 
    cpu_loop_exit();
989
 
}
990
 
#else
991
 
void helper_syscall(int next_eip_addend)
992
 
{
993
 
    int selector;
994
 
 
995
 
    if (!(env->efer & MSR_EFER_SCE)) {
996
 
        raise_exception_err(EXCP06_ILLOP, 0);
997
 
    }
998
 
    selector = (env->star >> 32) & 0xffff;
999
 
#ifdef TARGET_X86_64
1000
 
    if (env->hflags & HF_LMA_MASK) {
1001
 
        int code64;
1002
 
 
1003
 
        ECX = env->eip + next_eip_addend;
1004
 
        env->regs[11] = compute_eflags();
1005
 
 
1006
 
        code64 = env->hflags & HF_CS64_MASK;
1007
 
 
1008
 
        cpu_x86_set_cpl(env, 0);
1009
 
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1010
 
                           0, 0xffffffff,
1011
 
                               DESC_G_MASK | DESC_P_MASK |
1012
 
                               DESC_S_MASK |
1013
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1014
 
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1015
 
                               0, 0xffffffff,
1016
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1017
 
                               DESC_S_MASK |
1018
 
                               DESC_W_MASK | DESC_A_MASK);
1019
 
        env->eflags &= ~env->fmask;
1020
 
        load_eflags(env->eflags, 0);
1021
 
        if (code64)
1022
 
            env->eip = env->lstar;
1023
 
        else
1024
 
            env->eip = env->cstar;
1025
 
    } else
1026
 
#endif
1027
 
    {
1028
 
        ECX = (uint32_t)(env->eip + next_eip_addend);
1029
 
 
1030
 
        cpu_x86_set_cpl(env, 0);
1031
 
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1032
 
                           0, 0xffffffff,
1033
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1034
 
                               DESC_S_MASK |
1035
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1036
 
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1037
 
                               0, 0xffffffff,
1038
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1039
 
                               DESC_S_MASK |
1040
 
                               DESC_W_MASK | DESC_A_MASK);
1041
 
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1042
 
        env->eip = (uint32_t)env->star;
1043
 
    }
1044
 
}
1045
 
#endif
1046
 
 
1047
 
void helper_sysret(int dflag)
1048
 
{
1049
 
    int cpl, selector;
1050
 
 
1051
 
    if (!(env->efer & MSR_EFER_SCE)) {
1052
 
        raise_exception_err(EXCP06_ILLOP, 0);
1053
 
    }
1054
 
    cpl = env->hflags & HF_CPL_MASK;
1055
 
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1056
 
        raise_exception_err(EXCP0D_GPF, 0);
1057
 
    }
1058
 
    selector = (env->star >> 48) & 0xffff;
1059
 
#ifdef TARGET_X86_64
1060
 
    if (env->hflags & HF_LMA_MASK) {
1061
 
        if (dflag == 2) {
1062
 
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1063
 
                                   0, 0xffffffff,
1064
 
                                   DESC_G_MASK | DESC_P_MASK |
1065
 
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1066
 
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1067
 
                                   DESC_L_MASK);
1068
 
            env->eip = ECX;
1069
 
        } else {
1070
 
            cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1071
 
                                   0, 0xffffffff,
1072
 
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1073
 
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1074
 
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1075
 
            env->eip = (uint32_t)ECX;
1076
 
        }
1077
 
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1078
 
                               0, 0xffffffff,
1079
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1080
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1081
 
                               DESC_W_MASK | DESC_A_MASK);
1082
 
        load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1083
 
                    IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1084
 
        cpu_x86_set_cpl(env, 3);
1085
 
    } else
1086
 
#endif
1087
 
    {
1088
 
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1089
 
                               0, 0xffffffff,
1090
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1091
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1092
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1093
 
        env->eip = (uint32_t)ECX;
1094
 
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1095
 
                               0, 0xffffffff,
1096
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1097
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1098
 
                               DESC_W_MASK | DESC_A_MASK);
1099
 
        env->eflags |= IF_MASK;
1100
 
        cpu_x86_set_cpl(env, 3);
1101
 
    }
1102
 
#ifdef USE_KQEMU
1103
 
    if (kqemu_is_ok(env)) {
1104
 
        if (env->hflags & HF_LMA_MASK)
1105
 
            CC_OP = CC_OP_EFLAGS;
1106
 
        env->exception_index = -1;
1107
 
        cpu_loop_exit();
1108
 
    }
1109
 
#endif
1110
 
}
1111
 
 
1112
 
/* real mode interrupt */
1113
 
static void do_interrupt_real(int intno, int is_int, int error_code,
1114
 
                              unsigned int next_eip)
1115
 
{
1116
 
    SegmentCache *dt;
1117
 
    target_ulong ptr, ssp;
1118
 
    int selector;
1119
 
    uint32_t offset, esp;
1120
 
    uint32_t old_cs, old_eip;
1121
 
 
1122
 
    /* real mode (simpler !) */
1123
 
    dt = &env->idt;
1124
 
    if (intno * 4 + 3 > dt->limit)
1125
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1126
 
    ptr = dt->base + intno * 4;
1127
 
    offset = lduw_kernel(ptr);
1128
 
    selector = lduw_kernel(ptr + 2);
1129
 
    esp = ESP;
1130
 
    ssp = env->segs[R_SS].base;
1131
 
    if (is_int)
1132
 
        old_eip = next_eip;
1133
 
    else
1134
 
        old_eip = env->eip;
1135
 
    old_cs = env->segs[R_CS].selector;
1136
 
    /* XXX: use SS segment size ? */
1137
 
    PUSHW(ssp, esp, 0xffff, compute_eflags());
1138
 
    PUSHW(ssp, esp, 0xffff, old_cs);
1139
 
    PUSHW(ssp, esp, 0xffff, old_eip);
1140
 
 
1141
 
    /* update processor state */
1142
 
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1143
 
    env->eip = offset;
1144
 
    env->segs[R_CS].selector = selector;
1145
 
    env->segs[R_CS].base = (selector << 4);
1146
 
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1147
 
}
1148
 
 
1149
 
/* fake user mode interrupt */
1150
 
void do_interrupt_user(int intno, int is_int, int error_code,
1151
 
                       target_ulong next_eip)
1152
 
{
1153
 
    SegmentCache *dt;
1154
 
    target_ulong ptr;
1155
 
    int dpl, cpl, shift;
1156
 
    uint32_t e2;
1157
 
 
1158
 
    dt = &env->idt;
1159
 
    if (env->hflags & HF_LMA_MASK) {
1160
 
        shift = 4;
1161
 
    } else {
1162
 
        shift = 3;
1163
 
    }
1164
 
    ptr = dt->base + (intno << shift);
1165
 
    e2 = ldl_kernel(ptr + 4);
1166
 
 
1167
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1168
 
    cpl = env->hflags & HF_CPL_MASK;
1169
 
    /* check privilege if software int */
1170
 
    if (is_int && dpl < cpl)
1171
 
        raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1172
 
 
1173
 
    /* Since we emulate only user space, we cannot do more than
1174
 
       exiting the emulation with the suitable exception and error
1175
 
       code */
1176
 
    if (is_int)
1177
 
        EIP = next_eip;
1178
 
}
1179
 
 
1180
 
/*
1181
 
 * Begin execution of an interruption. is_int is TRUE if coming from
1182
 
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1183
 
 * instruction. It is only relevant if is_int is TRUE.
1184
 
 */
1185
 
void do_interrupt(int intno, int is_int, int error_code,
1186
 
                  target_ulong next_eip, int is_hw)
1187
 
{
1188
 
    if (loglevel & CPU_LOG_INT) {
1189
 
        if ((env->cr[0] & CR0_PE_MASK)) {
1190
 
            static int count;
1191
 
            fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1192
 
                    count, intno, error_code, is_int,
1193
 
                    env->hflags & HF_CPL_MASK,
1194
 
                    env->segs[R_CS].selector, EIP,
1195
 
                    (int)env->segs[R_CS].base + EIP,
1196
 
                    env->segs[R_SS].selector, ESP);
1197
 
            if (intno == 0x0e) {
1198
 
                fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1199
 
            } else {
1200
 
                fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1201
 
            }
1202
 
            fprintf(logfile, "\n");
1203
 
            cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1204
 
#if 0
1205
 
            {
1206
 
                int i;
1207
 
                uint8_t *ptr;
1208
 
                fprintf(logfile, "       code=");
1209
 
                ptr = env->segs[R_CS].base + env->eip;
1210
 
                for(i = 0; i < 16; i++) {
1211
 
                    fprintf(logfile, " %02x", ldub(ptr + i));
1212
 
                }
1213
 
                fprintf(logfile, "\n");
1214
 
            }
1215
 
#endif
1216
 
            count++;
1217
 
        }
1218
 
    }
1219
 
    if (env->cr[0] & CR0_PE_MASK) {
1220
 
#if TARGET_X86_64
1221
 
        if (env->hflags & HF_LMA_MASK) {
1222
 
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1223
 
        } else
1224
 
#endif
1225
 
        {
1226
 
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1227
 
        }
1228
 
    } else {
1229
 
        do_interrupt_real(intno, is_int, error_code, next_eip);
1230
 
    }
1231
 
}
1232
 
 
1233
 
/*
1234
 
 * Check nested exceptions and change to double or triple fault if
1235
 
 * needed. It should only be called, if this is not an interrupt.
1236
 
 * Returns the new exception number.
1237
 
 */
1238
 
static int check_exception(int intno, int *error_code)
1239
 
{
1240
 
    int first_contributory = env->old_exception == 0 ||
1241
 
                              (env->old_exception >= 10 &&
1242
 
                               env->old_exception <= 13);
1243
 
    int second_contributory = intno == 0 ||
1244
 
                               (intno >= 10 && intno <= 13);
1245
 
 
1246
 
    if (loglevel & CPU_LOG_INT)
1247
 
        fprintf(logfile, "check_exception old: 0x%x new 0x%x\n",
1248
 
                env->old_exception, intno);
1249
 
 
1250
 
    if (env->old_exception == EXCP08_DBLE)
1251
 
        cpu_abort(env, "triple fault");
1252
 
 
1253
 
    if ((first_contributory && second_contributory)
1254
 
        || (env->old_exception == EXCP0E_PAGE &&
1255
 
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1256
 
        intno = EXCP08_DBLE;
1257
 
        *error_code = 0;
1258
 
    }
1259
 
 
1260
 
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1261
 
        (intno == EXCP08_DBLE))
1262
 
        env->old_exception = intno;
1263
 
 
1264
 
    return intno;
1265
 
}
1266
 
 
1267
 
/*
1268
 
 * Signal an interruption. It is executed in the main CPU loop.
1269
 
 * is_int is TRUE if coming from the int instruction. next_eip is the
1270
 
 * EIP value AFTER the interrupt instruction. It is only relevant if
1271
 
 * is_int is TRUE.
1272
 
 */
1273
 
void raise_interrupt(int intno, int is_int, int error_code,
1274
 
                     int next_eip_addend)
1275
 
{
1276
 
    if (!is_int) {
1277
 
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1278
 
        intno = check_exception(intno, &error_code);
1279
 
    } else {
1280
 
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1281
 
    }
1282
 
 
1283
 
    env->exception_index = intno;
1284
 
    env->error_code = error_code;
1285
 
    env->exception_is_int = is_int;
1286
 
    env->exception_next_eip = env->eip + next_eip_addend;
1287
 
    cpu_loop_exit();
1288
 
}
1289
 
 
1290
 
/* shortcuts to generate exceptions */
1291
 
 
1292
 
void (raise_exception_err)(int exception_index, int error_code)
1293
 
{
1294
 
    raise_interrupt(exception_index, 0, error_code, 0);
1295
 
}
1296
 
 
1297
 
void raise_exception(int exception_index)
1298
 
{
1299
 
    raise_interrupt(exception_index, 0, 0, 0);
1300
 
}
1301
 
 
1302
 
/* SMM support */
1303
 
 
1304
 
#if defined(CONFIG_USER_ONLY)
1305
 
 
1306
 
void do_smm_enter(void)
1307
 
{
1308
 
}
1309
 
 
1310
 
void helper_rsm(void)
1311
 
{
1312
 
}
1313
 
 
1314
 
#else
1315
 
 
1316
 
#ifdef TARGET_X86_64
1317
 
#define SMM_REVISION_ID 0x00020064
1318
 
#else
1319
 
#define SMM_REVISION_ID 0x00020000
1320
 
#endif
1321
 
 
1322
 
void do_smm_enter(void)
1323
 
{
1324
 
    target_ulong sm_state;
1325
 
    SegmentCache *dt;
1326
 
    int i, offset;
1327
 
 
1328
 
    if (loglevel & CPU_LOG_INT) {
1329
 
        fprintf(logfile, "SMM: enter\n");
1330
 
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1331
 
    }
1332
 
 
1333
 
    env->hflags |= HF_SMM_MASK;
1334
 
    cpu_smm_update(env);
1335
 
 
1336
 
    sm_state = env->smbase + 0x8000;
1337
 
 
1338
 
#ifdef TARGET_X86_64
1339
 
    for(i = 0; i < 6; i++) {
1340
 
        dt = &env->segs[i];
1341
 
        offset = 0x7e00 + i * 16;
1342
 
        stw_phys(sm_state + offset, dt->selector);
1343
 
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1344
 
        stl_phys(sm_state + offset + 4, dt->limit);
1345
 
        stq_phys(sm_state + offset + 8, dt->base);
1346
 
    }
1347
 
 
1348
 
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1349
 
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1350
 
 
1351
 
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1352
 
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1353
 
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1354
 
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1355
 
 
1356
 
    stq_phys(sm_state + 0x7e88, env->idt.base);
1357
 
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1358
 
 
1359
 
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1360
 
    stq_phys(sm_state + 0x7e98, env->tr.base);
1361
 
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1362
 
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1363
 
 
1364
 
    stq_phys(sm_state + 0x7ed0, env->efer);
1365
 
 
1366
 
    stq_phys(sm_state + 0x7ff8, EAX);
1367
 
    stq_phys(sm_state + 0x7ff0, ECX);
1368
 
    stq_phys(sm_state + 0x7fe8, EDX);
1369
 
    stq_phys(sm_state + 0x7fe0, EBX);
1370
 
    stq_phys(sm_state + 0x7fd8, ESP);
1371
 
    stq_phys(sm_state + 0x7fd0, EBP);
1372
 
    stq_phys(sm_state + 0x7fc8, ESI);
1373
 
    stq_phys(sm_state + 0x7fc0, EDI);
1374
 
    for(i = 8; i < 16; i++)
1375
 
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1376
 
    stq_phys(sm_state + 0x7f78, env->eip);
1377
 
    stl_phys(sm_state + 0x7f70, compute_eflags());
1378
 
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1379
 
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1380
 
 
1381
 
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1382
 
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1383
 
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1384
 
 
1385
 
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1386
 
    stl_phys(sm_state + 0x7f00, env->smbase);
1387
 
#else
1388
 
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1389
 
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1390
 
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1391
 
    stl_phys(sm_state + 0x7ff0, env->eip);
1392
 
    stl_phys(sm_state + 0x7fec, EDI);
1393
 
    stl_phys(sm_state + 0x7fe8, ESI);
1394
 
    stl_phys(sm_state + 0x7fe4, EBP);
1395
 
    stl_phys(sm_state + 0x7fe0, ESP);
1396
 
    stl_phys(sm_state + 0x7fdc, EBX);
1397
 
    stl_phys(sm_state + 0x7fd8, EDX);
1398
 
    stl_phys(sm_state + 0x7fd4, ECX);
1399
 
    stl_phys(sm_state + 0x7fd0, EAX);
1400
 
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1401
 
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1402
 
 
1403
 
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1404
 
    stl_phys(sm_state + 0x7f64, env->tr.base);
1405
 
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1406
 
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1407
 
 
1408
 
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1409
 
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1410
 
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1411
 
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1412
 
 
1413
 
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1414
 
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1415
 
 
1416
 
    stl_phys(sm_state + 0x7f58, env->idt.base);
1417
 
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1418
 
 
1419
 
    for(i = 0; i < 6; i++) {
1420
 
        dt = &env->segs[i];
1421
 
        if (i < 3)
1422
 
            offset = 0x7f84 + i * 12;
1423
 
        else
1424
 
            offset = 0x7f2c + (i - 3) * 12;
1425
 
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1426
 
        stl_phys(sm_state + offset + 8, dt->base);
1427
 
        stl_phys(sm_state + offset + 4, dt->limit);
1428
 
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1429
 
    }
1430
 
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1431
 
 
1432
 
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1433
 
    stl_phys(sm_state + 0x7ef8, env->smbase);
1434
 
#endif
1435
 
    /* init SMM cpu state */
1436
 
 
1437
 
#ifdef TARGET_X86_64
1438
 
    cpu_load_efer(env, 0);
1439
 
#endif
1440
 
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1441
 
    env->eip = 0x00008000;
1442
 
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1443
 
                           0xffffffff, 0);
1444
 
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1445
 
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1446
 
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1447
 
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1448
 
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1449
 
 
1450
 
    cpu_x86_update_cr0(env,
1451
 
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1452
 
    cpu_x86_update_cr4(env, 0);
1453
 
    env->dr[7] = 0x00000400;
1454
 
    CC_OP = CC_OP_EFLAGS;
1455
 
}
1456
 
 
1457
 
void helper_rsm(void)
1458
 
{
1459
 
    target_ulong sm_state;
1460
 
    int i, offset;
1461
 
    uint32_t val;
1462
 
 
1463
 
    sm_state = env->smbase + 0x8000;
1464
 
#ifdef TARGET_X86_64
1465
 
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1466
 
 
1467
 
    for(i = 0; i < 6; i++) {
1468
 
        offset = 0x7e00 + i * 16;
1469
 
        cpu_x86_load_seg_cache(env, i,
1470
 
                               lduw_phys(sm_state + offset),
1471
 
                               ldq_phys(sm_state + offset + 8),
1472
 
                               ldl_phys(sm_state + offset + 4),
1473
 
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1474
 
    }
1475
 
 
1476
 
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1477
 
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1478
 
 
1479
 
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1480
 
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1481
 
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1482
 
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1483
 
 
1484
 
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1485
 
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1486
 
 
1487
 
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1488
 
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1489
 
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1490
 
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1491
 
 
1492
 
    EAX = ldq_phys(sm_state + 0x7ff8);
1493
 
    ECX = ldq_phys(sm_state + 0x7ff0);
1494
 
    EDX = ldq_phys(sm_state + 0x7fe8);
1495
 
    EBX = ldq_phys(sm_state + 0x7fe0);
1496
 
    ESP = ldq_phys(sm_state + 0x7fd8);
1497
 
    EBP = ldq_phys(sm_state + 0x7fd0);
1498
 
    ESI = ldq_phys(sm_state + 0x7fc8);
1499
 
    EDI = ldq_phys(sm_state + 0x7fc0);
1500
 
    for(i = 8; i < 16; i++)
1501
 
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1502
 
    env->eip = ldq_phys(sm_state + 0x7f78);
1503
 
    load_eflags(ldl_phys(sm_state + 0x7f70),
1504
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1505
 
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1506
 
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1507
 
 
1508
 
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1509
 
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1510
 
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1511
 
 
1512
 
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1513
 
    if (val & 0x20000) {
1514
 
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1515
 
    }
1516
 
#else
1517
 
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1518
 
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1519
 
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1520
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1521
 
    env->eip = ldl_phys(sm_state + 0x7ff0);
1522
 
    EDI = ldl_phys(sm_state + 0x7fec);
1523
 
    ESI = ldl_phys(sm_state + 0x7fe8);
1524
 
    EBP = ldl_phys(sm_state + 0x7fe4);
1525
 
    ESP = ldl_phys(sm_state + 0x7fe0);
1526
 
    EBX = ldl_phys(sm_state + 0x7fdc);
1527
 
    EDX = ldl_phys(sm_state + 0x7fd8);
1528
 
    ECX = ldl_phys(sm_state + 0x7fd4);
1529
 
    EAX = ldl_phys(sm_state + 0x7fd0);
1530
 
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1531
 
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1532
 
 
1533
 
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1534
 
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1535
 
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1536
 
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1537
 
 
1538
 
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1539
 
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1540
 
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1541
 
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1542
 
 
1543
 
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1544
 
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1545
 
 
1546
 
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1547
 
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1548
 
 
1549
 
    for(i = 0; i < 6; i++) {
1550
 
        if (i < 3)
1551
 
            offset = 0x7f84 + i * 12;
1552
 
        else
1553
 
            offset = 0x7f2c + (i - 3) * 12;
1554
 
        cpu_x86_load_seg_cache(env, i,
1555
 
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1556
 
                               ldl_phys(sm_state + offset + 8),
1557
 
                               ldl_phys(sm_state + offset + 4),
1558
 
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1559
 
    }
1560
 
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1561
 
 
1562
 
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1563
 
    if (val & 0x20000) {
1564
 
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1565
 
    }
1566
 
#endif
1567
 
    CC_OP = CC_OP_EFLAGS;
1568
 
    env->hflags &= ~HF_SMM_MASK;
1569
 
    cpu_smm_update(env);
1570
 
 
1571
 
    if (loglevel & CPU_LOG_INT) {
1572
 
        fprintf(logfile, "SMM: after RSM\n");
1573
 
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1574
 
    }
1575
 
}
1576
 
 
1577
 
#endif /* !CONFIG_USER_ONLY */
1578
 
 
1579
 
 
1580
 
/* division, flags are undefined */
1581
 
 
1582
 
void helper_divb_AL(target_ulong t0)
1583
 
{
1584
 
    unsigned int num, den, q, r;
1585
 
 
1586
 
    num = (EAX & 0xffff);
1587
 
    den = (t0 & 0xff);
1588
 
    if (den == 0) {
1589
 
        raise_exception(EXCP00_DIVZ);
1590
 
    }
1591
 
    q = (num / den);
1592
 
    if (q > 0xff)
1593
 
        raise_exception(EXCP00_DIVZ);
1594
 
    q &= 0xff;
1595
 
    r = (num % den) & 0xff;
1596
 
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1597
 
}
1598
 
 
1599
 
void helper_idivb_AL(target_ulong t0)
1600
 
{
1601
 
    int num, den, q, r;
1602
 
 
1603
 
    num = (int16_t)EAX;
1604
 
    den = (int8_t)t0;
1605
 
    if (den == 0) {
1606
 
        raise_exception(EXCP00_DIVZ);
1607
 
    }
1608
 
    q = (num / den);
1609
 
    if (q != (int8_t)q)
1610
 
        raise_exception(EXCP00_DIVZ);
1611
 
    q &= 0xff;
1612
 
    r = (num % den) & 0xff;
1613
 
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1614
 
}
1615
 
 
1616
 
void helper_divw_AX(target_ulong t0)
1617
 
{
1618
 
    unsigned int num, den, q, r;
1619
 
 
1620
 
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1621
 
    den = (t0 & 0xffff);
1622
 
    if (den == 0) {
1623
 
        raise_exception(EXCP00_DIVZ);
1624
 
    }
1625
 
    q = (num / den);
1626
 
    if (q > 0xffff)
1627
 
        raise_exception(EXCP00_DIVZ);
1628
 
    q &= 0xffff;
1629
 
    r = (num % den) & 0xffff;
1630
 
    EAX = (EAX & ~0xffff) | q;
1631
 
    EDX = (EDX & ~0xffff) | r;
1632
 
}
1633
 
 
1634
 
void helper_idivw_AX(target_ulong t0)
1635
 
{
1636
 
    int num, den, q, r;
1637
 
 
1638
 
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1639
 
    den = (int16_t)t0;
1640
 
    if (den == 0) {
1641
 
        raise_exception(EXCP00_DIVZ);
1642
 
    }
1643
 
    q = (num / den);
1644
 
    if (q != (int16_t)q)
1645
 
        raise_exception(EXCP00_DIVZ);
1646
 
    q &= 0xffff;
1647
 
    r = (num % den) & 0xffff;
1648
 
    EAX = (EAX & ~0xffff) | q;
1649
 
    EDX = (EDX & ~0xffff) | r;
1650
 
}
1651
 
 
1652
 
void helper_divl_EAX(target_ulong t0)
1653
 
{
1654
 
    unsigned int den, r;
1655
 
    uint64_t num, q;
1656
 
 
1657
 
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1658
 
    den = t0;
1659
 
    if (den == 0) {
1660
 
        raise_exception(EXCP00_DIVZ);
1661
 
    }
1662
 
    q = (num / den);
1663
 
    r = (num % den);
1664
 
    if (q > 0xffffffff)
1665
 
        raise_exception(EXCP00_DIVZ);
1666
 
    EAX = (uint32_t)q;
1667
 
    EDX = (uint32_t)r;
1668
 
}
1669
 
 
1670
 
void helper_idivl_EAX(target_ulong t0)
1671
 
{
1672
 
    int den, r;
1673
 
    int64_t num, q;
1674
 
 
1675
 
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1676
 
    den = t0;
1677
 
    if (den == 0) {
1678
 
        raise_exception(EXCP00_DIVZ);
1679
 
    }
1680
 
    q = (num / den);
1681
 
    r = (num % den);
1682
 
    if (q != (int32_t)q)
1683
 
        raise_exception(EXCP00_DIVZ);
1684
 
    EAX = (uint32_t)q;
1685
 
    EDX = (uint32_t)r;
1686
 
}
1687
 
 
1688
 
/* bcd */
1689
 
 
1690
 
/* XXX: exception */
1691
 
void helper_aam(int base)
1692
 
{
1693
 
    int al, ah;
1694
 
    al = EAX & 0xff;
1695
 
    ah = al / base;
1696
 
    al = al % base;
1697
 
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1698
 
    CC_DST = al;
1699
 
}
1700
 
 
1701
 
void helper_aad(int base)
1702
 
{
1703
 
    int al, ah;
1704
 
    al = EAX & 0xff;
1705
 
    ah = (EAX >> 8) & 0xff;
1706
 
    al = ((ah * base) + al) & 0xff;
1707
 
    EAX = (EAX & ~0xffff) | al;
1708
 
    CC_DST = al;
1709
 
}
1710
 
 
1711
 
void helper_aaa(void)
1712
 
{
1713
 
    int icarry;
1714
 
    int al, ah, af;
1715
 
    int eflags;
1716
 
 
1717
 
    eflags = cc_table[CC_OP].compute_all();
1718
 
    af = eflags & CC_A;
1719
 
    al = EAX & 0xff;
1720
 
    ah = (EAX >> 8) & 0xff;
1721
 
 
1722
 
    icarry = (al > 0xf9);
1723
 
    if (((al & 0x0f) > 9 ) || af) {
1724
 
        al = (al + 6) & 0x0f;
1725
 
        ah = (ah + 1 + icarry) & 0xff;
1726
 
        eflags |= CC_C | CC_A;
1727
 
    } else {
1728
 
        eflags &= ~(CC_C | CC_A);
1729
 
        al &= 0x0f;
1730
 
    }
1731
 
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1732
 
    CC_SRC = eflags;
1733
 
    FORCE_RET();
1734
 
}
1735
 
 
1736
 
void helper_aas(void)
1737
 
{
1738
 
    int icarry;
1739
 
    int al, ah, af;
1740
 
    int eflags;
1741
 
 
1742
 
    eflags = cc_table[CC_OP].compute_all();
1743
 
    af = eflags & CC_A;
1744
 
    al = EAX & 0xff;
1745
 
    ah = (EAX >> 8) & 0xff;
1746
 
 
1747
 
    icarry = (al < 6);
1748
 
    if (((al & 0x0f) > 9 ) || af) {
1749
 
        al = (al - 6) & 0x0f;
1750
 
        ah = (ah - 1 - icarry) & 0xff;
1751
 
        eflags |= CC_C | CC_A;
1752
 
    } else {
1753
 
        eflags &= ~(CC_C | CC_A);
1754
 
        al &= 0x0f;
1755
 
    }
1756
 
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1757
 
    CC_SRC = eflags;
1758
 
    FORCE_RET();
1759
 
}
1760
 
 
1761
 
void helper_daa(void)
1762
 
{
1763
 
    int al, af, cf;
1764
 
    int eflags;
1765
 
 
1766
 
    eflags = cc_table[CC_OP].compute_all();
1767
 
    cf = eflags & CC_C;
1768
 
    af = eflags & CC_A;
1769
 
    al = EAX & 0xff;
1770
 
 
1771
 
    eflags = 0;
1772
 
    if (((al & 0x0f) > 9 ) || af) {
1773
 
        al = (al + 6) & 0xff;
1774
 
        eflags |= CC_A;
1775
 
    }
1776
 
    if ((al > 0x9f) || cf) {
1777
 
        al = (al + 0x60) & 0xff;
1778
 
        eflags |= CC_C;
1779
 
    }
1780
 
    EAX = (EAX & ~0xff) | al;
1781
 
    /* well, speed is not an issue here, so we compute the flags by hand */
1782
 
    eflags |= (al == 0) << 6; /* zf */
1783
 
    eflags |= parity_table[al]; /* pf */
1784
 
    eflags |= (al & 0x80); /* sf */
1785
 
    CC_SRC = eflags;
1786
 
    FORCE_RET();
1787
 
}
1788
 
 
1789
 
void helper_das(void)
1790
 
{
1791
 
    int al, al1, af, cf;
1792
 
    int eflags;
1793
 
 
1794
 
    eflags = cc_table[CC_OP].compute_all();
1795
 
    cf = eflags & CC_C;
1796
 
    af = eflags & CC_A;
1797
 
    al = EAX & 0xff;
1798
 
 
1799
 
    eflags = 0;
1800
 
    al1 = al;
1801
 
    if (((al & 0x0f) > 9 ) || af) {
1802
 
        eflags |= CC_A;
1803
 
        if (al < 6 || cf)
1804
 
            eflags |= CC_C;
1805
 
        al = (al - 6) & 0xff;
1806
 
    }
1807
 
    if ((al1 > 0x99) || cf) {
1808
 
        al = (al - 0x60) & 0xff;
1809
 
        eflags |= CC_C;
1810
 
    }
1811
 
    EAX = (EAX & ~0xff) | al;
1812
 
    /* well, speed is not an issue here, so we compute the flags by hand */
1813
 
    eflags |= (al == 0) << 6; /* zf */
1814
 
    eflags |= parity_table[al]; /* pf */
1815
 
    eflags |= (al & 0x80); /* sf */
1816
 
    CC_SRC = eflags;
1817
 
    FORCE_RET();
1818
 
}
1819
 
 
1820
 
void helper_into(int next_eip_addend)
1821
 
{
1822
 
    int eflags;
1823
 
    eflags = cc_table[CC_OP].compute_all();
1824
 
    if (eflags & CC_O) {
1825
 
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1826
 
    }
1827
 
}
1828
 
 
1829
 
void helper_cmpxchg8b(target_ulong a0)
1830
 
{
1831
 
    uint64_t d;
1832
 
    int eflags;
1833
 
 
1834
 
    eflags = cc_table[CC_OP].compute_all();
1835
 
    d = ldq(a0);
1836
 
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1837
 
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1838
 
        eflags |= CC_Z;
1839
 
    } else {
1840
 
        EDX = (uint32_t)(d >> 32);
1841
 
        EAX = (uint32_t)d;
1842
 
        eflags &= ~CC_Z;
1843
 
    }
1844
 
    CC_SRC = eflags;
1845
 
}
1846
 
 
1847
 
#ifdef TARGET_X86_64
1848
 
void helper_cmpxchg16b(target_ulong a0)
1849
 
{
1850
 
    uint64_t d0, d1;
1851
 
    int eflags;
1852
 
 
1853
 
    eflags = cc_table[CC_OP].compute_all();
1854
 
    d0 = ldq(a0);
1855
 
    d1 = ldq(a0 + 8);
1856
 
    if (d0 == EAX && d1 == EDX) {
1857
 
        stq(a0, EBX);
1858
 
        stq(a0 + 8, ECX);
1859
 
        eflags |= CC_Z;
1860
 
    } else {
1861
 
        EDX = d1;
1862
 
        EAX = d0;
1863
 
        eflags &= ~CC_Z;
1864
 
    }
1865
 
    CC_SRC = eflags;
1866
 
}
1867
 
#endif
1868
 
 
1869
 
void helper_single_step(void)
1870
 
{
1871
 
    env->dr[6] |= 0x4000;
1872
 
    raise_exception(EXCP01_SSTP);
1873
 
}
1874
 
 
1875
 
void helper_cpuid(void)
1876
 
{
1877
 
    uint32_t index;
1878
 
 
1879
 
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1880
 
    
1881
 
    index = (uint32_t)EAX;
1882
 
    /* test if maximum index reached */
1883
 
    if (index & 0x80000000) {
1884
 
        if (index > env->cpuid_xlevel)
1885
 
            index = env->cpuid_level;
1886
 
    } else {
1887
 
        if (index > env->cpuid_level)
1888
 
            index = env->cpuid_level;
1889
 
    }
1890
 
 
1891
 
    switch(index) {
1892
 
    case 0:
1893
 
        EAX = env->cpuid_level;
1894
 
        EBX = env->cpuid_vendor1;
1895
 
        EDX = env->cpuid_vendor2;
1896
 
        ECX = env->cpuid_vendor3;
1897
 
        break;
1898
 
    case 1:
1899
 
        EAX = env->cpuid_version;
1900
 
        EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1901
 
        ECX = env->cpuid_ext_features;
1902
 
        EDX = env->cpuid_features;
1903
 
        break;
1904
 
    case 2:
1905
 
        /* cache info: needed for Pentium Pro compatibility */
1906
 
        EAX = 1;
1907
 
        EBX = 0;
1908
 
        ECX = 0;
1909
 
        EDX = 0x2c307d;
1910
 
        break;
1911
 
    case 0x80000000:
1912
 
        EAX = env->cpuid_xlevel;
1913
 
        EBX = env->cpuid_vendor1;
1914
 
        EDX = env->cpuid_vendor2;
1915
 
        ECX = env->cpuid_vendor3;
1916
 
        break;
1917
 
    case 0x80000001:
1918
 
        EAX = env->cpuid_features;
1919
 
        EBX = 0;
1920
 
        ECX = env->cpuid_ext3_features;
1921
 
        EDX = env->cpuid_ext2_features;
1922
 
        break;
1923
 
    case 0x80000002:
1924
 
    case 0x80000003:
1925
 
    case 0x80000004:
1926
 
        EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1927
 
        EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1928
 
        ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1929
 
        EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1930
 
        break;
1931
 
    case 0x80000005:
1932
 
        /* cache info (L1 cache) */
1933
 
        EAX = 0x01ff01ff;
1934
 
        EBX = 0x01ff01ff;
1935
 
        ECX = 0x40020140;
1936
 
        EDX = 0x40020140;
1937
 
        break;
1938
 
    case 0x80000006:
1939
 
        /* cache info (L2 cache) */
1940
 
        EAX = 0;
1941
 
        EBX = 0x42004200;
1942
 
        ECX = 0x02008140;
1943
 
        EDX = 0;
1944
 
        break;
1945
 
    case 0x80000008:
1946
 
        /* virtual & phys address size in low 2 bytes. */
1947
 
/* XXX: This value must match the one used in the MMU code. */ 
1948
 
        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
1949
 
            /* 64 bit processor */
1950
 
#if defined(USE_KQEMU)
1951
 
            EAX = 0x00003020;   /* 48 bits virtual, 32 bits physical */
1952
 
#else
1953
 
/* XXX: The physical address space is limited to 42 bits in exec.c. */
1954
 
            EAX = 0x00003028;   /* 48 bits virtual, 40 bits physical */
1955
 
#endif
1956
 
        } else {
1957
 
#if defined(USE_KQEMU)
1958
 
            EAX = 0x00000020;   /* 32 bits physical */
1959
 
#else
1960
 
            EAX = 0x00000024;   /* 36 bits physical */
1961
 
#endif
1962
 
        }
1963
 
        EBX = 0;
1964
 
        ECX = 0;
1965
 
        EDX = 0;
1966
 
        break;
1967
 
    case 0x8000000A:
1968
 
        EAX = 0x00000001;
1969
 
        EBX = 0;
1970
 
        ECX = 0;
1971
 
        EDX = 0;
1972
 
        break;
1973
 
    default:
1974
 
        /* reserved values: zero */
1975
 
        EAX = 0;
1976
 
        EBX = 0;
1977
 
        ECX = 0;
1978
 
        EDX = 0;
1979
 
        break;
1980
 
    }
1981
 
}
1982
 
 
1983
 
void helper_enter_level(int level, int data32, target_ulong t1)
1984
 
{
1985
 
    target_ulong ssp;
1986
 
    uint32_t esp_mask, esp, ebp;
1987
 
 
1988
 
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1989
 
    ssp = env->segs[R_SS].base;
1990
 
    ebp = EBP;
1991
 
    esp = ESP;
1992
 
    if (data32) {
1993
 
        /* 32 bit */
1994
 
        esp -= 4;
1995
 
        while (--level) {
1996
 
            esp -= 4;
1997
 
            ebp -= 4;
1998
 
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1999
 
        }
2000
 
        esp -= 4;
2001
 
        stl(ssp + (esp & esp_mask), t1);
2002
 
    } else {
2003
 
        /* 16 bit */
2004
 
        esp -= 2;
2005
 
        while (--level) {
2006
 
            esp -= 2;
2007
 
            ebp -= 2;
2008
 
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
2009
 
        }
2010
 
        esp -= 2;
2011
 
        stw(ssp + (esp & esp_mask), t1);
2012
 
    }
2013
 
}
2014
 
 
2015
 
#ifdef TARGET_X86_64
2016
 
void helper_enter64_level(int level, int data64, target_ulong t1)
2017
 
{
2018
 
    target_ulong esp, ebp;
2019
 
    ebp = EBP;
2020
 
    esp = ESP;
2021
 
 
2022
 
    if (data64) {
2023
 
        /* 64 bit */
2024
 
        esp -= 8;
2025
 
        while (--level) {
2026
 
            esp -= 8;
2027
 
            ebp -= 8;
2028
 
            stq(esp, ldq(ebp));
2029
 
        }
2030
 
        esp -= 8;
2031
 
        stq(esp, t1);
2032
 
    } else {
2033
 
        /* 16 bit */
2034
 
        esp -= 2;
2035
 
        while (--level) {
2036
 
            esp -= 2;
2037
 
            ebp -= 2;
2038
 
            stw(esp, lduw(ebp));
2039
 
        }
2040
 
        esp -= 2;
2041
 
        stw(esp, t1);
2042
 
    }
2043
 
}
2044
 
#endif
2045
 
 
2046
 
void helper_lldt(int selector)
2047
 
{
2048
 
    SegmentCache *dt;
2049
 
    uint32_t e1, e2;
2050
 
    int index, entry_limit;
2051
 
    target_ulong ptr;
2052
 
 
2053
 
    selector &= 0xffff;
2054
 
    if ((selector & 0xfffc) == 0) {
2055
 
        /* XXX: NULL selector case: invalid LDT */
2056
 
        env->ldt.base = 0;
2057
 
        env->ldt.limit = 0;
2058
 
    } else {
2059
 
        if (selector & 0x4)
2060
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2061
 
        dt = &env->gdt;
2062
 
        index = selector & ~7;
2063
 
#ifdef TARGET_X86_64
2064
 
        if (env->hflags & HF_LMA_MASK)
2065
 
            entry_limit = 15;
2066
 
        else
2067
 
#endif
2068
 
            entry_limit = 7;
2069
 
        if ((index + entry_limit) > dt->limit)
2070
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2071
 
        ptr = dt->base + index;
2072
 
        e1 = ldl_kernel(ptr);
2073
 
        e2 = ldl_kernel(ptr + 4);
2074
 
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2075
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2076
 
        if (!(e2 & DESC_P_MASK))
2077
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2078
 
#ifdef TARGET_X86_64
2079
 
        if (env->hflags & HF_LMA_MASK) {
2080
 
            uint32_t e3;
2081
 
            e3 = ldl_kernel(ptr + 8);
2082
 
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2083
 
            env->ldt.base |= (target_ulong)e3 << 32;
2084
 
        } else
2085
 
#endif
2086
 
        {
2087
 
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2088
 
        }
2089
 
    }
2090
 
    env->ldt.selector = selector;
2091
 
}
2092
 
 
2093
 
void helper_ltr(int selector)
2094
 
{
2095
 
    SegmentCache *dt;
2096
 
    uint32_t e1, e2;
2097
 
    int index, type, entry_limit;
2098
 
    target_ulong ptr;
2099
 
 
2100
 
    selector &= 0xffff;
2101
 
    if ((selector & 0xfffc) == 0) {
2102
 
        /* NULL selector case: invalid TR */
2103
 
        env->tr.base = 0;
2104
 
        env->tr.limit = 0;
2105
 
        env->tr.flags = 0;
2106
 
    } else {
2107
 
        if (selector & 0x4)
2108
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2109
 
        dt = &env->gdt;
2110
 
        index = selector & ~7;
2111
 
#ifdef TARGET_X86_64
2112
 
        if (env->hflags & HF_LMA_MASK)
2113
 
            entry_limit = 15;
2114
 
        else
2115
 
#endif
2116
 
            entry_limit = 7;
2117
 
        if ((index + entry_limit) > dt->limit)
2118
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2119
 
        ptr = dt->base + index;
2120
 
        e1 = ldl_kernel(ptr);
2121
 
        e2 = ldl_kernel(ptr + 4);
2122
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2123
 
        if ((e2 & DESC_S_MASK) ||
2124
 
            (type != 1 && type != 9))
2125
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2126
 
        if (!(e2 & DESC_P_MASK))
2127
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2128
 
#ifdef TARGET_X86_64
2129
 
        if (env->hflags & HF_LMA_MASK) {
2130
 
            uint32_t e3, e4;
2131
 
            e3 = ldl_kernel(ptr + 8);
2132
 
            e4 = ldl_kernel(ptr + 12);
2133
 
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2134
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2135
 
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2136
 
            env->tr.base |= (target_ulong)e3 << 32;
2137
 
        } else
2138
 
#endif
2139
 
        {
2140
 
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2141
 
        }
2142
 
        e2 |= DESC_TSS_BUSY_MASK;
2143
 
        stl_kernel(ptr + 4, e2);
2144
 
    }
2145
 
    env->tr.selector = selector;
2146
 
}
2147
 
 
2148
 
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2149
 
void helper_load_seg(int seg_reg, int selector)
2150
 
{
2151
 
    uint32_t e1, e2;
2152
 
    int cpl, dpl, rpl;
2153
 
    SegmentCache *dt;
2154
 
    int index;
2155
 
    target_ulong ptr;
2156
 
 
2157
 
    selector &= 0xffff;
2158
 
    cpl = env->hflags & HF_CPL_MASK;
2159
 
    if ((selector & 0xfffc) == 0) {
2160
 
        /* null selector case */
2161
 
        if (seg_reg == R_SS
2162
 
#ifdef TARGET_X86_64
2163
 
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2164
 
#endif
2165
 
            )
2166
 
            raise_exception_err(EXCP0D_GPF, 0);
2167
 
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2168
 
    } else {
2169
 
 
2170
 
        if (selector & 0x4)
2171
 
            dt = &env->ldt;
2172
 
        else
2173
 
            dt = &env->gdt;
2174
 
        index = selector & ~7;
2175
 
        if ((index + 7) > dt->limit)
2176
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2177
 
        ptr = dt->base + index;
2178
 
        e1 = ldl_kernel(ptr);
2179
 
        e2 = ldl_kernel(ptr + 4);
2180
 
 
2181
 
        if (!(e2 & DESC_S_MASK))
2182
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2183
 
        rpl = selector & 3;
2184
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2185
 
        if (seg_reg == R_SS) {
2186
 
            /* must be writable segment */
2187
 
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2188
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2189
 
            if (rpl != cpl || dpl != cpl)
2190
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2191
 
        } else {
2192
 
            /* must be readable segment */
2193
 
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2194
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2195
 
 
2196
 
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2197
 
                /* if not conforming code, test rights */
2198
 
                if (dpl < cpl || dpl < rpl)
2199
 
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2200
 
            }
2201
 
        }
2202
 
 
2203
 
        if (!(e2 & DESC_P_MASK)) {
2204
 
            if (seg_reg == R_SS)
2205
 
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2206
 
            else
2207
 
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2208
 
        }
2209
 
 
2210
 
        /* set the access bit if not already set */
2211
 
        if (!(e2 & DESC_A_MASK)) {
2212
 
            e2 |= DESC_A_MASK;
2213
 
            stl_kernel(ptr + 4, e2);
2214
 
        }
2215
 
 
2216
 
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2217
 
                       get_seg_base(e1, e2),
2218
 
                       get_seg_limit(e1, e2),
2219
 
                       e2);
2220
 
#if 0
2221
 
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2222
 
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2223
 
#endif
2224
 
    }
2225
 
}
2226
 
 
2227
 
/* protected mode jump */
2228
 
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2229
 
                           int next_eip_addend)
2230
 
{
2231
 
    int gate_cs, type;
2232
 
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2233
 
    target_ulong next_eip;
2234
 
 
2235
 
    if ((new_cs & 0xfffc) == 0)
2236
 
        raise_exception_err(EXCP0D_GPF, 0);
2237
 
    if (load_segment(&e1, &e2, new_cs) != 0)
2238
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2239
 
    cpl = env->hflags & HF_CPL_MASK;
2240
 
    if (e2 & DESC_S_MASK) {
2241
 
        if (!(e2 & DESC_CS_MASK))
2242
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2243
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2244
 
        if (e2 & DESC_C_MASK) {
2245
 
            /* conforming code segment */
2246
 
            if (dpl > cpl)
2247
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2248
 
        } else {
2249
 
            /* non conforming code segment */
2250
 
            rpl = new_cs & 3;
2251
 
            if (rpl > cpl)
2252
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2253
 
            if (dpl != cpl)
2254
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2255
 
        }
2256
 
        if (!(e2 & DESC_P_MASK))
2257
 
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2258
 
        limit = get_seg_limit(e1, e2);
2259
 
        if (new_eip > limit &&
2260
 
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2261
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2262
 
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2263
 
                       get_seg_base(e1, e2), limit, e2);
2264
 
        EIP = new_eip;
2265
 
    } else {
2266
 
        /* jump to call or task gate */
2267
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2268
 
        rpl = new_cs & 3;
2269
 
        cpl = env->hflags & HF_CPL_MASK;
2270
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2271
 
        switch(type) {
2272
 
        case 1: /* 286 TSS */
2273
 
        case 9: /* 386 TSS */
2274
 
        case 5: /* task gate */
2275
 
            if (dpl < cpl || dpl < rpl)
2276
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2277
 
            next_eip = env->eip + next_eip_addend;
2278
 
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2279
 
            CC_OP = CC_OP_EFLAGS;
2280
 
            break;
2281
 
        case 4: /* 286 call gate */
2282
 
        case 12: /* 386 call gate */
2283
 
            if ((dpl < cpl) || (dpl < rpl))
2284
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2285
 
            if (!(e2 & DESC_P_MASK))
2286
 
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2287
 
            gate_cs = e1 >> 16;
2288
 
            new_eip = (e1 & 0xffff);
2289
 
            if (type == 12)
2290
 
                new_eip |= (e2 & 0xffff0000);
2291
 
            if (load_segment(&e1, &e2, gate_cs) != 0)
2292
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2293
 
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2294
 
            /* must be code segment */
2295
 
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2296
 
                 (DESC_S_MASK | DESC_CS_MASK)))
2297
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2298
 
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2299
 
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2300
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2301
 
            if (!(e2 & DESC_P_MASK))
2302
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2303
 
            limit = get_seg_limit(e1, e2);
2304
 
            if (new_eip > limit)
2305
 
                raise_exception_err(EXCP0D_GPF, 0);
2306
 
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2307
 
                                   get_seg_base(e1, e2), limit, e2);
2308
 
            EIP = new_eip;
2309
 
            break;
2310
 
        default:
2311
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2312
 
            break;
2313
 
        }
2314
 
    }
2315
 
}
2316
 
 
2317
 
/* real mode call */
2318
 
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2319
 
                       int shift, int next_eip)
2320
 
{
2321
 
    int new_eip;
2322
 
    uint32_t esp, esp_mask;
2323
 
    target_ulong ssp;
2324
 
 
2325
 
    new_eip = new_eip1;
2326
 
    esp = ESP;
2327
 
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2328
 
    ssp = env->segs[R_SS].base;
2329
 
    if (shift) {
2330
 
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2331
 
        PUSHL(ssp, esp, esp_mask, next_eip);
2332
 
    } else {
2333
 
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2334
 
        PUSHW(ssp, esp, esp_mask, next_eip);
2335
 
    }
2336
 
 
2337
 
    SET_ESP(esp, esp_mask);
2338
 
    env->eip = new_eip;
2339
 
    env->segs[R_CS].selector = new_cs;
2340
 
    env->segs[R_CS].base = (new_cs << 4);
2341
 
}
2342
 
 
2343
 
/* protected mode call */
2344
 
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2345
 
                            int shift, int next_eip_addend)
2346
 
{
2347
 
    int new_stack, i;
2348
 
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2349
 
    uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
2350
 
    uint32_t val, limit, old_sp_mask;
2351
 
    target_ulong ssp, old_ssp, next_eip;
2352
 
 
2353
 
    next_eip = env->eip + next_eip_addend;
2354
 
#ifdef DEBUG_PCALL
2355
 
    if (loglevel & CPU_LOG_PCALL) {
2356
 
        fprintf(logfile, "lcall %04x:%08x s=%d\n",
2357
 
                new_cs, (uint32_t)new_eip, shift);
2358
 
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2359
 
    }
2360
 
#endif
2361
 
    if ((new_cs & 0xfffc) == 0)
2362
 
        raise_exception_err(EXCP0D_GPF, 0);
2363
 
    if (load_segment(&e1, &e2, new_cs) != 0)
2364
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2365
 
    cpl = env->hflags & HF_CPL_MASK;
2366
 
#ifdef DEBUG_PCALL
2367
 
    if (loglevel & CPU_LOG_PCALL) {
2368
 
        fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
2369
 
    }
2370
 
#endif
2371
 
    if (e2 & DESC_S_MASK) {
2372
 
        if (!(e2 & DESC_CS_MASK))
2373
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2374
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2375
 
        if (e2 & DESC_C_MASK) {
2376
 
            /* conforming code segment */
2377
 
            if (dpl > cpl)
2378
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2379
 
        } else {
2380
 
            /* non conforming code segment */
2381
 
            rpl = new_cs & 3;
2382
 
            if (rpl > cpl)
2383
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2384
 
            if (dpl != cpl)
2385
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2386
 
        }
2387
 
        if (!(e2 & DESC_P_MASK))
2388
 
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2389
 
 
2390
 
#ifdef TARGET_X86_64
2391
 
        /* XXX: check 16/32 bit cases in long mode */
2392
 
        if (shift == 2) {
2393
 
            target_ulong rsp;
2394
 
            /* 64 bit case */
2395
 
            rsp = ESP;
2396
 
            PUSHQ(rsp, env->segs[R_CS].selector);
2397
 
            PUSHQ(rsp, next_eip);
2398
 
            /* from this point, not restartable */
2399
 
            ESP = rsp;
2400
 
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2401
 
                                   get_seg_base(e1, e2),
2402
 
                                   get_seg_limit(e1, e2), e2);
2403
 
            EIP = new_eip;
2404
 
        } else
2405
 
#endif
2406
 
        {
2407
 
            sp = ESP;
2408
 
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2409
 
            ssp = env->segs[R_SS].base;
2410
 
            if (shift) {
2411
 
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2412
 
                PUSHL(ssp, sp, sp_mask, next_eip);
2413
 
            } else {
2414
 
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2415
 
                PUSHW(ssp, sp, sp_mask, next_eip);
2416
 
            }
2417
 
 
2418
 
            limit = get_seg_limit(e1, e2);
2419
 
            if (new_eip > limit)
2420
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2421
 
            /* from this point, not restartable */
2422
 
            SET_ESP(sp, sp_mask);
2423
 
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2424
 
                                   get_seg_base(e1, e2), limit, e2);
2425
 
            EIP = new_eip;
2426
 
        }
2427
 
    } else {
2428
 
        /* check gate type */
2429
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2430
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2431
 
        rpl = new_cs & 3;
2432
 
        switch(type) {
2433
 
        case 1: /* available 286 TSS */
2434
 
        case 9: /* available 386 TSS */
2435
 
        case 5: /* task gate */
2436
 
            if (dpl < cpl || dpl < rpl)
2437
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2438
 
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2439
 
            CC_OP = CC_OP_EFLAGS;
2440
 
            return;
2441
 
        case 4: /* 286 call gate */
2442
 
        case 12: /* 386 call gate */
2443
 
            break;
2444
 
        default:
2445
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2446
 
            break;
2447
 
        }
2448
 
        shift = type >> 3;
2449
 
 
2450
 
        if (dpl < cpl || dpl < rpl)
2451
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2452
 
        /* check valid bit */
2453
 
        if (!(e2 & DESC_P_MASK))
2454
 
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2455
 
        selector = e1 >> 16;
2456
 
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2457
 
        param_count = e2 & 0x1f;
2458
 
        if ((selector & 0xfffc) == 0)
2459
 
            raise_exception_err(EXCP0D_GPF, 0);
2460
 
 
2461
 
        if (load_segment(&e1, &e2, selector) != 0)
2462
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2463
 
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2464
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2465
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2466
 
        if (dpl > cpl)
2467
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2468
 
        if (!(e2 & DESC_P_MASK))
2469
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2470
 
 
2471
 
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2472
 
            /* to inner privilege */
2473
 
            get_ss_esp_from_tss(&ss, &sp, dpl);
2474
 
#ifdef DEBUG_PCALL
2475
 
            if (loglevel & CPU_LOG_PCALL)
2476
 
                fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2477
 
                        ss, sp, param_count, ESP);
2478
 
#endif
2479
 
            if ((ss & 0xfffc) == 0)
2480
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2481
 
            if ((ss & 3) != dpl)
2482
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2483
 
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2484
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2485
 
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2486
 
            if (ss_dpl != dpl)
2487
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2488
 
            if (!(ss_e2 & DESC_S_MASK) ||
2489
 
                (ss_e2 & DESC_CS_MASK) ||
2490
 
                !(ss_e2 & DESC_W_MASK))
2491
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2492
 
            if (!(ss_e2 & DESC_P_MASK))
2493
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2494
 
 
2495
 
            //            push_size = ((param_count * 2) + 8) << shift;
2496
 
 
2497
 
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2498
 
            old_ssp = env->segs[R_SS].base;
2499
 
 
2500
 
            sp_mask = get_sp_mask(ss_e2);
2501
 
            ssp = get_seg_base(ss_e1, ss_e2);
2502
 
            if (shift) {
2503
 
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2504
 
                PUSHL(ssp, sp, sp_mask, ESP);
2505
 
                for(i = param_count - 1; i >= 0; i--) {
2506
 
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2507
 
                    PUSHL(ssp, sp, sp_mask, val);
2508
 
                }
2509
 
            } else {
2510
 
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2511
 
                PUSHW(ssp, sp, sp_mask, ESP);
2512
 
                for(i = param_count - 1; i >= 0; i--) {
2513
 
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2514
 
                    PUSHW(ssp, sp, sp_mask, val);
2515
 
                }
2516
 
            }
2517
 
            new_stack = 1;
2518
 
        } else {
2519
 
            /* to same privilege */
2520
 
            sp = ESP;
2521
 
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2522
 
            ssp = env->segs[R_SS].base;
2523
 
            //            push_size = (4 << shift);
2524
 
            new_stack = 0;
2525
 
        }
2526
 
 
2527
 
        if (shift) {
2528
 
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2529
 
            PUSHL(ssp, sp, sp_mask, next_eip);
2530
 
        } else {
2531
 
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2532
 
            PUSHW(ssp, sp, sp_mask, next_eip);
2533
 
        }
2534
 
 
2535
 
        /* from this point, not restartable */
2536
 
 
2537
 
        if (new_stack) {
2538
 
            ss = (ss & ~3) | dpl;
2539
 
            cpu_x86_load_seg_cache(env, R_SS, ss,
2540
 
                                   ssp,
2541
 
                                   get_seg_limit(ss_e1, ss_e2),
2542
 
                                   ss_e2);
2543
 
        }
2544
 
 
2545
 
        selector = (selector & ~3) | dpl;
2546
 
        cpu_x86_load_seg_cache(env, R_CS, selector,
2547
 
                       get_seg_base(e1, e2),
2548
 
                       get_seg_limit(e1, e2),
2549
 
                       e2);
2550
 
        cpu_x86_set_cpl(env, dpl);
2551
 
        SET_ESP(sp, sp_mask);
2552
 
        EIP = offset;
2553
 
    }
2554
 
#ifdef USE_KQEMU
2555
 
    if (kqemu_is_ok(env)) {
2556
 
        env->exception_index = -1;
2557
 
        cpu_loop_exit();
2558
 
    }
2559
 
#endif
2560
 
}
2561
 
 
2562
 
/* real and vm86 mode iret */
2563
 
void helper_iret_real(int shift)
2564
 
{
2565
 
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2566
 
    target_ulong ssp;
2567
 
    int eflags_mask;
2568
 
 
2569
 
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2570
 
    sp = ESP;
2571
 
    ssp = env->segs[R_SS].base;
2572
 
    if (shift == 1) {
2573
 
        /* 32 bits */
2574
 
        POPL(ssp, sp, sp_mask, new_eip);
2575
 
        POPL(ssp, sp, sp_mask, new_cs);
2576
 
        new_cs &= 0xffff;
2577
 
        POPL(ssp, sp, sp_mask, new_eflags);
2578
 
    } else {
2579
 
        /* 16 bits */
2580
 
        POPW(ssp, sp, sp_mask, new_eip);
2581
 
        POPW(ssp, sp, sp_mask, new_cs);
2582
 
        POPW(ssp, sp, sp_mask, new_eflags);
2583
 
    }
2584
 
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2585
 
    load_seg_vm(R_CS, new_cs);
2586
 
    env->eip = new_eip;
2587
 
    if (env->eflags & VM_MASK)
2588
 
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2589
 
    else
2590
 
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2591
 
    if (shift == 0)
2592
 
        eflags_mask &= 0xffff;
2593
 
    load_eflags(new_eflags, eflags_mask);
2594
 
    env->hflags &= ~HF_NMI_MASK;
2595
 
}
2596
 
 
2597
 
static inline void validate_seg(int seg_reg, int cpl)
2598
 
{
2599
 
    int dpl;
2600
 
    uint32_t e2;
2601
 
 
2602
 
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2603
 
       they may still contain a valid base. I would be interested to
2604
 
       know how a real x86_64 CPU behaves */
2605
 
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2606
 
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2607
 
        return;
2608
 
 
2609
 
    e2 = env->segs[seg_reg].flags;
2610
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2611
 
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2612
 
        /* data or non conforming code segment */
2613
 
        if (dpl < cpl) {
2614
 
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2615
 
        }
2616
 
    }
2617
 
}
2618
 
 
2619
 
/* protected mode iret */
2620
 
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2621
 
{
2622
 
    uint32_t new_cs, new_eflags, new_ss;
2623
 
    uint32_t new_es, new_ds, new_fs, new_gs;
2624
 
    uint32_t e1, e2, ss_e1, ss_e2;
2625
 
    int cpl, dpl, rpl, eflags_mask, iopl;
2626
 
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2627
 
 
2628
 
#ifdef TARGET_X86_64
2629
 
    if (shift == 2)
2630
 
        sp_mask = -1;
2631
 
    else
2632
 
#endif
2633
 
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2634
 
    sp = ESP;
2635
 
    ssp = env->segs[R_SS].base;
2636
 
    new_eflags = 0; /* avoid warning */
2637
 
#ifdef TARGET_X86_64
2638
 
    if (shift == 2) {
2639
 
        POPQ(sp, new_eip);
2640
 
        POPQ(sp, new_cs);
2641
 
        new_cs &= 0xffff;
2642
 
        if (is_iret) {
2643
 
            POPQ(sp, new_eflags);
2644
 
        }
2645
 
    } else
2646
 
#endif
2647
 
    if (shift == 1) {
2648
 
        /* 32 bits */
2649
 
        POPL(ssp, sp, sp_mask, new_eip);
2650
 
        POPL(ssp, sp, sp_mask, new_cs);
2651
 
        new_cs &= 0xffff;
2652
 
        if (is_iret) {
2653
 
            POPL(ssp, sp, sp_mask, new_eflags);
2654
 
            if (new_eflags & VM_MASK)
2655
 
                goto return_to_vm86;
2656
 
        }
2657
 
    } else {
2658
 
        /* 16 bits */
2659
 
        POPW(ssp, sp, sp_mask, new_eip);
2660
 
        POPW(ssp, sp, sp_mask, new_cs);
2661
 
        if (is_iret)
2662
 
            POPW(ssp, sp, sp_mask, new_eflags);
2663
 
    }
2664
 
#ifdef DEBUG_PCALL
2665
 
    if (loglevel & CPU_LOG_PCALL) {
2666
 
        fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2667
 
                new_cs, new_eip, shift, addend);
2668
 
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2669
 
    }
2670
 
#endif
2671
 
    if ((new_cs & 0xfffc) == 0)
2672
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2673
 
    if (load_segment(&e1, &e2, new_cs) != 0)
2674
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2675
 
    if (!(e2 & DESC_S_MASK) ||
2676
 
        !(e2 & DESC_CS_MASK))
2677
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2678
 
    cpl = env->hflags & HF_CPL_MASK;
2679
 
    rpl = new_cs & 3;
2680
 
    if (rpl < cpl)
2681
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2682
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2683
 
    if (e2 & DESC_C_MASK) {
2684
 
        if (dpl > rpl)
2685
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2686
 
    } else {
2687
 
        if (dpl != rpl)
2688
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2689
 
    }
2690
 
    if (!(e2 & DESC_P_MASK))
2691
 
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2692
 
 
2693
 
    sp += addend;
2694
 
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2695
 
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2696
 
        /* return to same privilege level */
2697
 
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2698
 
                       get_seg_base(e1, e2),
2699
 
                       get_seg_limit(e1, e2),
2700
 
                       e2);
2701
 
    } else {
2702
 
        /* return to different privilege level */
2703
 
#ifdef TARGET_X86_64
2704
 
        if (shift == 2) {
2705
 
            POPQ(sp, new_esp);
2706
 
            POPQ(sp, new_ss);
2707
 
            new_ss &= 0xffff;
2708
 
        } else
2709
 
#endif
2710
 
        if (shift == 1) {
2711
 
            /* 32 bits */
2712
 
            POPL(ssp, sp, sp_mask, new_esp);
2713
 
            POPL(ssp, sp, sp_mask, new_ss);
2714
 
            new_ss &= 0xffff;
2715
 
        } else {
2716
 
            /* 16 bits */
2717
 
            POPW(ssp, sp, sp_mask, new_esp);
2718
 
            POPW(ssp, sp, sp_mask, new_ss);
2719
 
        }
2720
 
#ifdef DEBUG_PCALL
2721
 
        if (loglevel & CPU_LOG_PCALL) {
2722
 
            fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
2723
 
                    new_ss, new_esp);
2724
 
        }
2725
 
#endif
2726
 
        if ((new_ss & 0xfffc) == 0) {
2727
 
#ifdef TARGET_X86_64
2728
 
            /* NULL ss is allowed in long mode if cpl != 3*/
2729
 
            /* XXX: test CS64 ? */
2730
 
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2731
 
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2732
 
                                       0, 0xffffffff,
2733
 
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2734
 
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2735
 
                                       DESC_W_MASK | DESC_A_MASK);
2736
 
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2737
 
            } else
2738
 
#endif
2739
 
            {
2740
 
                raise_exception_err(EXCP0D_GPF, 0);
2741
 
            }
2742
 
        } else {
2743
 
            if ((new_ss & 3) != rpl)
2744
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2745
 
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2746
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2747
 
            if (!(ss_e2 & DESC_S_MASK) ||
2748
 
                (ss_e2 & DESC_CS_MASK) ||
2749
 
                !(ss_e2 & DESC_W_MASK))
2750
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2751
 
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2752
 
            if (dpl != rpl)
2753
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2754
 
            if (!(ss_e2 & DESC_P_MASK))
2755
 
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2756
 
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2757
 
                                   get_seg_base(ss_e1, ss_e2),
2758
 
                                   get_seg_limit(ss_e1, ss_e2),
2759
 
                                   ss_e2);
2760
 
        }
2761
 
 
2762
 
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2763
 
                       get_seg_base(e1, e2),
2764
 
                       get_seg_limit(e1, e2),
2765
 
                       e2);
2766
 
        cpu_x86_set_cpl(env, rpl);
2767
 
        sp = new_esp;
2768
 
#ifdef TARGET_X86_64
2769
 
        if (env->hflags & HF_CS64_MASK)
2770
 
            sp_mask = -1;
2771
 
        else
2772
 
#endif
2773
 
            sp_mask = get_sp_mask(ss_e2);
2774
 
 
2775
 
        /* validate data segments */
2776
 
        validate_seg(R_ES, rpl);
2777
 
        validate_seg(R_DS, rpl);
2778
 
        validate_seg(R_FS, rpl);
2779
 
        validate_seg(R_GS, rpl);
2780
 
 
2781
 
        sp += addend;
2782
 
    }
2783
 
    SET_ESP(sp, sp_mask);
2784
 
    env->eip = new_eip;
2785
 
    if (is_iret) {
2786
 
        /* NOTE: 'cpl' is the _old_ CPL */
2787
 
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2788
 
        if (cpl == 0)
2789
 
            eflags_mask |= IOPL_MASK;
2790
 
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2791
 
        if (cpl <= iopl)
2792
 
            eflags_mask |= IF_MASK;
2793
 
        if (shift == 0)
2794
 
            eflags_mask &= 0xffff;
2795
 
        load_eflags(new_eflags, eflags_mask);
2796
 
    }
2797
 
    return;
2798
 
 
2799
 
 return_to_vm86:
2800
 
    POPL(ssp, sp, sp_mask, new_esp);
2801
 
    POPL(ssp, sp, sp_mask, new_ss);
2802
 
    POPL(ssp, sp, sp_mask, new_es);
2803
 
    POPL(ssp, sp, sp_mask, new_ds);
2804
 
    POPL(ssp, sp, sp_mask, new_fs);
2805
 
    POPL(ssp, sp, sp_mask, new_gs);
2806
 
 
2807
 
    /* modify processor state */
2808
 
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2809
 
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2810
 
    load_seg_vm(R_CS, new_cs & 0xffff);
2811
 
    cpu_x86_set_cpl(env, 3);
2812
 
    load_seg_vm(R_SS, new_ss & 0xffff);
2813
 
    load_seg_vm(R_ES, new_es & 0xffff);
2814
 
    load_seg_vm(R_DS, new_ds & 0xffff);
2815
 
    load_seg_vm(R_FS, new_fs & 0xffff);
2816
 
    load_seg_vm(R_GS, new_gs & 0xffff);
2817
 
 
2818
 
    env->eip = new_eip & 0xffff;
2819
 
    ESP = new_esp;
2820
 
}
2821
 
 
2822
 
void helper_iret_protected(int shift, int next_eip)
2823
 
{
2824
 
    int tss_selector, type;
2825
 
    uint32_t e1, e2;
2826
 
 
2827
 
    /* specific case for TSS */
2828
 
    if (env->eflags & NT_MASK) {
2829
 
#ifdef TARGET_X86_64
2830
 
        if (env->hflags & HF_LMA_MASK)
2831
 
            raise_exception_err(EXCP0D_GPF, 0);
2832
 
#endif
2833
 
        tss_selector = lduw_kernel(env->tr.base + 0);
2834
 
        if (tss_selector & 4)
2835
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2836
 
        if (load_segment(&e1, &e2, tss_selector) != 0)
2837
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2838
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2839
 
        /* NOTE: we check both segment and busy TSS */
2840
 
        if (type != 3)
2841
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2842
 
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2843
 
    } else {
2844
 
        helper_ret_protected(shift, 1, 0);
2845
 
    }
2846
 
    env->hflags &= ~HF_NMI_MASK;
2847
 
#ifdef USE_KQEMU
2848
 
    if (kqemu_is_ok(env)) {
2849
 
        CC_OP = CC_OP_EFLAGS;
2850
 
        env->exception_index = -1;
2851
 
        cpu_loop_exit();
2852
 
    }
2853
 
#endif
2854
 
}
2855
 
 
2856
 
void helper_lret_protected(int shift, int addend)
2857
 
{
2858
 
    helper_ret_protected(shift, 0, addend);
2859
 
#ifdef USE_KQEMU
2860
 
    if (kqemu_is_ok(env)) {
2861
 
        env->exception_index = -1;
2862
 
        cpu_loop_exit();
2863
 
    }
2864
 
#endif
2865
 
}
2866
 
 
2867
 
void helper_sysenter(void)
2868
 
{
2869
 
    if (env->sysenter_cs == 0) {
2870
 
        raise_exception_err(EXCP0D_GPF, 0);
2871
 
    }
2872
 
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2873
 
    cpu_x86_set_cpl(env, 0);
2874
 
    cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2875
 
                           0, 0xffffffff,
2876
 
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2877
 
                           DESC_S_MASK |
2878
 
                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2879
 
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2880
 
                           0, 0xffffffff,
2881
 
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2882
 
                           DESC_S_MASK |
2883
 
                           DESC_W_MASK | DESC_A_MASK);
2884
 
    ESP = env->sysenter_esp;
2885
 
    EIP = env->sysenter_eip;
2886
 
}
2887
 
 
2888
 
void helper_sysexit(void)
2889
 
{
2890
 
    int cpl;
2891
 
 
2892
 
    cpl = env->hflags & HF_CPL_MASK;
2893
 
    if (env->sysenter_cs == 0 || cpl != 0) {
2894
 
        raise_exception_err(EXCP0D_GPF, 0);
2895
 
    }
2896
 
    cpu_x86_set_cpl(env, 3);
2897
 
    cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2898
 
                           0, 0xffffffff,
2899
 
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2900
 
                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2901
 
                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2902
 
    cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2903
 
                           0, 0xffffffff,
2904
 
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2905
 
                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2906
 
                           DESC_W_MASK | DESC_A_MASK);
2907
 
    ESP = ECX;
2908
 
    EIP = EDX;
2909
 
#ifdef USE_KQEMU
2910
 
    if (kqemu_is_ok(env)) {
2911
 
        env->exception_index = -1;
2912
 
        cpu_loop_exit();
2913
 
    }
2914
 
#endif
2915
 
}
2916
 
 
2917
 
#if defined(CONFIG_USER_ONLY)
2918
 
target_ulong helper_read_crN(int reg)
2919
 
{
2920
 
    return 0;
2921
 
}
2922
 
 
2923
 
void helper_write_crN(int reg, target_ulong t0)
2924
 
{
2925
 
}
2926
 
#else
2927
 
target_ulong helper_read_crN(int reg)
2928
 
{
2929
 
    target_ulong val;
2930
 
 
2931
 
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
2932
 
    switch(reg) {
2933
 
    default:
2934
 
        val = env->cr[reg];
2935
 
        break;
2936
 
    case 8:
2937
 
        val = cpu_get_apic_tpr(env);
2938
 
        break;
2939
 
    }
2940
 
    return val;
2941
 
}
2942
 
 
2943
 
void helper_write_crN(int reg, target_ulong t0)
2944
 
{
2945
 
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
2946
 
    switch(reg) {
2947
 
    case 0:
2948
 
        cpu_x86_update_cr0(env, t0);
2949
 
        break;
2950
 
    case 3:
2951
 
        cpu_x86_update_cr3(env, t0);
2952
 
        break;
2953
 
    case 4:
2954
 
        cpu_x86_update_cr4(env, t0);
2955
 
        break;
2956
 
    case 8:
2957
 
        cpu_set_apic_tpr(env, t0);
2958
 
        env->cr[8] = t0;
2959
 
        break;
2960
 
    default:
2961
 
        env->cr[reg] = t0;
2962
 
        break;
2963
 
    }
2964
 
}
2965
 
#endif
2966
 
 
2967
 
void helper_lmsw(target_ulong t0)
2968
 
{
2969
 
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2970
 
       if already set to one. */
2971
 
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2972
 
    helper_write_crN(0, t0);
2973
 
}
2974
 
 
2975
 
void helper_clts(void)
2976
 
{
2977
 
    env->cr[0] &= ~CR0_TS_MASK;
2978
 
    env->hflags &= ~HF_TS_MASK;
2979
 
}
2980
 
 
2981
 
#if !defined(CONFIG_USER_ONLY)
2982
 
target_ulong helper_movtl_T0_cr8(void)
2983
 
{
2984
 
    return cpu_get_apic_tpr(env);
2985
 
}
2986
 
#endif
2987
 
 
2988
 
/* XXX: do more */
2989
 
void helper_movl_drN_T0(int reg, target_ulong t0)
2990
 
{
2991
 
    env->dr[reg] = t0;
2992
 
}
2993
 
 
2994
 
void helper_invlpg(target_ulong addr)
2995
 
{
2996
 
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
2997
 
    tlb_flush_page(env, addr);
2998
 
}
2999
 
 
3000
 
void helper_rdtsc(void)
3001
 
{
3002
 
    uint64_t val;
3003
 
 
3004
 
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3005
 
        raise_exception(EXCP0D_GPF);
3006
 
    }
3007
 
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
3008
 
 
3009
 
    val = cpu_get_tsc(env);
3010
 
    EAX = (uint32_t)(val);
3011
 
    EDX = (uint32_t)(val >> 32);
3012
 
}
3013
 
 
3014
 
void helper_rdpmc(void)
3015
 
{
3016
 
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3017
 
        raise_exception(EXCP0D_GPF);
3018
 
    }
3019
 
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3020
 
    
3021
 
    /* currently unimplemented */
3022
 
    raise_exception_err(EXCP06_ILLOP, 0);
3023
 
}
3024
 
 
3025
 
#if defined(CONFIG_USER_ONLY)
3026
 
void helper_wrmsr(void)
3027
 
{
3028
 
}
3029
 
 
3030
 
void helper_rdmsr(void)
3031
 
{
3032
 
}
3033
 
#else
3034
 
void helper_wrmsr(void)
3035
 
{
3036
 
    uint64_t val;
3037
 
 
3038
 
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3039
 
 
3040
 
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3041
 
 
3042
 
    switch((uint32_t)ECX) {
3043
 
    case MSR_IA32_SYSENTER_CS:
3044
 
        env->sysenter_cs = val & 0xffff;
3045
 
        break;
3046
 
    case MSR_IA32_SYSENTER_ESP:
3047
 
        env->sysenter_esp = val;
3048
 
        break;
3049
 
    case MSR_IA32_SYSENTER_EIP:
3050
 
        env->sysenter_eip = val;
3051
 
        break;
3052
 
    case MSR_IA32_APICBASE:
3053
 
        cpu_set_apic_base(env, val);
3054
 
        break;
3055
 
    case MSR_EFER:
3056
 
        {
3057
 
            uint64_t update_mask;
3058
 
            update_mask = 0;
3059
 
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3060
 
                update_mask |= MSR_EFER_SCE;
3061
 
            if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3062
 
                update_mask |= MSR_EFER_LME;
3063
 
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3064
 
                update_mask |= MSR_EFER_FFXSR;
3065
 
            if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3066
 
                update_mask |= MSR_EFER_NXE;
3067
 
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3068
 
                update_mask |= MSR_EFER_SVME;
3069
 
            cpu_load_efer(env, (env->efer & ~update_mask) |
3070
 
                          (val & update_mask));
3071
 
        }
3072
 
        break;
3073
 
    case MSR_STAR:
3074
 
        env->star = val;
3075
 
        break;
3076
 
    case MSR_PAT:
3077
 
        env->pat = val;
3078
 
        break;
3079
 
    case MSR_VM_HSAVE_PA:
3080
 
        env->vm_hsave = val;
3081
 
        break;
3082
 
#ifdef TARGET_X86_64
3083
 
    case MSR_LSTAR:
3084
 
        env->lstar = val;
3085
 
        break;
3086
 
    case MSR_CSTAR:
3087
 
        env->cstar = val;
3088
 
        break;
3089
 
    case MSR_FMASK:
3090
 
        env->fmask = val;
3091
 
        break;
3092
 
    case MSR_FSBASE:
3093
 
        env->segs[R_FS].base = val;
3094
 
        break;
3095
 
    case MSR_GSBASE:
3096
 
        env->segs[R_GS].base = val;
3097
 
        break;
3098
 
    case MSR_KERNELGSBASE:
3099
 
        env->kernelgsbase = val;
3100
 
        break;
3101
 
#endif
3102
 
    default:
3103
 
        /* XXX: exception ? */
3104
 
        break;
3105
 
    }
3106
 
}
3107
 
 
3108
 
void helper_rdmsr(void)
3109
 
{
3110
 
    uint64_t val;
3111
 
 
3112
 
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3113
 
 
3114
 
    switch((uint32_t)ECX) {
3115
 
    case MSR_IA32_SYSENTER_CS:
3116
 
        val = env->sysenter_cs;
3117
 
        break;
3118
 
    case MSR_IA32_SYSENTER_ESP:
3119
 
        val = env->sysenter_esp;
3120
 
        break;
3121
 
    case MSR_IA32_SYSENTER_EIP:
3122
 
        val = env->sysenter_eip;
3123
 
        break;
3124
 
    case MSR_IA32_APICBASE:
3125
 
        val = cpu_get_apic_base(env);
3126
 
        break;
3127
 
    case MSR_EFER:
3128
 
        val = env->efer;
3129
 
        break;
3130
 
    case MSR_STAR:
3131
 
        val = env->star;
3132
 
        break;
3133
 
    case MSR_PAT:
3134
 
        val = env->pat;
3135
 
        break;
3136
 
    case MSR_VM_HSAVE_PA:
3137
 
        val = env->vm_hsave;
3138
 
        break;
3139
 
#ifdef TARGET_X86_64
3140
 
    case MSR_LSTAR:
3141
 
        val = env->lstar;
3142
 
        break;
3143
 
    case MSR_CSTAR:
3144
 
        val = env->cstar;
3145
 
        break;
3146
 
    case MSR_FMASK:
3147
 
        val = env->fmask;
3148
 
        break;
3149
 
    case MSR_FSBASE:
3150
 
        val = env->segs[R_FS].base;
3151
 
        break;
3152
 
    case MSR_GSBASE:
3153
 
        val = env->segs[R_GS].base;
3154
 
        break;
3155
 
    case MSR_KERNELGSBASE:
3156
 
        val = env->kernelgsbase;
3157
 
        break;
3158
 
#endif
3159
 
#ifdef USE_KQEMU
3160
 
    case MSR_QPI_COMMBASE:
3161
 
        if (env->kqemu_enabled) {
3162
 
            val = kqemu_comm_base;
3163
 
        } else {
3164
 
            val = 0;
3165
 
        }
3166
 
        break;
3167
 
#endif
3168
 
    default:
3169
 
        /* XXX: exception ? */
3170
 
        val = 0;
3171
 
        break;
3172
 
    }
3173
 
    EAX = (uint32_t)(val);
3174
 
    EDX = (uint32_t)(val >> 32);
3175
 
}
3176
 
#endif
3177
 
 
3178
 
target_ulong helper_lsl(target_ulong selector1)
3179
 
{
3180
 
    unsigned int limit;
3181
 
    uint32_t e1, e2, eflags, selector;
3182
 
    int rpl, dpl, cpl, type;
3183
 
 
3184
 
    selector = selector1 & 0xffff;
3185
 
    eflags = cc_table[CC_OP].compute_all();
3186
 
    if (load_segment(&e1, &e2, selector) != 0)
3187
 
        goto fail;
3188
 
    rpl = selector & 3;
3189
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3190
 
    cpl = env->hflags & HF_CPL_MASK;
3191
 
    if (e2 & DESC_S_MASK) {
3192
 
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3193
 
            /* conforming */
3194
 
        } else {
3195
 
            if (dpl < cpl || dpl < rpl)
3196
 
                goto fail;
3197
 
        }
3198
 
    } else {
3199
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3200
 
        switch(type) {
3201
 
        case 1:
3202
 
        case 2:
3203
 
        case 3:
3204
 
        case 9:
3205
 
        case 11:
3206
 
            break;
3207
 
        default:
3208
 
            goto fail;
3209
 
        }
3210
 
        if (dpl < cpl || dpl < rpl) {
3211
 
        fail:
3212
 
            CC_SRC = eflags & ~CC_Z;
3213
 
            return 0;
3214
 
        }
3215
 
    }
3216
 
    limit = get_seg_limit(e1, e2);
3217
 
    CC_SRC = eflags | CC_Z;
3218
 
    return limit;
3219
 
}
3220
 
 
3221
 
target_ulong helper_lar(target_ulong selector1)
3222
 
{
3223
 
    uint32_t e1, e2, eflags, selector;
3224
 
    int rpl, dpl, cpl, type;
3225
 
 
3226
 
    selector = selector1 & 0xffff;
3227
 
    eflags = cc_table[CC_OP].compute_all();
3228
 
    if ((selector & 0xfffc) == 0)
3229
 
        goto fail;
3230
 
    if (load_segment(&e1, &e2, selector) != 0)
3231
 
        goto fail;
3232
 
    rpl = selector & 3;
3233
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3234
 
    cpl = env->hflags & HF_CPL_MASK;
3235
 
    if (e2 & DESC_S_MASK) {
3236
 
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3237
 
            /* conforming */
3238
 
        } else {
3239
 
            if (dpl < cpl || dpl < rpl)
3240
 
                goto fail;
3241
 
        }
3242
 
    } else {
3243
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3244
 
        switch(type) {
3245
 
        case 1:
3246
 
        case 2:
3247
 
        case 3:
3248
 
        case 4:
3249
 
        case 5:
3250
 
        case 9:
3251
 
        case 11:
3252
 
        case 12:
3253
 
            break;
3254
 
        default:
3255
 
            goto fail;
3256
 
        }
3257
 
        if (dpl < cpl || dpl < rpl) {
3258
 
        fail:
3259
 
            CC_SRC = eflags & ~CC_Z;
3260
 
            return 0;
3261
 
        }
3262
 
    }
3263
 
    CC_SRC = eflags | CC_Z;
3264
 
    return e2 & 0x00f0ff00;
3265
 
}
3266
 
 
3267
 
void helper_verr(target_ulong selector1)
3268
 
{
3269
 
    uint32_t e1, e2, eflags, selector;
3270
 
    int rpl, dpl, cpl;
3271
 
 
3272
 
    selector = selector1 & 0xffff;
3273
 
    eflags = cc_table[CC_OP].compute_all();
3274
 
    if ((selector & 0xfffc) == 0)
3275
 
        goto fail;
3276
 
    if (load_segment(&e1, &e2, selector) != 0)
3277
 
        goto fail;
3278
 
    if (!(e2 & DESC_S_MASK))
3279
 
        goto fail;
3280
 
    rpl = selector & 3;
3281
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3282
 
    cpl = env->hflags & HF_CPL_MASK;
3283
 
    if (e2 & DESC_CS_MASK) {
3284
 
        if (!(e2 & DESC_R_MASK))
3285
 
            goto fail;
3286
 
        if (!(e2 & DESC_C_MASK)) {
3287
 
            if (dpl < cpl || dpl < rpl)
3288
 
                goto fail;
3289
 
        }
3290
 
    } else {
3291
 
        if (dpl < cpl || dpl < rpl) {
3292
 
        fail:
3293
 
            CC_SRC = eflags & ~CC_Z;
3294
 
            return;
3295
 
        }
3296
 
    }
3297
 
    CC_SRC = eflags | CC_Z;
3298
 
}
3299
 
 
3300
 
void helper_verw(target_ulong selector1)
3301
 
{
3302
 
    uint32_t e1, e2, eflags, selector;
3303
 
    int rpl, dpl, cpl;
3304
 
 
3305
 
    selector = selector1 & 0xffff;
3306
 
    eflags = cc_table[CC_OP].compute_all();
3307
 
    if ((selector & 0xfffc) == 0)
3308
 
        goto fail;
3309
 
    if (load_segment(&e1, &e2, selector) != 0)
3310
 
        goto fail;
3311
 
    if (!(e2 & DESC_S_MASK))
3312
 
        goto fail;
3313
 
    rpl = selector & 3;
3314
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3315
 
    cpl = env->hflags & HF_CPL_MASK;
3316
 
    if (e2 & DESC_CS_MASK) {
3317
 
        goto fail;
3318
 
    } else {
3319
 
        if (dpl < cpl || dpl < rpl)
3320
 
            goto fail;
3321
 
        if (!(e2 & DESC_W_MASK)) {
3322
 
        fail:
3323
 
            CC_SRC = eflags & ~CC_Z;
3324
 
            return;
3325
 
        }
3326
 
    }
3327
 
    CC_SRC = eflags | CC_Z;
3328
 
}
3329
 
 
3330
 
/* x87 FPU helpers */
3331
 
 
3332
 
static void fpu_set_exception(int mask)
3333
 
{
3334
 
    env->fpus |= mask;
3335
 
    if (env->fpus & (~env->fpuc & FPUC_EM))
3336
 
        env->fpus |= FPUS_SE | FPUS_B;
3337
 
}
3338
 
 
3339
 
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3340
 
{
3341
 
    if (b == 0.0)
3342
 
        fpu_set_exception(FPUS_ZE);
3343
 
    return a / b;
3344
 
}
3345
 
 
3346
 
void fpu_raise_exception(void)
3347
 
{
3348
 
    if (env->cr[0] & CR0_NE_MASK) {
3349
 
        raise_exception(EXCP10_COPR);
3350
 
    }
3351
 
#if !defined(CONFIG_USER_ONLY)
3352
 
    else {
3353
 
        cpu_set_ferr(env);
3354
 
    }
3355
 
#endif
3356
 
}
3357
 
 
3358
 
void helper_flds_FT0(uint32_t val)
3359
 
{
3360
 
    union {
3361
 
        float32 f;
3362
 
        uint32_t i;
3363
 
    } u;
3364
 
    u.i = val;
3365
 
    FT0 = float32_to_floatx(u.f, &env->fp_status);
3366
 
}
3367
 
 
3368
 
void helper_fldl_FT0(uint64_t val)
3369
 
{
3370
 
    union {
3371
 
        float64 f;
3372
 
        uint64_t i;
3373
 
    } u;
3374
 
    u.i = val;
3375
 
    FT0 = float64_to_floatx(u.f, &env->fp_status);
3376
 
}
3377
 
 
3378
 
void helper_fildl_FT0(int32_t val)
3379
 
{
3380
 
    FT0 = int32_to_floatx(val, &env->fp_status);
3381
 
}
3382
 
 
3383
 
void helper_flds_ST0(uint32_t val)
3384
 
{
3385
 
    int new_fpstt;
3386
 
    union {
3387
 
        float32 f;
3388
 
        uint32_t i;
3389
 
    } u;
3390
 
    new_fpstt = (env->fpstt - 1) & 7;
3391
 
    u.i = val;
3392
 
    env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3393
 
    env->fpstt = new_fpstt;
3394
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3395
 
}
3396
 
 
3397
 
void helper_fldl_ST0(uint64_t val)
3398
 
{
3399
 
    int new_fpstt;
3400
 
    union {
3401
 
        float64 f;
3402
 
        uint64_t i;
3403
 
    } u;
3404
 
    new_fpstt = (env->fpstt - 1) & 7;
3405
 
    u.i = val;
3406
 
    env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3407
 
    env->fpstt = new_fpstt;
3408
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3409
 
}
3410
 
 
3411
 
void helper_fildl_ST0(int32_t val)
3412
 
{
3413
 
    int new_fpstt;
3414
 
    new_fpstt = (env->fpstt - 1) & 7;
3415
 
    env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3416
 
    env->fpstt = new_fpstt;
3417
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3418
 
}
3419
 
 
3420
 
void helper_fildll_ST0(int64_t val)
3421
 
{
3422
 
    int new_fpstt;
3423
 
    new_fpstt = (env->fpstt - 1) & 7;
3424
 
    env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3425
 
    env->fpstt = new_fpstt;
3426
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3427
 
}
3428
 
 
3429
 
uint32_t helper_fsts_ST0(void)
3430
 
{
3431
 
    union {
3432
 
        float32 f;
3433
 
        uint32_t i;
3434
 
    } u;
3435
 
    u.f = floatx_to_float32(ST0, &env->fp_status);
3436
 
    return u.i;
3437
 
}
3438
 
 
3439
 
uint64_t helper_fstl_ST0(void)
3440
 
{
3441
 
    union {
3442
 
        float64 f;
3443
 
        uint64_t i;
3444
 
    } u;
3445
 
    u.f = floatx_to_float64(ST0, &env->fp_status);
3446
 
    return u.i;
3447
 
}
3448
 
 
3449
 
int32_t helper_fist_ST0(void)
3450
 
{
3451
 
    int32_t val;
3452
 
    val = floatx_to_int32(ST0, &env->fp_status);
3453
 
    if (val != (int16_t)val)
3454
 
        val = -32768;
3455
 
    return val;
3456
 
}
3457
 
 
3458
 
int32_t helper_fistl_ST0(void)
3459
 
{
3460
 
    int32_t val;
3461
 
    val = floatx_to_int32(ST0, &env->fp_status);
3462
 
    return val;
3463
 
}
3464
 
 
3465
 
int64_t helper_fistll_ST0(void)
3466
 
{
3467
 
    int64_t val;
3468
 
    val = floatx_to_int64(ST0, &env->fp_status);
3469
 
    return val;
3470
 
}
3471
 
 
3472
 
int32_t helper_fistt_ST0(void)
3473
 
{
3474
 
    int32_t val;
3475
 
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3476
 
    if (val != (int16_t)val)
3477
 
        val = -32768;
3478
 
    return val;
3479
 
}
3480
 
 
3481
 
int32_t helper_fisttl_ST0(void)
3482
 
{
3483
 
    int32_t val;
3484
 
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3485
 
    return val;
3486
 
}
3487
 
 
3488
 
int64_t helper_fisttll_ST0(void)
3489
 
{
3490
 
    int64_t val;
3491
 
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3492
 
    return val;
3493
 
}
3494
 
 
3495
 
void helper_fldt_ST0(target_ulong ptr)
3496
 
{
3497
 
    int new_fpstt;
3498
 
    new_fpstt = (env->fpstt - 1) & 7;
3499
 
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3500
 
    env->fpstt = new_fpstt;
3501
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3502
 
}
3503
 
 
3504
 
void helper_fstt_ST0(target_ulong ptr)
3505
 
{
3506
 
    helper_fstt(ST0, ptr);
3507
 
}
3508
 
 
3509
 
void helper_fpush(void)
3510
 
{
3511
 
    fpush();
3512
 
}
3513
 
 
3514
 
void helper_fpop(void)
3515
 
{
3516
 
    fpop();
3517
 
}
3518
 
 
3519
 
void helper_fdecstp(void)
3520
 
{
3521
 
    env->fpstt = (env->fpstt - 1) & 7;
3522
 
    env->fpus &= (~0x4700);
3523
 
}
3524
 
 
3525
 
void helper_fincstp(void)
3526
 
{
3527
 
    env->fpstt = (env->fpstt + 1) & 7;
3528
 
    env->fpus &= (~0x4700);
3529
 
}
3530
 
 
3531
 
/* FPU move */
3532
 
 
3533
 
void helper_ffree_STN(int st_index)
3534
 
{
3535
 
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3536
 
}
3537
 
 
3538
 
void helper_fmov_ST0_FT0(void)
3539
 
{
3540
 
    ST0 = FT0;
3541
 
}
3542
 
 
3543
 
void helper_fmov_FT0_STN(int st_index)
3544
 
{
3545
 
    FT0 = ST(st_index);
3546
 
}
3547
 
 
3548
 
void helper_fmov_ST0_STN(int st_index)
3549
 
{
3550
 
    ST0 = ST(st_index);
3551
 
}
3552
 
 
3553
 
void helper_fmov_STN_ST0(int st_index)
3554
 
{
3555
 
    ST(st_index) = ST0;
3556
 
}
3557
 
 
3558
 
void helper_fxchg_ST0_STN(int st_index)
3559
 
{
3560
 
    CPU86_LDouble tmp;
3561
 
    tmp = ST(st_index);
3562
 
    ST(st_index) = ST0;
3563
 
    ST0 = tmp;
3564
 
}
3565
 
 
3566
 
/* FPU operations */
3567
 
 
3568
 
static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
3569
 
 
3570
 
void helper_fcom_ST0_FT0(void)
3571
 
{
3572
 
    int ret;
3573
 
 
3574
 
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3575
 
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3576
 
    FORCE_RET();
3577
 
}
3578
 
 
3579
 
void helper_fucom_ST0_FT0(void)
3580
 
{
3581
 
    int ret;
3582
 
 
3583
 
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3584
 
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3585
 
    FORCE_RET();
3586
 
}
3587
 
 
3588
 
static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
3589
 
 
3590
 
void helper_fcomi_ST0_FT0(void)
3591
 
{
3592
 
    int eflags;
3593
 
    int ret;
3594
 
 
3595
 
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3596
 
    eflags = cc_table[CC_OP].compute_all();
3597
 
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3598
 
    CC_SRC = eflags;
3599
 
    FORCE_RET();
3600
 
}
3601
 
 
3602
 
void helper_fucomi_ST0_FT0(void)
3603
 
{
3604
 
    int eflags;
3605
 
    int ret;
3606
 
 
3607
 
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3608
 
    eflags = cc_table[CC_OP].compute_all();
3609
 
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3610
 
    CC_SRC = eflags;
3611
 
    FORCE_RET();
3612
 
}
3613
 
 
3614
 
void helper_fadd_ST0_FT0(void)
3615
 
{
3616
 
    ST0 += FT0;
3617
 
}
3618
 
 
3619
 
void helper_fmul_ST0_FT0(void)
3620
 
{
3621
 
    ST0 *= FT0;
3622
 
}
3623
 
 
3624
 
void helper_fsub_ST0_FT0(void)
3625
 
{
3626
 
    ST0 -= FT0;
3627
 
}
3628
 
 
3629
 
void helper_fsubr_ST0_FT0(void)
3630
 
{
3631
 
    ST0 = FT0 - ST0;
3632
 
}
3633
 
 
3634
 
void helper_fdiv_ST0_FT0(void)
3635
 
{
3636
 
    ST0 = helper_fdiv(ST0, FT0);
3637
 
}
3638
 
 
3639
 
void helper_fdivr_ST0_FT0(void)
3640
 
{
3641
 
    ST0 = helper_fdiv(FT0, ST0);
3642
 
}
3643
 
 
3644
 
/* fp operations between STN and ST0 */
3645
 
 
3646
 
void helper_fadd_STN_ST0(int st_index)
3647
 
{
3648
 
    ST(st_index) += ST0;
3649
 
}
3650
 
 
3651
 
void helper_fmul_STN_ST0(int st_index)
3652
 
{
3653
 
    ST(st_index) *= ST0;
3654
 
}
3655
 
 
3656
 
void helper_fsub_STN_ST0(int st_index)
3657
 
{
3658
 
    ST(st_index) -= ST0;
3659
 
}
3660
 
 
3661
 
void helper_fsubr_STN_ST0(int st_index)
3662
 
{
3663
 
    CPU86_LDouble *p;
3664
 
    p = &ST(st_index);
3665
 
    *p = ST0 - *p;
3666
 
}
3667
 
 
3668
 
void helper_fdiv_STN_ST0(int st_index)
3669
 
{
3670
 
    CPU86_LDouble *p;
3671
 
    p = &ST(st_index);
3672
 
    *p = helper_fdiv(*p, ST0);
3673
 
}
3674
 
 
3675
 
void helper_fdivr_STN_ST0(int st_index)
3676
 
{
3677
 
    CPU86_LDouble *p;
3678
 
    p = &ST(st_index);
3679
 
    *p = helper_fdiv(ST0, *p);
3680
 
}
3681
 
 
3682
 
/* misc FPU operations */
3683
 
void helper_fchs_ST0(void)
3684
 
{
3685
 
    ST0 = floatx_chs(ST0);
3686
 
}
3687
 
 
3688
 
void helper_fabs_ST0(void)
3689
 
{
3690
 
    ST0 = floatx_abs(ST0);
3691
 
}
3692
 
 
3693
 
void helper_fld1_ST0(void)
3694
 
{
3695
 
    ST0 = f15rk[1];
3696
 
}
3697
 
 
3698
 
void helper_fldl2t_ST0(void)
3699
 
{
3700
 
    ST0 = f15rk[6];
3701
 
}
3702
 
 
3703
 
void helper_fldl2e_ST0(void)
3704
 
{
3705
 
    ST0 = f15rk[5];
3706
 
}
3707
 
 
3708
 
void helper_fldpi_ST0(void)
3709
 
{
3710
 
    ST0 = f15rk[2];
3711
 
}
3712
 
 
3713
 
void helper_fldlg2_ST0(void)
3714
 
{
3715
 
    ST0 = f15rk[3];
3716
 
}
3717
 
 
3718
 
void helper_fldln2_ST0(void)
3719
 
{
3720
 
    ST0 = f15rk[4];
3721
 
}
3722
 
 
3723
 
void helper_fldz_ST0(void)
3724
 
{
3725
 
    ST0 = f15rk[0];
3726
 
}
3727
 
 
3728
 
void helper_fldz_FT0(void)
3729
 
{
3730
 
    FT0 = f15rk[0];
3731
 
}
3732
 
 
3733
 
uint32_t helper_fnstsw(void)
3734
 
{
3735
 
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3736
 
}
3737
 
 
3738
 
uint32_t helper_fnstcw(void)
3739
 
{
3740
 
    return env->fpuc;
3741
 
}
3742
 
 
3743
 
static void update_fp_status(void)
3744
 
{
3745
 
    int rnd_type;
3746
 
 
3747
 
    /* set rounding mode */
3748
 
    switch(env->fpuc & RC_MASK) {
3749
 
    default:
3750
 
    case RC_NEAR:
3751
 
        rnd_type = float_round_nearest_even;
3752
 
        break;
3753
 
    case RC_DOWN:
3754
 
        rnd_type = float_round_down;
3755
 
        break;
3756
 
    case RC_UP:
3757
 
        rnd_type = float_round_up;
3758
 
        break;
3759
 
    case RC_CHOP:
3760
 
        rnd_type = float_round_to_zero;
3761
 
        break;
3762
 
    }
3763
 
    set_float_rounding_mode(rnd_type, &env->fp_status);
3764
 
#ifdef FLOATX80
3765
 
    switch((env->fpuc >> 8) & 3) {
3766
 
    case 0:
3767
 
        rnd_type = 32;
3768
 
        break;
3769
 
    case 2:
3770
 
        rnd_type = 64;
3771
 
        break;
3772
 
    case 3:
3773
 
    default:
3774
 
        rnd_type = 80;
3775
 
        break;
3776
 
    }
3777
 
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3778
 
#endif
3779
 
}
3780
 
 
3781
 
void helper_fldcw(uint32_t val)
3782
 
{
3783
 
    env->fpuc = val;
3784
 
    update_fp_status();
3785
 
}
3786
 
 
3787
 
void helper_fclex(void)
3788
 
{
3789
 
    env->fpus &= 0x7f00;
3790
 
}
3791
 
 
3792
 
void helper_fwait(void)
3793
 
{
3794
 
    if (env->fpus & FPUS_SE)
3795
 
        fpu_raise_exception();
3796
 
    FORCE_RET();
3797
 
}
3798
 
 
3799
 
void helper_fninit(void)
3800
 
{
3801
 
    env->fpus = 0;
3802
 
    env->fpstt = 0;
3803
 
    env->fpuc = 0x37f;
3804
 
    env->fptags[0] = 1;
3805
 
    env->fptags[1] = 1;
3806
 
    env->fptags[2] = 1;
3807
 
    env->fptags[3] = 1;
3808
 
    env->fptags[4] = 1;
3809
 
    env->fptags[5] = 1;
3810
 
    env->fptags[6] = 1;
3811
 
    env->fptags[7] = 1;
3812
 
}
3813
 
 
3814
 
/* BCD ops */
3815
 
 
3816
 
void helper_fbld_ST0(target_ulong ptr)
3817
 
{
3818
 
    CPU86_LDouble tmp;
3819
 
    uint64_t val;
3820
 
    unsigned int v;
3821
 
    int i;
3822
 
 
3823
 
    val = 0;
3824
 
    for(i = 8; i >= 0; i--) {
3825
 
        v = ldub(ptr + i);
3826
 
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3827
 
    }
3828
 
    tmp = val;
3829
 
    if (ldub(ptr + 9) & 0x80)
3830
 
        tmp = -tmp;
3831
 
    fpush();
3832
 
    ST0 = tmp;
3833
 
}
3834
 
 
3835
 
void helper_fbst_ST0(target_ulong ptr)
3836
 
{
3837
 
    int v;
3838
 
    target_ulong mem_ref, mem_end;
3839
 
    int64_t val;
3840
 
 
3841
 
    val = floatx_to_int64(ST0, &env->fp_status);
3842
 
    mem_ref = ptr;
3843
 
    mem_end = mem_ref + 9;
3844
 
    if (val < 0) {
3845
 
        stb(mem_end, 0x80);
3846
 
        val = -val;
3847
 
    } else {
3848
 
        stb(mem_end, 0x00);
3849
 
    }
3850
 
    while (mem_ref < mem_end) {
3851
 
        if (val == 0)
3852
 
            break;
3853
 
        v = val % 100;
3854
 
        val = val / 100;
3855
 
        v = ((v / 10) << 4) | (v % 10);
3856
 
        stb(mem_ref++, v);
3857
 
    }
3858
 
    while (mem_ref < mem_end) {
3859
 
        stb(mem_ref++, 0);
3860
 
    }
3861
 
}
3862
 
 
3863
 
void helper_f2xm1(void)
3864
 
{
3865
 
    ST0 = pow(2.0,ST0) - 1.0;
3866
 
}
3867
 
 
3868
 
void helper_fyl2x(void)
3869
 
{
3870
 
    CPU86_LDouble fptemp;
3871
 
 
3872
 
    fptemp = ST0;
3873
 
    if (fptemp>0.0){
3874
 
        fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
3875
 
        ST1 *= fptemp;
3876
 
        fpop();
3877
 
    } else {
3878
 
        env->fpus &= (~0x4700);
3879
 
        env->fpus |= 0x400;
3880
 
    }
3881
 
}
3882
 
 
3883
 
void helper_fptan(void)
3884
 
{
3885
 
    CPU86_LDouble fptemp;
3886
 
 
3887
 
    fptemp = ST0;
3888
 
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3889
 
        env->fpus |= 0x400;
3890
 
    } else {
3891
 
        ST0 = tan(fptemp);
3892
 
        fpush();
3893
 
        ST0 = 1.0;
3894
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
3895
 
        /* the above code is for  |arg| < 2**52 only */
3896
 
    }
3897
 
}
3898
 
 
3899
 
void helper_fpatan(void)
3900
 
{
3901
 
    CPU86_LDouble fptemp, fpsrcop;
3902
 
 
3903
 
    fpsrcop = ST1;
3904
 
    fptemp = ST0;
3905
 
    ST1 = atan2(fpsrcop,fptemp);
3906
 
    fpop();
3907
 
}
3908
 
 
3909
 
void helper_fxtract(void)
3910
 
{
3911
 
    CPU86_LDoubleU temp;
3912
 
    unsigned int expdif;
3913
 
 
3914
 
    temp.d = ST0;
3915
 
    expdif = EXPD(temp) - EXPBIAS;
3916
 
    /*DP exponent bias*/
3917
 
    ST0 = expdif;
3918
 
    fpush();
3919
 
    BIASEXPONENT(temp);
3920
 
    ST0 = temp.d;
3921
 
}
3922
 
 
3923
 
void helper_fprem1(void)
3924
 
{
3925
 
    CPU86_LDouble dblq, fpsrcop, fptemp;
3926
 
    CPU86_LDoubleU fpsrcop1, fptemp1;
3927
 
    int expdif;
3928
 
    signed long long int q;
3929
 
 
3930
 
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3931
 
        ST0 = 0.0 / 0.0; /* NaN */
3932
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3933
 
        return;
3934
 
    }
3935
 
 
3936
 
    fpsrcop = ST0;
3937
 
    fptemp = ST1;
3938
 
    fpsrcop1.d = fpsrcop;
3939
 
    fptemp1.d = fptemp;
3940
 
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3941
 
 
3942
 
    if (expdif < 0) {
3943
 
        /* optimisation? taken from the AMD docs */
3944
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3945
 
        /* ST0 is unchanged */
3946
 
        return;
3947
 
    }
3948
 
 
3949
 
    if (expdif < 53) {
3950
 
        dblq = fpsrcop / fptemp;
3951
 
        /* round dblq towards nearest integer */
3952
 
        dblq = rint(dblq);
3953
 
        ST0 = fpsrcop - fptemp * dblq;
3954
 
 
3955
 
        /* convert dblq to q by truncating towards zero */
3956
 
        if (dblq < 0.0)
3957
 
           q = (signed long long int)(-dblq);
3958
 
        else
3959
 
           q = (signed long long int)dblq;
3960
 
 
3961
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3962
 
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
3963
 
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
3964
 
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
3965
 
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
3966
 
    } else {
3967
 
        env->fpus |= 0x400;  /* C2 <-- 1 */
3968
 
        fptemp = pow(2.0, expdif - 50);
3969
 
        fpsrcop = (ST0 / ST1) / fptemp;
3970
 
        /* fpsrcop = integer obtained by chopping */
3971
 
        fpsrcop = (fpsrcop < 0.0) ?
3972
 
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
3973
 
        ST0 -= (ST1 * fpsrcop * fptemp);
3974
 
    }
3975
 
}
3976
 
 
3977
 
void helper_fprem(void)
3978
 
{
3979
 
    CPU86_LDouble dblq, fpsrcop, fptemp;
3980
 
    CPU86_LDoubleU fpsrcop1, fptemp1;
3981
 
    int expdif;
3982
 
    signed long long int q;
3983
 
 
3984
 
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3985
 
       ST0 = 0.0 / 0.0; /* NaN */
3986
 
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3987
 
       return;
3988
 
    }
3989
 
 
3990
 
    fpsrcop = (CPU86_LDouble)ST0;
3991
 
    fptemp = (CPU86_LDouble)ST1;
3992
 
    fpsrcop1.d = fpsrcop;
3993
 
    fptemp1.d = fptemp;
3994
 
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3995
 
 
3996
 
    if (expdif < 0) {
3997
 
        /* optimisation? taken from the AMD docs */
3998
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3999
 
        /* ST0 is unchanged */
4000
 
        return;
4001
 
    }
4002
 
 
4003
 
    if ( expdif < 53 ) {
4004
 
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4005
 
        /* round dblq towards zero */
4006
 
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4007
 
        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
4008
 
 
4009
 
        /* convert dblq to q by truncating towards zero */
4010
 
        if (dblq < 0.0)
4011
 
           q = (signed long long int)(-dblq);
4012
 
        else
4013
 
           q = (signed long long int)dblq;
4014
 
 
4015
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4016
 
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4017
 
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4018
 
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4019
 
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4020
 
    } else {
4021
 
        int N = 32 + (expdif % 32); /* as per AMD docs */
4022
 
        env->fpus |= 0x400;  /* C2 <-- 1 */
4023
 
        fptemp = pow(2.0, (double)(expdif - N));
4024
 
        fpsrcop = (ST0 / ST1) / fptemp;
4025
 
        /* fpsrcop = integer obtained by chopping */
4026
 
        fpsrcop = (fpsrcop < 0.0) ?
4027
 
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4028
 
        ST0 -= (ST1 * fpsrcop * fptemp);
4029
 
    }
4030
 
}
4031
 
 
4032
 
void helper_fyl2xp1(void)
4033
 
{
4034
 
    CPU86_LDouble fptemp;
4035
 
 
4036
 
    fptemp = ST0;
4037
 
    if ((fptemp+1.0)>0.0) {
4038
 
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4039
 
        ST1 *= fptemp;
4040
 
        fpop();
4041
 
    } else {
4042
 
        env->fpus &= (~0x4700);
4043
 
        env->fpus |= 0x400;
4044
 
    }
4045
 
}
4046
 
 
4047
 
void helper_fsqrt(void)
4048
 
{
4049
 
    CPU86_LDouble fptemp;
4050
 
 
4051
 
    fptemp = ST0;
4052
 
    if (fptemp<0.0) {
4053
 
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4054
 
        env->fpus |= 0x400;
4055
 
    }
4056
 
    ST0 = sqrt(fptemp);
4057
 
}
4058
 
 
4059
 
void helper_fsincos(void)
4060
 
{
4061
 
    CPU86_LDouble fptemp;
4062
 
 
4063
 
    fptemp = ST0;
4064
 
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4065
 
        env->fpus |= 0x400;
4066
 
    } else {
4067
 
        ST0 = sin(fptemp);
4068
 
        fpush();
4069
 
        ST0 = cos(fptemp);
4070
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4071
 
        /* the above code is for  |arg| < 2**63 only */
4072
 
    }
4073
 
}
4074
 
 
4075
 
void helper_frndint(void)
4076
 
{
4077
 
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4078
 
}
4079
 
 
4080
 
void helper_fscale(void)
4081
 
{
4082
 
    ST0 = ldexp (ST0, (int)(ST1));
4083
 
}
4084
 
 
4085
 
void helper_fsin(void)
4086
 
{
4087
 
    CPU86_LDouble fptemp;
4088
 
 
4089
 
    fptemp = ST0;
4090
 
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4091
 
        env->fpus |= 0x400;
4092
 
    } else {
4093
 
        ST0 = sin(fptemp);
4094
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4095
 
        /* the above code is for  |arg| < 2**53 only */
4096
 
    }
4097
 
}
4098
 
 
4099
 
void helper_fcos(void)
4100
 
{
4101
 
    CPU86_LDouble fptemp;
4102
 
 
4103
 
    fptemp = ST0;
4104
 
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4105
 
        env->fpus |= 0x400;
4106
 
    } else {
4107
 
        ST0 = cos(fptemp);
4108
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4109
 
        /* the above code is for  |arg5 < 2**63 only */
4110
 
    }
4111
 
}
4112
 
 
4113
 
void helper_fxam_ST0(void)
4114
 
{
4115
 
    CPU86_LDoubleU temp;
4116
 
    int expdif;
4117
 
 
4118
 
    temp.d = ST0;
4119
 
 
4120
 
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4121
 
    if (SIGND(temp))
4122
 
        env->fpus |= 0x200; /* C1 <-- 1 */
4123
 
 
4124
 
    /* XXX: test fptags too */
4125
 
    expdif = EXPD(temp);
4126
 
    if (expdif == MAXEXPD) {
4127
 
#ifdef USE_X86LDOUBLE
4128
 
        if (MANTD(temp) == 0x8000000000000000ULL)
4129
 
#else
4130
 
        if (MANTD(temp) == 0)
4131
 
#endif
4132
 
            env->fpus |=  0x500 /*Infinity*/;
4133
 
        else
4134
 
            env->fpus |=  0x100 /*NaN*/;
4135
 
    } else if (expdif == 0) {
4136
 
        if (MANTD(temp) == 0)
4137
 
            env->fpus |=  0x4000 /*Zero*/;
4138
 
        else
4139
 
            env->fpus |= 0x4400 /*Denormal*/;
4140
 
    } else {
4141
 
        env->fpus |= 0x400;
4142
 
    }
4143
 
}
4144
 
 
4145
 
void helper_fstenv(target_ulong ptr, int data32)
4146
 
{
4147
 
    int fpus, fptag, exp, i;
4148
 
    uint64_t mant;
4149
 
    CPU86_LDoubleU tmp;
4150
 
 
4151
 
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4152
 
    fptag = 0;
4153
 
    for (i=7; i>=0; i--) {
4154
 
        fptag <<= 2;
4155
 
        if (env->fptags[i]) {
4156
 
            fptag |= 3;
4157
 
        } else {
4158
 
            tmp.d = env->fpregs[i].d;
4159
 
            exp = EXPD(tmp);
4160
 
            mant = MANTD(tmp);
4161
 
            if (exp == 0 && mant == 0) {
4162
 
                /* zero */
4163
 
                fptag |= 1;
4164
 
            } else if (exp == 0 || exp == MAXEXPD
4165
 
#ifdef USE_X86LDOUBLE
4166
 
                       || (mant & (1LL << 63)) == 0
4167
 
#endif
4168
 
                       ) {
4169
 
                /* NaNs, infinity, denormal */
4170
 
                fptag |= 2;
4171
 
            }
4172
 
        }
4173
 
    }
4174
 
    if (data32) {
4175
 
        /* 32 bit */
4176
 
        stl(ptr, env->fpuc);
4177
 
        stl(ptr + 4, fpus);
4178
 
        stl(ptr + 8, fptag);
4179
 
        stl(ptr + 12, 0); /* fpip */
4180
 
        stl(ptr + 16, 0); /* fpcs */
4181
 
        stl(ptr + 20, 0); /* fpoo */
4182
 
        stl(ptr + 24, 0); /* fpos */
4183
 
    } else {
4184
 
        /* 16 bit */
4185
 
        stw(ptr, env->fpuc);
4186
 
        stw(ptr + 2, fpus);
4187
 
        stw(ptr + 4, fptag);
4188
 
        stw(ptr + 6, 0);
4189
 
        stw(ptr + 8, 0);
4190
 
        stw(ptr + 10, 0);
4191
 
        stw(ptr + 12, 0);
4192
 
    }
4193
 
}
4194
 
 
4195
 
void helper_fldenv(target_ulong ptr, int data32)
4196
 
{
4197
 
    int i, fpus, fptag;
4198
 
 
4199
 
    if (data32) {
4200
 
        env->fpuc = lduw(ptr);
4201
 
        fpus = lduw(ptr + 4);
4202
 
        fptag = lduw(ptr + 8);
4203
 
    }
4204
 
    else {
4205
 
        env->fpuc = lduw(ptr);
4206
 
        fpus = lduw(ptr + 2);
4207
 
        fptag = lduw(ptr + 4);
4208
 
    }
4209
 
    env->fpstt = (fpus >> 11) & 7;
4210
 
    env->fpus = fpus & ~0x3800;
4211
 
    for(i = 0;i < 8; i++) {
4212
 
        env->fptags[i] = ((fptag & 3) == 3);
4213
 
        fptag >>= 2;
4214
 
    }
4215
 
}
4216
 
 
4217
 
void helper_fsave(target_ulong ptr, int data32)
4218
 
{
4219
 
    CPU86_LDouble tmp;
4220
 
    int i;
4221
 
 
4222
 
    helper_fstenv(ptr, data32);
4223
 
 
4224
 
    ptr += (14 << data32);
4225
 
    for(i = 0;i < 8; i++) {
4226
 
        tmp = ST(i);
4227
 
        helper_fstt(tmp, ptr);
4228
 
        ptr += 10;
4229
 
    }
4230
 
 
4231
 
    /* fninit */
4232
 
    env->fpus = 0;
4233
 
    env->fpstt = 0;
4234
 
    env->fpuc = 0x37f;
4235
 
    env->fptags[0] = 1;
4236
 
    env->fptags[1] = 1;
4237
 
    env->fptags[2] = 1;
4238
 
    env->fptags[3] = 1;
4239
 
    env->fptags[4] = 1;
4240
 
    env->fptags[5] = 1;
4241
 
    env->fptags[6] = 1;
4242
 
    env->fptags[7] = 1;
4243
 
}
4244
 
 
4245
 
void helper_frstor(target_ulong ptr, int data32)
4246
 
{
4247
 
    CPU86_LDouble tmp;
4248
 
    int i;
4249
 
 
4250
 
    helper_fldenv(ptr, data32);
4251
 
    ptr += (14 << data32);
4252
 
 
4253
 
    for(i = 0;i < 8; i++) {
4254
 
        tmp = helper_fldt(ptr);
4255
 
        ST(i) = tmp;
4256
 
        ptr += 10;
4257
 
    }
4258
 
}
4259
 
 
4260
 
void helper_fxsave(target_ulong ptr, int data64)
4261
 
{
4262
 
    int fpus, fptag, i, nb_xmm_regs;
4263
 
    CPU86_LDouble tmp;
4264
 
    target_ulong addr;
4265
 
 
4266
 
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4267
 
    fptag = 0;
4268
 
    for(i = 0; i < 8; i++) {
4269
 
        fptag |= (env->fptags[i] << i);
4270
 
    }
4271
 
    stw(ptr, env->fpuc);
4272
 
    stw(ptr + 2, fpus);
4273
 
    stw(ptr + 4, fptag ^ 0xff);
4274
 
#ifdef TARGET_X86_64
4275
 
    if (data64) {
4276
 
        stq(ptr + 0x08, 0); /* rip */
4277
 
        stq(ptr + 0x10, 0); /* rdp */
4278
 
    } else 
4279
 
#endif
4280
 
    {
4281
 
        stl(ptr + 0x08, 0); /* eip */
4282
 
        stl(ptr + 0x0c, 0); /* sel  */
4283
 
        stl(ptr + 0x10, 0); /* dp */
4284
 
        stl(ptr + 0x14, 0); /* sel  */
4285
 
    }
4286
 
 
4287
 
    addr = ptr + 0x20;
4288
 
    for(i = 0;i < 8; i++) {
4289
 
        tmp = ST(i);
4290
 
        helper_fstt(tmp, addr);
4291
 
        addr += 16;
4292
 
    }
4293
 
 
4294
 
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4295
 
        /* XXX: finish it */
4296
 
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4297
 
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4298
 
        if (env->hflags & HF_CS64_MASK)
4299
 
            nb_xmm_regs = 16;
4300
 
        else
4301
 
            nb_xmm_regs = 8;
4302
 
        addr = ptr + 0xa0;
4303
 
        for(i = 0; i < nb_xmm_regs; i++) {
4304
 
            stq(addr, env->xmm_regs[i].XMM_Q(0));
4305
 
            stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4306
 
            addr += 16;
4307
 
        }
4308
 
    }
4309
 
}
4310
 
 
4311
 
void helper_fxrstor(target_ulong ptr, int data64)
4312
 
{
4313
 
    int i, fpus, fptag, nb_xmm_regs;
4314
 
    CPU86_LDouble tmp;
4315
 
    target_ulong addr;
4316
 
 
4317
 
    env->fpuc = lduw(ptr);
4318
 
    fpus = lduw(ptr + 2);
4319
 
    fptag = lduw(ptr + 4);
4320
 
    env->fpstt = (fpus >> 11) & 7;
4321
 
    env->fpus = fpus & ~0x3800;
4322
 
    fptag ^= 0xff;
4323
 
    for(i = 0;i < 8; i++) {
4324
 
        env->fptags[i] = ((fptag >> i) & 1);
4325
 
    }
4326
 
 
4327
 
    addr = ptr + 0x20;
4328
 
    for(i = 0;i < 8; i++) {
4329
 
        tmp = helper_fldt(addr);
4330
 
        ST(i) = tmp;
4331
 
        addr += 16;
4332
 
    }
4333
 
 
4334
 
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4335
 
        /* XXX: finish it */
4336
 
        env->mxcsr = ldl(ptr + 0x18);
4337
 
        //ldl(ptr + 0x1c);
4338
 
        if (env->hflags & HF_CS64_MASK)
4339
 
            nb_xmm_regs = 16;
4340
 
        else
4341
 
            nb_xmm_regs = 8;
4342
 
        addr = ptr + 0xa0;
4343
 
        for(i = 0; i < nb_xmm_regs; i++) {
4344
 
            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4345
 
            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4346
 
            addr += 16;
4347
 
        }
4348
 
    }
4349
 
}
4350
 
 
4351
 
#ifndef USE_X86LDOUBLE
4352
 
 
4353
 
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4354
 
{
4355
 
    CPU86_LDoubleU temp;
4356
 
    int e;
4357
 
 
4358
 
    temp.d = f;
4359
 
    /* mantissa */
4360
 
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4361
 
    /* exponent + sign */
4362
 
    e = EXPD(temp) - EXPBIAS + 16383;
4363
 
    e |= SIGND(temp) >> 16;
4364
 
    *pexp = e;
4365
 
}
4366
 
 
4367
 
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4368
 
{
4369
 
    CPU86_LDoubleU temp;
4370
 
    int e;
4371
 
    uint64_t ll;
4372
 
 
4373
 
    /* XXX: handle overflow ? */
4374
 
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4375
 
    e |= (upper >> 4) & 0x800; /* sign */
4376
 
    ll = (mant >> 11) & ((1LL << 52) - 1);
4377
 
#ifdef __arm__
4378
 
    temp.l.upper = (e << 20) | (ll >> 32);
4379
 
    temp.l.lower = ll;
4380
 
#else
4381
 
    temp.ll = ll | ((uint64_t)e << 52);
4382
 
#endif
4383
 
    return temp.d;
4384
 
}
4385
 
 
4386
 
#else
4387
 
 
4388
 
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4389
 
{
4390
 
    CPU86_LDoubleU temp;
4391
 
 
4392
 
    temp.d = f;
4393
 
    *pmant = temp.l.lower;
4394
 
    *pexp = temp.l.upper;
4395
 
}
4396
 
 
4397
 
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4398
 
{
4399
 
    CPU86_LDoubleU temp;
4400
 
 
4401
 
    temp.l.upper = upper;
4402
 
    temp.l.lower = mant;
4403
 
    return temp.d;
4404
 
}
4405
 
#endif
4406
 
 
4407
 
#ifdef TARGET_X86_64
4408
 
 
4409
 
//#define DEBUG_MULDIV
4410
 
 
4411
 
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4412
 
{
4413
 
    *plow += a;
4414
 
    /* carry test */
4415
 
    if (*plow < a)
4416
 
        (*phigh)++;
4417
 
    *phigh += b;
4418
 
}
4419
 
 
4420
 
static void neg128(uint64_t *plow, uint64_t *phigh)
4421
 
{
4422
 
    *plow = ~ *plow;
4423
 
    *phigh = ~ *phigh;
4424
 
    add128(plow, phigh, 1, 0);
4425
 
}
4426
 
 
4427
 
/* return TRUE if overflow */
4428
 
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4429
 
{
4430
 
    uint64_t q, r, a1, a0;
4431
 
    int i, qb, ab;
4432
 
 
4433
 
    a0 = *plow;
4434
 
    a1 = *phigh;
4435
 
    if (a1 == 0) {
4436
 
        q = a0 / b;
4437
 
        r = a0 % b;
4438
 
        *plow = q;
4439
 
        *phigh = r;
4440
 
    } else {
4441
 
        if (a1 >= b)
4442
 
            return 1;
4443
 
        /* XXX: use a better algorithm */
4444
 
        for(i = 0; i < 64; i++) {
4445
 
            ab = a1 >> 63;
4446
 
            a1 = (a1 << 1) | (a0 >> 63);
4447
 
            if (ab || a1 >= b) {
4448
 
                a1 -= b;
4449
 
                qb = 1;
4450
 
            } else {
4451
 
                qb = 0;
4452
 
            }
4453
 
            a0 = (a0 << 1) | qb;
4454
 
        }
4455
 
#if defined(DEBUG_MULDIV)
4456
 
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4457
 
               *phigh, *plow, b, a0, a1);
4458
 
#endif
4459
 
        *plow = a0;
4460
 
        *phigh = a1;
4461
 
    }
4462
 
    return 0;
4463
 
}
4464
 
 
4465
 
/* return TRUE if overflow */
4466
 
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4467
 
{
4468
 
    int sa, sb;
4469
 
    sa = ((int64_t)*phigh < 0);
4470
 
    if (sa)
4471
 
        neg128(plow, phigh);
4472
 
    sb = (b < 0);
4473
 
    if (sb)
4474
 
        b = -b;
4475
 
    if (div64(plow, phigh, b) != 0)
4476
 
        return 1;
4477
 
    if (sa ^ sb) {
4478
 
        if (*plow > (1ULL << 63))
4479
 
            return 1;
4480
 
        *plow = - *plow;
4481
 
    } else {
4482
 
        if (*plow >= (1ULL << 63))
4483
 
            return 1;
4484
 
    }
4485
 
    if (sa)
4486
 
        *phigh = - *phigh;
4487
 
    return 0;
4488
 
}
4489
 
 
4490
 
void helper_mulq_EAX_T0(target_ulong t0)
4491
 
{
4492
 
    uint64_t r0, r1;
4493
 
 
4494
 
    mulu64(&r0, &r1, EAX, t0);
4495
 
    EAX = r0;
4496
 
    EDX = r1;
4497
 
    CC_DST = r0;
4498
 
    CC_SRC = r1;
4499
 
}
4500
 
 
4501
 
void helper_imulq_EAX_T0(target_ulong t0)
4502
 
{
4503
 
    uint64_t r0, r1;
4504
 
 
4505
 
    muls64(&r0, &r1, EAX, t0);
4506
 
    EAX = r0;
4507
 
    EDX = r1;
4508
 
    CC_DST = r0;
4509
 
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4510
 
}
4511
 
 
4512
 
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4513
 
{
4514
 
    uint64_t r0, r1;
4515
 
 
4516
 
    muls64(&r0, &r1, t0, t1);
4517
 
    CC_DST = r0;
4518
 
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4519
 
    return r0;
4520
 
}
4521
 
 
4522
 
void helper_divq_EAX(target_ulong t0)
4523
 
{
4524
 
    uint64_t r0, r1;
4525
 
    if (t0 == 0) {
4526
 
        raise_exception(EXCP00_DIVZ);
4527
 
    }
4528
 
    r0 = EAX;
4529
 
    r1 = EDX;
4530
 
    if (div64(&r0, &r1, t0))
4531
 
        raise_exception(EXCP00_DIVZ);
4532
 
    EAX = r0;
4533
 
    EDX = r1;
4534
 
}
4535
 
 
4536
 
void helper_idivq_EAX(target_ulong t0)
4537
 
{
4538
 
    uint64_t r0, r1;
4539
 
    if (t0 == 0) {
4540
 
        raise_exception(EXCP00_DIVZ);
4541
 
    }
4542
 
    r0 = EAX;
4543
 
    r1 = EDX;
4544
 
    if (idiv64(&r0, &r1, t0))
4545
 
        raise_exception(EXCP00_DIVZ);
4546
 
    EAX = r0;
4547
 
    EDX = r1;
4548
 
}
4549
 
#endif
4550
 
 
4551
 
void helper_hlt(void)
4552
 
{
4553
 
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4554
 
    
4555
 
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4556
 
    env->halted = 1;
4557
 
    env->exception_index = EXCP_HLT;
4558
 
    cpu_loop_exit();
4559
 
}
4560
 
 
4561
 
void helper_monitor(target_ulong ptr)
4562
 
{
4563
 
    if ((uint32_t)ECX != 0)
4564
 
        raise_exception(EXCP0D_GPF);
4565
 
    /* XXX: store address ? */
4566
 
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4567
 
}
4568
 
 
4569
 
void helper_mwait(void)
4570
 
{
4571
 
    if ((uint32_t)ECX != 0)
4572
 
        raise_exception(EXCP0D_GPF);
4573
 
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4574
 
    /* XXX: not complete but not completely erroneous */
4575
 
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4576
 
        /* more than one CPU: do not sleep because another CPU may
4577
 
           wake this one */
4578
 
    } else {
4579
 
        helper_hlt();
4580
 
    }
4581
 
}
4582
 
 
4583
 
void helper_debug(void)
4584
 
{
4585
 
    env->exception_index = EXCP_DEBUG;
4586
 
    cpu_loop_exit();
4587
 
}
4588
 
 
4589
 
void helper_raise_interrupt(int intno, int next_eip_addend)
4590
 
{
4591
 
    raise_interrupt(intno, 1, 0, next_eip_addend);
4592
 
}
4593
 
 
4594
 
void helper_raise_exception(int exception_index)
4595
 
{
4596
 
    raise_exception(exception_index);
4597
 
}
4598
 
 
4599
 
void helper_cli(void)
4600
 
{
4601
 
    env->eflags &= ~IF_MASK;
4602
 
}
4603
 
 
4604
 
void helper_sti(void)
4605
 
{
4606
 
    env->eflags |= IF_MASK;
4607
 
}
4608
 
 
4609
 
#if 0
4610
 
/* vm86plus instructions */
4611
 
void helper_cli_vm(void)
4612
 
{
4613
 
    env->eflags &= ~VIF_MASK;
4614
 
}
4615
 
 
4616
 
void helper_sti_vm(void)
4617
 
{
4618
 
    env->eflags |= VIF_MASK;
4619
 
    if (env->eflags & VIP_MASK) {
4620
 
        raise_exception(EXCP0D_GPF);
4621
 
    }
4622
 
}
4623
 
#endif
4624
 
 
4625
 
void helper_set_inhibit_irq(void)
4626
 
{
4627
 
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4628
 
}
4629
 
 
4630
 
void helper_reset_inhibit_irq(void)
4631
 
{
4632
 
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4633
 
}
4634
 
 
4635
 
void helper_boundw(target_ulong a0, int v)
4636
 
{
4637
 
    int low, high;
4638
 
    low = ldsw(a0);
4639
 
    high = ldsw(a0 + 2);
4640
 
    v = (int16_t)v;
4641
 
    if (v < low || v > high) {
4642
 
        raise_exception(EXCP05_BOUND);
4643
 
    }
4644
 
    FORCE_RET();
4645
 
}
4646
 
 
4647
 
void helper_boundl(target_ulong a0, int v)
4648
 
{
4649
 
    int low, high;
4650
 
    low = ldl(a0);
4651
 
    high = ldl(a0 + 4);
4652
 
    if (v < low || v > high) {
4653
 
        raise_exception(EXCP05_BOUND);
4654
 
    }
4655
 
    FORCE_RET();
4656
 
}
4657
 
 
4658
 
static float approx_rsqrt(float a)
4659
 
{
4660
 
    return 1.0 / sqrt(a);
4661
 
}
4662
 
 
4663
 
static float approx_rcp(float a)
4664
 
{
4665
 
    return 1.0 / a;
4666
 
}
4667
 
 
4668
 
#if !defined(CONFIG_USER_ONLY)
4669
 
 
4670
 
#define MMUSUFFIX _mmu
4671
 
 
4672
 
#define SHIFT 0
4673
 
#include "softmmu_template.h"
4674
 
 
4675
 
#define SHIFT 1
4676
 
#include "softmmu_template.h"
4677
 
 
4678
 
#define SHIFT 2
4679
 
#include "softmmu_template.h"
4680
 
 
4681
 
#define SHIFT 3
4682
 
#include "softmmu_template.h"
4683
 
 
4684
 
#endif
4685
 
 
4686
 
/* try to fill the TLB and return an exception if error. If retaddr is
4687
 
   NULL, it means that the function was called in C code (i.e. not
4688
 
   from generated code or from helper.c) */
4689
 
/* XXX: fix it to restore all registers */
4690
 
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4691
 
{
4692
 
    TranslationBlock *tb;
4693
 
    int ret;
4694
 
    unsigned long pc;
4695
 
    CPUX86State *saved_env;
4696
 
 
4697
 
    /* XXX: hack to restore env in all cases, even if not called from
4698
 
       generated code */
4699
 
    saved_env = env;
4700
 
    env = cpu_single_env;
4701
 
 
4702
 
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4703
 
    if (ret) {
4704
 
        if (retaddr) {
4705
 
            /* now we have a real cpu fault */
4706
 
            pc = (unsigned long)retaddr;
4707
 
            tb = tb_find_pc(pc);
4708
 
            if (tb) {
4709
 
                /* the PC is inside the translated code. It means that we have
4710
 
                   a virtual CPU fault */
4711
 
                cpu_restore_state(tb, env, pc, NULL);
4712
 
            }
4713
 
        }
4714
 
        raise_exception_err(env->exception_index, env->error_code);
4715
 
    }
4716
 
    env = saved_env;
4717
 
}
4718
 
 
4719
 
 
4720
 
/* Secure Virtual Machine helpers */
4721
 
 
4722
 
#if defined(CONFIG_USER_ONLY)
4723
 
 
4724
 
void helper_vmrun(int aflag)
4725
 
4726
 
}
4727
 
void helper_vmmcall(void) 
4728
 
4729
 
}
4730
 
void helper_vmload(int aflag)
4731
 
4732
 
}
4733
 
void helper_vmsave(int aflag)
4734
 
4735
 
}
4736
 
void helper_stgi(void)
4737
 
{
4738
 
}
4739
 
void helper_clgi(void)
4740
 
{
4741
 
}
4742
 
void helper_skinit(void) 
4743
 
4744
 
}
4745
 
void helper_invlpga(int aflag)
4746
 
4747
 
}
4748
 
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4749
 
4750
 
}
4751
 
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4752
 
{
4753
 
}
4754
 
 
4755
 
void helper_svm_check_io(uint32_t port, uint32_t param, 
4756
 
                         uint32_t next_eip_addend)
4757
 
{
4758
 
}
4759
 
#else
4760
 
 
4761
 
static inline void svm_save_seg(target_phys_addr_t addr,
4762
 
                                const SegmentCache *sc)
4763
 
{
4764
 
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4765
 
             sc->selector);
4766
 
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4767
 
             sc->base);
4768
 
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4769
 
             sc->limit);
4770
 
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4771
 
             (sc->flags >> 8) | ((sc->flags >> 12) & 0x0f00));
4772
 
}
4773
 
                                
4774
 
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4775
 
{
4776
 
    unsigned int flags;
4777
 
 
4778
 
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4779
 
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4780
 
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4781
 
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4782
 
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4783
 
}
4784
 
 
4785
 
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4786
 
                                      CPUState *env, int seg_reg)
4787
 
{
4788
 
    SegmentCache sc1, *sc = &sc1;
4789
 
    svm_load_seg(addr, sc);
4790
 
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4791
 
                           sc->base, sc->limit, sc->flags);
4792
 
}
4793
 
 
4794
 
void helper_vmrun(int aflag)
4795
 
{
4796
 
    target_ulong addr;
4797
 
    uint32_t event_inj;
4798
 
    uint32_t int_ctl;
4799
 
 
4800
 
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4801
 
 
4802
 
    if (aflag == 2)
4803
 
        addr = EAX;
4804
 
    else
4805
 
        addr = (uint32_t)EAX;
4806
 
 
4807
 
    if (loglevel & CPU_LOG_TB_IN_ASM)
4808
 
        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4809
 
 
4810
 
    env->vm_vmcb = addr;
4811
 
 
4812
 
    /* save the current CPU state in the hsave page */
4813
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4814
 
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4815
 
 
4816
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4817
 
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4818
 
 
4819
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4820
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4821
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4822
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4823
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8), env->cr[8]);
4824
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4825
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4826
 
 
4827
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4828
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4829
 
 
4830
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4831
 
                  &env->segs[R_ES]);
4832
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4833
 
                 &env->segs[R_CS]);
4834
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4835
 
                 &env->segs[R_SS]);
4836
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4837
 
                 &env->segs[R_DS]);
4838
 
 
4839
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP);
4840
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4841
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4842
 
 
4843
 
    /* load the interception bitmaps so we do not need to access the
4844
 
       vmcb in svm mode */
4845
 
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4846
 
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4847
 
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4848
 
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4849
 
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4850
 
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4851
 
 
4852
 
    /* enable intercepts */
4853
 
    env->hflags |= HF_SVMI_MASK;
4854
 
 
4855
 
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4856
 
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4857
 
 
4858
 
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4859
 
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4860
 
 
4861
 
    /* clear exit_info_2 so we behave like the real hardware */
4862
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
4863
 
 
4864
 
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4865
 
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4866
 
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4867
 
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4868
 
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4869
 
    if (int_ctl & V_INTR_MASKING_MASK) {
4870
 
        env->cr[8] = int_ctl & V_TPR_MASK;
4871
 
        cpu_set_apic_tpr(env, env->cr[8]);
4872
 
        if (env->eflags & IF_MASK)
4873
 
            env->hflags |= HF_HIF_MASK;
4874
 
    }
4875
 
 
4876
 
#ifdef TARGET_X86_64
4877
 
    cpu_load_efer(env, 
4878
 
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4879
 
#endif
4880
 
    env->eflags = 0;
4881
 
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4882
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4883
 
    CC_OP = CC_OP_EFLAGS;
4884
 
 
4885
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4886
 
                       env, R_ES);
4887
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4888
 
                       env, R_CS);
4889
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4890
 
                       env, R_SS);
4891
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4892
 
                       env, R_DS);
4893
 
 
4894
 
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4895
 
    env->eip = EIP;
4896
 
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4897
 
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4898
 
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4899
 
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4900
 
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4901
 
 
4902
 
    /* FIXME: guest state consistency checks */
4903
 
 
4904
 
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4905
 
        case TLB_CONTROL_DO_NOTHING:
4906
 
            break;
4907
 
        case TLB_CONTROL_FLUSH_ALL_ASID:
4908
 
            /* FIXME: this is not 100% correct but should work for now */
4909
 
            tlb_flush(env, 1);
4910
 
        break;
4911
 
    }
4912
 
 
4913
 
    helper_stgi();
4914
 
 
4915
 
    /* maybe we need to inject an event */
4916
 
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4917
 
    if (event_inj & SVM_EVTINJ_VALID) {
4918
 
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4919
 
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4920
 
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4921
 
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4922
 
 
4923
 
        if (loglevel & CPU_LOG_TB_IN_ASM)
4924
 
            fprintf(logfile, "Injecting(%#hx): ", valid_err);
4925
 
        /* FIXME: need to implement valid_err */
4926
 
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4927
 
        case SVM_EVTINJ_TYPE_INTR:
4928
 
                env->exception_index = vector;
4929
 
                env->error_code = event_inj_err;
4930
 
                env->exception_is_int = 0;
4931
 
                env->exception_next_eip = -1;
4932
 
                if (loglevel & CPU_LOG_TB_IN_ASM)
4933
 
                    fprintf(logfile, "INTR");
4934
 
                break;
4935
 
        case SVM_EVTINJ_TYPE_NMI:
4936
 
                env->exception_index = vector;
4937
 
                env->error_code = event_inj_err;
4938
 
                env->exception_is_int = 0;
4939
 
                env->exception_next_eip = EIP;
4940
 
                if (loglevel & CPU_LOG_TB_IN_ASM)
4941
 
                    fprintf(logfile, "NMI");
4942
 
                break;
4943
 
        case SVM_EVTINJ_TYPE_EXEPT:
4944
 
                env->exception_index = vector;
4945
 
                env->error_code = event_inj_err;
4946
 
                env->exception_is_int = 0;
4947
 
                env->exception_next_eip = -1;
4948
 
                if (loglevel & CPU_LOG_TB_IN_ASM)
4949
 
                    fprintf(logfile, "EXEPT");
4950
 
                break;
4951
 
        case SVM_EVTINJ_TYPE_SOFT:
4952
 
                env->exception_index = vector;
4953
 
                env->error_code = event_inj_err;
4954
 
                env->exception_is_int = 1;
4955
 
                env->exception_next_eip = EIP;
4956
 
                if (loglevel & CPU_LOG_TB_IN_ASM)
4957
 
                    fprintf(logfile, "SOFT");
4958
 
                break;
4959
 
        }
4960
 
        if (loglevel & CPU_LOG_TB_IN_ASM)
4961
 
            fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
4962
 
    }
4963
 
    if ((int_ctl & V_IRQ_MASK) || 
4964
 
        (env->intercept & (1ULL << (SVM_EXIT_INTR - SVM_EXIT_INTR)))) {
4965
 
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4966
 
    }
4967
 
 
4968
 
    cpu_loop_exit();
4969
 
}
4970
 
 
4971
 
void helper_vmmcall(void)
4972
 
{
4973
 
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
4974
 
    raise_exception(EXCP06_ILLOP);
4975
 
}
4976
 
 
4977
 
void helper_vmload(int aflag)
4978
 
{
4979
 
    target_ulong addr;
4980
 
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
4981
 
 
4982
 
    if (aflag == 2)
4983
 
        addr = EAX;
4984
 
    else
4985
 
        addr = (uint32_t)EAX;
4986
 
 
4987
 
    if (loglevel & CPU_LOG_TB_IN_ASM)
4988
 
        fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4989
 
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4990
 
                env->segs[R_FS].base);
4991
 
 
4992
 
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
4993
 
                       env, R_FS);
4994
 
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
4995
 
                       env, R_GS);
4996
 
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
4997
 
                 &env->tr);
4998
 
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
4999
 
                 &env->ldt);
5000
 
 
5001
 
#ifdef TARGET_X86_64
5002
 
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
5003
 
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
5004
 
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
5005
 
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
5006
 
#endif
5007
 
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
5008
 
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
5009
 
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
5010
 
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
5011
 
}
5012
 
 
5013
 
void helper_vmsave(int aflag)
5014
 
{
5015
 
    target_ulong addr;
5016
 
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5017
 
 
5018
 
    if (aflag == 2)
5019
 
        addr = EAX;
5020
 
    else
5021
 
        addr = (uint32_t)EAX;
5022
 
 
5023
 
    if (loglevel & CPU_LOG_TB_IN_ASM)
5024
 
        fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5025
 
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5026
 
                env->segs[R_FS].base);
5027
 
 
5028
 
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5029
 
                 &env->segs[R_FS]);
5030
 
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5031
 
                 &env->segs[R_GS]);
5032
 
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5033
 
                 &env->tr);
5034
 
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5035
 
                 &env->ldt);
5036
 
 
5037
 
#ifdef TARGET_X86_64
5038
 
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
5039
 
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
5040
 
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
5041
 
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
5042
 
#endif
5043
 
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
5044
 
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
5045
 
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
5046
 
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
5047
 
}
5048
 
 
5049
 
void helper_stgi(void)
5050
 
{
5051
 
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5052
 
    env->hflags |= HF_GIF_MASK;
5053
 
}
5054
 
 
5055
 
void helper_clgi(void)
5056
 
{
5057
 
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5058
 
    env->hflags &= ~HF_GIF_MASK;
5059
 
}
5060
 
 
5061
 
void helper_skinit(void)
5062
 
{
5063
 
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5064
 
    /* XXX: not implemented */
5065
 
    raise_exception(EXCP06_ILLOP);
5066
 
}
5067
 
 
5068
 
void helper_invlpga(int aflag)
5069
 
{
5070
 
    target_ulong addr;
5071
 
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5072
 
    
5073
 
    if (aflag == 2)
5074
 
        addr = EAX;
5075
 
    else
5076
 
        addr = (uint32_t)EAX;
5077
 
 
5078
 
    /* XXX: could use the ASID to see if it is needed to do the
5079
 
       flush */
5080
 
    tlb_flush_page(env, addr);
5081
 
}
5082
 
 
5083
 
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5084
 
{
5085
 
    if (likely(!(env->hflags & HF_SVMI_MASK)))
5086
 
        return;
5087
 
    switch(type) {
5088
 
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5089
 
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5090
 
            helper_vmexit(type, param);
5091
 
        }
5092
 
        break;
5093
 
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5094
 
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
5095
 
            helper_vmexit(type, param);
5096
 
        }
5097
 
        break;
5098
 
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
5099
 
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
5100
 
            helper_vmexit(type, param);
5101
 
        }
5102
 
        break;
5103
 
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
5104
 
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
5105
 
            helper_vmexit(type, param);
5106
 
        }
5107
 
        break;
5108
 
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
5109
 
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
5110
 
            helper_vmexit(type, param);
5111
 
        }
5112
 
        break;
5113
 
    case SVM_EXIT_MSR:
5114
 
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5115
 
            /* FIXME: this should be read in at vmrun (faster this way?) */
5116
 
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5117
 
            uint32_t t0, t1;
5118
 
            switch((uint32_t)ECX) {
5119
 
            case 0 ... 0x1fff:
5120
 
                t0 = (ECX * 2) % 8;
5121
 
                t1 = ECX / 8;
5122
 
                break;
5123
 
            case 0xc0000000 ... 0xc0001fff:
5124
 
                t0 = (8192 + ECX - 0xc0000000) * 2;
5125
 
                t1 = (t0 / 8);
5126
 
                t0 %= 8;
5127
 
                break;
5128
 
            case 0xc0010000 ... 0xc0011fff:
5129
 
                t0 = (16384 + ECX - 0xc0010000) * 2;
5130
 
                t1 = (t0 / 8);
5131
 
                t0 %= 8;
5132
 
                break;
5133
 
            default:
5134
 
                helper_vmexit(type, param);
5135
 
                t0 = 0;
5136
 
                t1 = 0;
5137
 
                break;
5138
 
            }
5139
 
            if (ldub_phys(addr + t1) & ((1 << param) << t0))
5140
 
                helper_vmexit(type, param);
5141
 
        }
5142
 
        break;
5143
 
    default:
5144
 
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5145
 
            helper_vmexit(type, param);
5146
 
        }
5147
 
        break;
5148
 
    }
5149
 
}
5150
 
 
5151
 
void helper_svm_check_io(uint32_t port, uint32_t param, 
5152
 
                         uint32_t next_eip_addend)
5153
 
{
5154
 
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5155
 
        /* FIXME: this should be read in at vmrun (faster this way?) */
5156
 
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5157
 
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5158
 
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5159
 
            /* next EIP */
5160
 
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5161
 
                     env->eip + next_eip_addend);
5162
 
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5163
 
        }
5164
 
    }
5165
 
}
5166
 
 
5167
 
/* Note: currently only 32 bits of exit_code are used */
5168
 
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5169
 
{
5170
 
    uint32_t int_ctl;
5171
 
 
5172
 
    if (loglevel & CPU_LOG_TB_IN_ASM)
5173
 
        fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5174
 
                exit_code, exit_info_1,
5175
 
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5176
 
                EIP);
5177
 
 
5178
 
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5179
 
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5180
 
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5181
 
    } else {
5182
 
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5183
 
    }
5184
 
 
5185
 
    /* Save the VM state in the vmcb */
5186
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5187
 
                 &env->segs[R_ES]);
5188
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5189
 
                 &env->segs[R_CS]);
5190
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5191
 
                 &env->segs[R_SS]);
5192
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5193
 
                 &env->segs[R_DS]);
5194
 
 
5195
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5196
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5197
 
 
5198
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5199
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5200
 
 
5201
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5202
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5203
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5204
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5205
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5206
 
 
5207
 
    if ((int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl))) & V_INTR_MASKING_MASK) {
5208
 
        int_ctl &= ~V_TPR_MASK;
5209
 
        int_ctl |= env->cr[8] & V_TPR_MASK;
5210
 
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5211
 
    }
5212
 
 
5213
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5214
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5215
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5216
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5217
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5218
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5219
 
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5220
 
 
5221
 
    /* Reload the host state from vm_hsave */
5222
 
    env->hflags &= ~HF_HIF_MASK;
5223
 
    env->hflags &= ~HF_SVMI_MASK;
5224
 
    env->intercept = 0;
5225
 
    env->intercept_exceptions = 0;
5226
 
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5227
 
 
5228
 
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5229
 
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5230
 
 
5231
 
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5232
 
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5233
 
 
5234
 
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5235
 
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5236
 
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5237
 
    if (int_ctl & V_INTR_MASKING_MASK) {
5238
 
        env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8));
5239
 
        cpu_set_apic_tpr(env, env->cr[8]);
5240
 
    }
5241
 
    /* we need to set the efer after the crs so the hidden flags get
5242
 
       set properly */
5243
 
#ifdef TARGET_X86_64
5244
 
    cpu_load_efer(env, 
5245
 
                  ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
5246
 
#endif
5247
 
 
5248
 
    env->eflags = 0;
5249
 
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5250
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5251
 
    CC_OP = CC_OP_EFLAGS;
5252
 
 
5253
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5254
 
                       env, R_ES);
5255
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5256
 
                       env, R_CS);
5257
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5258
 
                       env, R_SS);
5259
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5260
 
                       env, R_DS);
5261
 
 
5262
 
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5263
 
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5264
 
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5265
 
 
5266
 
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5267
 
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5268
 
 
5269
 
    /* other setups */
5270
 
    cpu_x86_set_cpl(env, 0);
5271
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5272
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5273
 
 
5274
 
    helper_clgi();
5275
 
    /* FIXME: Resets the current ASID register to zero (host ASID). */
5276
 
 
5277
 
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5278
 
 
5279
 
    /* Clears the TSC_OFFSET inside the processor. */
5280
 
 
5281
 
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5282
 
       from the page table indicated the host's CR3. If the PDPEs contain
5283
 
       illegal state, the processor causes a shutdown. */
5284
 
 
5285
 
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5286
 
    env->cr[0] |= CR0_PE_MASK;
5287
 
    env->eflags &= ~VM_MASK;
5288
 
 
5289
 
    /* Disables all breakpoints in the host DR7 register. */
5290
 
 
5291
 
    /* Checks the reloaded host state for consistency. */
5292
 
 
5293
 
    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5294
 
       host's code segment or non-canonical (in the case of long mode), a
5295
 
       #GP fault is delivered inside the host.) */
5296
 
 
5297
 
    /* remove any pending exception */
5298
 
    env->exception_index = -1;
5299
 
    env->error_code = 0;
5300
 
    env->old_exception = -1;
5301
 
 
5302
 
    cpu_loop_exit();
5303
 
}
5304
 
 
5305
 
#endif
5306
 
 
5307
 
/* MMX/SSE */
5308
 
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5309
 
void helper_enter_mmx(void)
5310
 
{
5311
 
    env->fpstt = 0;
5312
 
    *(uint32_t *)(env->fptags) = 0;
5313
 
    *(uint32_t *)(env->fptags + 4) = 0;
5314
 
}
5315
 
 
5316
 
void helper_emms(void)
5317
 
{
5318
 
    /* set to empty state */
5319
 
    *(uint32_t *)(env->fptags) = 0x01010101;
5320
 
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5321
 
}
5322
 
 
5323
 
/* XXX: suppress */
5324
 
void helper_movq(uint64_t *d, uint64_t *s)
5325
 
{
5326
 
    *d = *s;
5327
 
}
5328
 
 
5329
 
#define SHIFT 0
5330
 
#include "ops_sse.h"
5331
 
 
5332
 
#define SHIFT 1
5333
 
#include "ops_sse.h"
5334
 
 
5335
 
#define SHIFT 0
5336
 
#include "helper_template.h"
5337
 
#undef SHIFT
5338
 
 
5339
 
#define SHIFT 1
5340
 
#include "helper_template.h"
5341
 
#undef SHIFT
5342
 
 
5343
 
#define SHIFT 2
5344
 
#include "helper_template.h"
5345
 
#undef SHIFT
5346
 
 
5347
 
#ifdef TARGET_X86_64
5348
 
 
5349
 
#define SHIFT 3
5350
 
#include "helper_template.h"
5351
 
#undef SHIFT
5352
 
 
5353
 
#endif
5354
 
 
5355
 
/* bit operations */
5356
 
target_ulong helper_bsf(target_ulong t0)
5357
 
{
5358
 
    int count;
5359
 
    target_ulong res;
5360
 
 
5361
 
    res = t0;
5362
 
    count = 0;
5363
 
    while ((res & 1) == 0) {
5364
 
        count++;
5365
 
        res >>= 1;
5366
 
    }
5367
 
    return count;
5368
 
}
5369
 
 
5370
 
target_ulong helper_bsr(target_ulong t0)
5371
 
{
5372
 
    int count;
5373
 
    target_ulong res, mask;
5374
 
    
5375
 
    res = t0;
5376
 
    count = TARGET_LONG_BITS - 1;
5377
 
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5378
 
    while ((res & mask) == 0) {
5379
 
        count--;
5380
 
        res <<= 1;
5381
 
    }
5382
 
    return count;
5383
 
}
5384
 
 
5385
 
 
5386
 
static int compute_all_eflags(void)
5387
 
{
5388
 
    return CC_SRC;
5389
 
}
5390
 
 
5391
 
static int compute_c_eflags(void)
5392
 
{
5393
 
    return CC_SRC & CC_C;
5394
 
}
5395
 
 
5396
 
CCTable cc_table[CC_OP_NB] = {
5397
 
    [CC_OP_DYNAMIC] = { /* should never happen */ },
5398
 
 
5399
 
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
5400
 
 
5401
 
    [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
5402
 
    [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
5403
 
    [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
5404
 
 
5405
 
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
5406
 
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
5407
 
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
5408
 
 
5409
 
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
5410
 
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
5411
 
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
5412
 
 
5413
 
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
5414
 
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
5415
 
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
5416
 
 
5417
 
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
5418
 
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
5419
 
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
5420
 
 
5421
 
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
5422
 
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
5423
 
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
5424
 
 
5425
 
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
5426
 
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
5427
 
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
5428
 
 
5429
 
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
5430
 
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
5431
 
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
5432
 
 
5433
 
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
5434
 
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
5435
 
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
5436
 
 
5437
 
    [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
5438
 
    [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
5439
 
    [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
5440
 
 
5441
 
#ifdef TARGET_X86_64
5442
 
    [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
5443
 
 
5444
 
    [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq  },
5445
 
 
5446
 
    [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq  },
5447
 
 
5448
 
    [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq  },
5449
 
 
5450
 
    [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq  },
5451
 
 
5452
 
    [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
5453
 
 
5454
 
    [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
5455
 
 
5456
 
    [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
5457
 
 
5458
 
    [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
5459
 
 
5460
 
    [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
5461
 
#endif
5462
 
};
5463