Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ dc1ded53

History | View | Annotate | Download (156.6 kB)

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., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20
#define CPU_NO_GLOBAL_REGS
21
#include "exec.h"
22
#include "exec-all.h"
23
#include "host-utils.h"
24

    
25
//#define DEBUG_PCALL
26

    
27

    
28
#ifdef DEBUG_PCALL
29
#  define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
30
#  define LOG_PCALL_STATE(env) \
31
          log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
32
#else
33
#  define LOG_PCALL(...) do { } while (0)
34
#  define LOG_PCALL_STATE(env) do { } while (0)
35
#endif
36

    
37

    
38
#if 0
39
#define raise_exception_err(a, b)\
40
do {\
41
    qemu_log("raise_exception line=%d\n", __LINE__);\
42
    (raise_exception_err)(a, b);\
43
} while (0)
44
#endif
45

    
46
static const uint8_t parity_table[256] = {
47
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
48
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
49
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
51
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
52
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
53
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
61
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
62
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
63
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
64
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
65
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
66
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
67
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
68
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
69
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
70
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
71
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
72
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
73
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
74
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
75
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
76
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
77
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
78
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
79
};
80

    
81
/* modulo 17 table */
82
static const uint8_t rclw_table[32] = {
83
    0, 1, 2, 3, 4, 5, 6, 7,
84
    8, 9,10,11,12,13,14,15,
85
   16, 0, 1, 2, 3, 4, 5, 6,
86
    7, 8, 9,10,11,12,13,14,
87
};
88

    
89
/* modulo 9 table */
90
static const uint8_t rclb_table[32] = {
91
    0, 1, 2, 3, 4, 5, 6, 7,
92
    8, 0, 1, 2, 3, 4, 5, 6,
93
    7, 8, 0, 1, 2, 3, 4, 5,
94
    6, 7, 8, 0, 1, 2, 3, 4,
95
};
96

    
97
static const CPU86_LDouble f15rk[7] =
98
{
99
    0.00000000000000000000L,
100
    1.00000000000000000000L,
101
    3.14159265358979323851L,  /*pi*/
102
    0.30102999566398119523L,  /*lg2*/
103
    0.69314718055994530943L,  /*ln2*/
104
    1.44269504088896340739L,  /*l2e*/
105
    3.32192809488736234781L,  /*l2t*/
106
};
107

    
108
/* broken thread support */
109

    
110
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
111

    
112
void helper_lock(void)
113
{
114
    spin_lock(&global_cpu_lock);
115
}
116

    
117
void helper_unlock(void)
118
{
119
    spin_unlock(&global_cpu_lock);
120
}
121

    
122
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
123
{
124
    load_eflags(t0, update_mask);
125
}
126

    
127
target_ulong helper_read_eflags(void)
128
{
129
    uint32_t eflags;
130
    eflags = helper_cc_compute_all(CC_OP);
131
    eflags |= (DF & DF_MASK);
132
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
133
    return eflags;
134
}
135

    
136
/* return non zero if error */
137
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
138
                               int selector)
139
{
140
    SegmentCache *dt;
141
    int index;
142
    target_ulong ptr;
143

    
144
    if (selector & 0x4)
145
        dt = &env->ldt;
146
    else
147
        dt = &env->gdt;
148
    index = selector & ~7;
149
    if ((index + 7) > dt->limit)
150
        return -1;
151
    ptr = dt->base + index;
152
    *e1_ptr = ldl_kernel(ptr);
153
    *e2_ptr = ldl_kernel(ptr + 4);
154
    return 0;
155
}
156

    
157
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
158
{
159
    unsigned int limit;
160
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
161
    if (e2 & DESC_G_MASK)
162
        limit = (limit << 12) | 0xfff;
163
    return limit;
164
}
165

    
166
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
167
{
168
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
169
}
170

    
171
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
172
{
173
    sc->base = get_seg_base(e1, e2);
174
    sc->limit = get_seg_limit(e1, e2);
175
    sc->flags = e2;
176
}
177

    
178
/* init the segment cache in vm86 mode. */
179
static inline void load_seg_vm(int seg, int selector)
180
{
181
    selector &= 0xffff;
182
    cpu_x86_load_seg_cache(env, seg, selector,
183
                           (selector << 4), 0xffff, 0);
184
}
185

    
186
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
187
                                       uint32_t *esp_ptr, int dpl)
188
{
189
    int type, index, shift;
190

    
191
#if 0
192
    {
193
        int i;
194
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
195
        for(i=0;i<env->tr.limit;i++) {
196
            printf("%02x ", env->tr.base[i]);
197
            if ((i & 7) == 7) printf("\n");
198
        }
199
        printf("\n");
200
    }
201
#endif
202

    
203
    if (!(env->tr.flags & DESC_P_MASK))
204
        cpu_abort(env, "invalid tss");
205
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
206
    if ((type & 7) != 1)
207
        cpu_abort(env, "invalid tss type");
208
    shift = type >> 3;
209
    index = (dpl * 4 + 2) << shift;
210
    if (index + (4 << shift) - 1 > env->tr.limit)
211
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
212
    if (shift == 0) {
213
        *esp_ptr = lduw_kernel(env->tr.base + index);
214
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
215
    } else {
216
        *esp_ptr = ldl_kernel(env->tr.base + index);
217
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
218
    }
219
}
220

    
221
/* XXX: merge with load_seg() */
222
static void tss_load_seg(int seg_reg, int selector)
223
{
224
    uint32_t e1, e2;
225
    int rpl, dpl, cpl;
226

    
227
    if ((selector & 0xfffc) != 0) {
228
        if (load_segment(&e1, &e2, selector) != 0)
229
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
230
        if (!(e2 & DESC_S_MASK))
231
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
232
        rpl = selector & 3;
233
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
234
        cpl = env->hflags & HF_CPL_MASK;
235
        if (seg_reg == R_CS) {
236
            if (!(e2 & DESC_CS_MASK))
237
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
238
            /* XXX: is it correct ? */
239
            if (dpl != rpl)
240
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
241
            if ((e2 & DESC_C_MASK) && dpl > rpl)
242
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
243
        } else if (seg_reg == R_SS) {
244
            /* SS must be writable data */
245
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
246
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
247
            if (dpl != cpl || dpl != rpl)
248
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
249
        } else {
250
            /* not readable code */
251
            if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
252
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
253
            /* if data or non conforming code, checks the rights */
254
            if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
255
                if (dpl < cpl || dpl < rpl)
256
                    raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
257
            }
258
        }
259
        if (!(e2 & DESC_P_MASK))
260
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
261
        cpu_x86_load_seg_cache(env, seg_reg, selector,
262
                       get_seg_base(e1, e2),
263
                       get_seg_limit(e1, e2),
264
                       e2);
265
    } else {
266
        if (seg_reg == R_SS || seg_reg == R_CS)
267
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
268
    }
269
}
270

    
271
#define SWITCH_TSS_JMP  0
272
#define SWITCH_TSS_IRET 1
273
#define SWITCH_TSS_CALL 2
274

    
275
/* XXX: restore CPU state in registers (PowerPC case) */
276
static void switch_tss(int tss_selector,
277
                       uint32_t e1, uint32_t e2, int source,
278
                       uint32_t next_eip)
279
{
280
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
281
    target_ulong tss_base;
282
    uint32_t new_regs[8], new_segs[6];
283
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
284
    uint32_t old_eflags, eflags_mask;
285
    SegmentCache *dt;
286
    int index;
287
    target_ulong ptr;
288

    
289
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
290
    LOG_PCALL("switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
291

    
292
    /* if task gate, we read the TSS segment and we load it */
293
    if (type == 5) {
294
        if (!(e2 & DESC_P_MASK))
295
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
296
        tss_selector = e1 >> 16;
297
        if (tss_selector & 4)
298
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
299
        if (load_segment(&e1, &e2, tss_selector) != 0)
300
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
301
        if (e2 & DESC_S_MASK)
302
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
303
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
304
        if ((type & 7) != 1)
305
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
306
    }
307

    
308
    if (!(e2 & DESC_P_MASK))
309
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
310

    
311
    if (type & 8)
312
        tss_limit_max = 103;
313
    else
314
        tss_limit_max = 43;
315
    tss_limit = get_seg_limit(e1, e2);
316
    tss_base = get_seg_base(e1, e2);
317
    if ((tss_selector & 4) != 0 ||
318
        tss_limit < tss_limit_max)
319
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
320
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
321
    if (old_type & 8)
322
        old_tss_limit_max = 103;
323
    else
324
        old_tss_limit_max = 43;
325

    
326
    /* read all the registers from the new TSS */
327
    if (type & 8) {
328
        /* 32 bit */
329
        new_cr3 = ldl_kernel(tss_base + 0x1c);
330
        new_eip = ldl_kernel(tss_base + 0x20);
331
        new_eflags = ldl_kernel(tss_base + 0x24);
332
        for(i = 0; i < 8; i++)
333
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
334
        for(i = 0; i < 6; i++)
335
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
336
        new_ldt = lduw_kernel(tss_base + 0x60);
337
        new_trap = ldl_kernel(tss_base + 0x64);
338
    } else {
339
        /* 16 bit */
340
        new_cr3 = 0;
341
        new_eip = lduw_kernel(tss_base + 0x0e);
342
        new_eflags = lduw_kernel(tss_base + 0x10);
343
        for(i = 0; i < 8; i++)
344
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
345
        for(i = 0; i < 4; i++)
346
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
347
        new_ldt = lduw_kernel(tss_base + 0x2a);
348
        new_segs[R_FS] = 0;
349
        new_segs[R_GS] = 0;
350
        new_trap = 0;
351
    }
352

    
353
    /* NOTE: we must avoid memory exceptions during the task switch,
354
       so we make dummy accesses before */
355
    /* XXX: it can still fail in some cases, so a bigger hack is
356
       necessary to valid the TLB after having done the accesses */
357

    
358
    v1 = ldub_kernel(env->tr.base);
359
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
360
    stb_kernel(env->tr.base, v1);
361
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
362

    
363
    /* clear busy bit (it is restartable) */
364
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
365
        target_ulong ptr;
366
        uint32_t e2;
367
        ptr = env->gdt.base + (env->tr.selector & ~7);
368
        e2 = ldl_kernel(ptr + 4);
369
        e2 &= ~DESC_TSS_BUSY_MASK;
370
        stl_kernel(ptr + 4, e2);
371
    }
372
    old_eflags = compute_eflags();
373
    if (source == SWITCH_TSS_IRET)
374
        old_eflags &= ~NT_MASK;
375

    
376
    /* save the current state in the old TSS */
377
    if (type & 8) {
378
        /* 32 bit */
379
        stl_kernel(env->tr.base + 0x20, next_eip);
380
        stl_kernel(env->tr.base + 0x24, old_eflags);
381
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
382
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
383
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
384
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
385
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
386
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
387
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
388
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
389
        for(i = 0; i < 6; i++)
390
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
391
    } else {
392
        /* 16 bit */
393
        stw_kernel(env->tr.base + 0x0e, next_eip);
394
        stw_kernel(env->tr.base + 0x10, old_eflags);
395
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
396
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
397
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
398
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
399
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
400
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
401
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
402
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
403
        for(i = 0; i < 4; i++)
404
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
405
    }
406

    
407
    /* now if an exception occurs, it will occurs in the next task
408
       context */
409

    
410
    if (source == SWITCH_TSS_CALL) {
411
        stw_kernel(tss_base, env->tr.selector);
412
        new_eflags |= NT_MASK;
413
    }
414

    
415
    /* set busy bit */
416
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
417
        target_ulong ptr;
418
        uint32_t e2;
419
        ptr = env->gdt.base + (tss_selector & ~7);
420
        e2 = ldl_kernel(ptr + 4);
421
        e2 |= DESC_TSS_BUSY_MASK;
422
        stl_kernel(ptr + 4, e2);
423
    }
424

    
425
    /* set the new CPU state */
426
    /* from this point, any exception which occurs can give problems */
427
    env->cr[0] |= CR0_TS_MASK;
428
    env->hflags |= HF_TS_MASK;
429
    env->tr.selector = tss_selector;
430
    env->tr.base = tss_base;
431
    env->tr.limit = tss_limit;
432
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
433

    
434
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
435
        cpu_x86_update_cr3(env, new_cr3);
436
    }
437

    
438
    /* load all registers without an exception, then reload them with
439
       possible exception */
440
    env->eip = new_eip;
441
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
442
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
443
    if (!(type & 8))
444
        eflags_mask &= 0xffff;
445
    load_eflags(new_eflags, eflags_mask);
446
    /* XXX: what to do in 16 bit case ? */
447
    EAX = new_regs[0];
448
    ECX = new_regs[1];
449
    EDX = new_regs[2];
450
    EBX = new_regs[3];
451
    ESP = new_regs[4];
452
    EBP = new_regs[5];
453
    ESI = new_regs[6];
454
    EDI = new_regs[7];
455
    if (new_eflags & VM_MASK) {
456
        for(i = 0; i < 6; i++)
457
            load_seg_vm(i, new_segs[i]);
458
        /* in vm86, CPL is always 3 */
459
        cpu_x86_set_cpl(env, 3);
460
    } else {
461
        /* CPL is set the RPL of CS */
462
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
463
        /* first just selectors as the rest may trigger exceptions */
464
        for(i = 0; i < 6; i++)
465
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
466
    }
467

    
468
    env->ldt.selector = new_ldt & ~4;
469
    env->ldt.base = 0;
470
    env->ldt.limit = 0;
471
    env->ldt.flags = 0;
472

    
473
    /* load the LDT */
474
    if (new_ldt & 4)
475
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
476

    
477
    if ((new_ldt & 0xfffc) != 0) {
478
        dt = &env->gdt;
479
        index = new_ldt & ~7;
480
        if ((index + 7) > dt->limit)
481
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
482
        ptr = dt->base + index;
483
        e1 = ldl_kernel(ptr);
484
        e2 = ldl_kernel(ptr + 4);
485
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
486
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
487
        if (!(e2 & DESC_P_MASK))
488
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
489
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
490
    }
491

    
492
    /* load the segments */
493
    if (!(new_eflags & VM_MASK)) {
494
        tss_load_seg(R_CS, new_segs[R_CS]);
495
        tss_load_seg(R_SS, new_segs[R_SS]);
496
        tss_load_seg(R_ES, new_segs[R_ES]);
497
        tss_load_seg(R_DS, new_segs[R_DS]);
498
        tss_load_seg(R_FS, new_segs[R_FS]);
499
        tss_load_seg(R_GS, new_segs[R_GS]);
500
    }
501

    
502
    /* check that EIP is in the CS segment limits */
503
    if (new_eip > env->segs[R_CS].limit) {
504
        /* XXX: different exception if CALL ? */
505
        raise_exception_err(EXCP0D_GPF, 0);
506
    }
507

    
508
#ifndef CONFIG_USER_ONLY
509
    /* reset local breakpoints */
510
    if (env->dr[7] & 0x55) {
511
        for (i = 0; i < 4; i++) {
512
            if (hw_breakpoint_enabled(env->dr[7], i) == 0x1)
513
                hw_breakpoint_remove(env, i);
514
        }
515
        env->dr[7] &= ~0x55;
516
    }
517
#endif
518
}
519

    
520
/* check if Port I/O is allowed in TSS */
521
static inline void check_io(int addr, int size)
522
{
523
    int io_offset, val, mask;
524

    
525
    /* TSS must be a valid 32 bit one */
526
    if (!(env->tr.flags & DESC_P_MASK) ||
527
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
528
        env->tr.limit < 103)
529
        goto fail;
530
    io_offset = lduw_kernel(env->tr.base + 0x66);
531
    io_offset += (addr >> 3);
532
    /* Note: the check needs two bytes */
533
    if ((io_offset + 1) > env->tr.limit)
534
        goto fail;
535
    val = lduw_kernel(env->tr.base + io_offset);
536
    val >>= (addr & 7);
537
    mask = (1 << size) - 1;
538
    /* all bits must be zero to allow the I/O */
539
    if ((val & mask) != 0) {
540
    fail:
541
        raise_exception_err(EXCP0D_GPF, 0);
542
    }
543
}
544

    
545
void helper_check_iob(uint32_t t0)
546
{
547
    check_io(t0, 1);
548
}
549

    
550
void helper_check_iow(uint32_t t0)
551
{
552
    check_io(t0, 2);
553
}
554

    
555
void helper_check_iol(uint32_t t0)
556
{
557
    check_io(t0, 4);
558
}
559

    
560
void helper_outb(uint32_t port, uint32_t data)
561
{
562
    cpu_outb(env, port, data & 0xff);
563
}
564

    
565
target_ulong helper_inb(uint32_t port)
566
{
567
    return cpu_inb(env, port);
568
}
569

    
570
void helper_outw(uint32_t port, uint32_t data)
571
{
572
    cpu_outw(env, port, data & 0xffff);
573
}
574

    
575
target_ulong helper_inw(uint32_t port)
576
{
577
    return cpu_inw(env, port);
578
}
579

    
580
void helper_outl(uint32_t port, uint32_t data)
581
{
582
    cpu_outl(env, port, data);
583
}
584

    
585
target_ulong helper_inl(uint32_t port)
586
{
587
    return cpu_inl(env, port);
588
}
589

    
590
static inline unsigned int get_sp_mask(unsigned int e2)
591
{
592
    if (e2 & DESC_B_MASK)
593
        return 0xffffffff;
594
    else
595
        return 0xffff;
596
}
597

    
598
#ifdef TARGET_X86_64
599
#define SET_ESP(val, sp_mask)\
600
do {\
601
    if ((sp_mask) == 0xffff)\
602
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
603
    else if ((sp_mask) == 0xffffffffLL)\
604
        ESP = (uint32_t)(val);\
605
    else\
606
        ESP = (val);\
607
} while (0)
608
#else
609
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
610
#endif
611

    
612
/* in 64-bit machines, this can overflow. So this segment addition macro
613
 * can be used to trim the value to 32-bit whenever needed */
614
#define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
615

    
616
/* XXX: add a is_user flag to have proper security support */
617
#define PUSHW(ssp, sp, sp_mask, val)\
618
{\
619
    sp -= 2;\
620
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
621
}
622

    
623
#define PUSHL(ssp, sp, sp_mask, val)\
624
{\
625
    sp -= 4;\
626
    stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
627
}
628

    
629
#define POPW(ssp, sp, sp_mask, val)\
630
{\
631
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
632
    sp += 2;\
633
}
634

    
635
#define POPL(ssp, sp, sp_mask, val)\
636
{\
637
    val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
638
    sp += 4;\
639
}
640

    
641
/* protected mode interrupt */
642
static void do_interrupt_protected(int intno, int is_int, int error_code,
643
                                   unsigned int next_eip, int is_hw)
644
{
645
    SegmentCache *dt;
646
    target_ulong ptr, ssp;
647
    int type, dpl, selector, ss_dpl, cpl;
648
    int has_error_code, new_stack, shift;
649
    uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
650
    uint32_t old_eip, sp_mask;
651

    
652
    has_error_code = 0;
653
    if (!is_int && !is_hw) {
654
        switch(intno) {
655
        case 8:
656
        case 10:
657
        case 11:
658
        case 12:
659
        case 13:
660
        case 14:
661
        case 17:
662
            has_error_code = 1;
663
            break;
664
        }
665
    }
666
    if (is_int)
667
        old_eip = next_eip;
668
    else
669
        old_eip = env->eip;
670

    
671
    dt = &env->idt;
672
    if (intno * 8 + 7 > dt->limit)
673
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
674
    ptr = dt->base + intno * 8;
675
    e1 = ldl_kernel(ptr);
676
    e2 = ldl_kernel(ptr + 4);
677
    /* check gate type */
678
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
679
    switch(type) {
680
    case 5: /* task gate */
681
        /* must do that check here to return the correct error code */
682
        if (!(e2 & DESC_P_MASK))
683
            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
684
        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
685
        if (has_error_code) {
686
            int type;
687
            uint32_t mask;
688
            /* push the error code */
689
            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
690
            shift = type >> 3;
691
            if (env->segs[R_SS].flags & DESC_B_MASK)
692
                mask = 0xffffffff;
693
            else
694
                mask = 0xffff;
695
            esp = (ESP - (2 << shift)) & mask;
696
            ssp = env->segs[R_SS].base + esp;
697
            if (shift)
698
                stl_kernel(ssp, error_code);
699
            else
700
                stw_kernel(ssp, error_code);
701
            SET_ESP(esp, mask);
702
        }
703
        return;
704
    case 6: /* 286 interrupt gate */
705
    case 7: /* 286 trap gate */
706
    case 14: /* 386 interrupt gate */
707
    case 15: /* 386 trap gate */
708
        break;
709
    default:
710
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
711
        break;
712
    }
713
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
714
    cpl = env->hflags & HF_CPL_MASK;
715
    /* check privilege if software int */
716
    if (is_int && dpl < cpl)
717
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
718
    /* check valid bit */
719
    if (!(e2 & DESC_P_MASK))
720
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
721
    selector = e1 >> 16;
722
    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
723
    if ((selector & 0xfffc) == 0)
724
        raise_exception_err(EXCP0D_GPF, 0);
725

    
726
    if (load_segment(&e1, &e2, selector) != 0)
727
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
728
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
729
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
730
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
731
    if (dpl > cpl)
732
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
733
    if (!(e2 & DESC_P_MASK))
734
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
735
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
736
        /* to inner privilege */
737
        get_ss_esp_from_tss(&ss, &esp, dpl);
738
        if ((ss & 0xfffc) == 0)
739
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
740
        if ((ss & 3) != dpl)
741
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
742
        if (load_segment(&ss_e1, &ss_e2, ss) != 0)
743
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
744
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
745
        if (ss_dpl != dpl)
746
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
747
        if (!(ss_e2 & DESC_S_MASK) ||
748
            (ss_e2 & DESC_CS_MASK) ||
749
            !(ss_e2 & DESC_W_MASK))
750
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
751
        if (!(ss_e2 & DESC_P_MASK))
752
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
753
        new_stack = 1;
754
        sp_mask = get_sp_mask(ss_e2);
755
        ssp = get_seg_base(ss_e1, ss_e2);
756
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
757
        /* to same privilege */
758
        if (env->eflags & VM_MASK)
759
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
760
        new_stack = 0;
761
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
762
        ssp = env->segs[R_SS].base;
763
        esp = ESP;
764
        dpl = cpl;
765
    } else {
766
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
767
        new_stack = 0; /* avoid warning */
768
        sp_mask = 0; /* avoid warning */
769
        ssp = 0; /* avoid warning */
770
        esp = 0; /* avoid warning */
771
    }
772

    
773
    shift = type >> 3;
774

    
775
#if 0
776
    /* XXX: check that enough room is available */
777
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
778
    if (env->eflags & VM_MASK)
779
        push_size += 8;
780
    push_size <<= shift;
781
#endif
782
    if (shift == 1) {
783
        if (new_stack) {
784
            if (env->eflags & VM_MASK) {
785
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
786
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
787
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
788
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
789
            }
790
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
791
            PUSHL(ssp, esp, sp_mask, ESP);
792
        }
793
        PUSHL(ssp, esp, sp_mask, compute_eflags());
794
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
795
        PUSHL(ssp, esp, sp_mask, old_eip);
796
        if (has_error_code) {
797
            PUSHL(ssp, esp, sp_mask, error_code);
798
        }
799
    } else {
800
        if (new_stack) {
801
            if (env->eflags & VM_MASK) {
802
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
803
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
804
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
805
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
806
            }
807
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
808
            PUSHW(ssp, esp, sp_mask, ESP);
809
        }
810
        PUSHW(ssp, esp, sp_mask, compute_eflags());
811
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
812
        PUSHW(ssp, esp, sp_mask, old_eip);
813
        if (has_error_code) {
814
            PUSHW(ssp, esp, sp_mask, error_code);
815
        }
816
    }
817

    
818
    if (new_stack) {
819
        if (env->eflags & VM_MASK) {
820
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
821
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
822
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
823
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
824
        }
825
        ss = (ss & ~3) | dpl;
826
        cpu_x86_load_seg_cache(env, R_SS, ss,
827
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
828
    }
829
    SET_ESP(esp, sp_mask);
830

    
831
    selector = (selector & ~3) | dpl;
832
    cpu_x86_load_seg_cache(env, R_CS, selector,
833
                   get_seg_base(e1, e2),
834
                   get_seg_limit(e1, e2),
835
                   e2);
836
    cpu_x86_set_cpl(env, dpl);
837
    env->eip = offset;
838

    
839
    /* interrupt gate clear IF mask */
840
    if ((type & 1) == 0) {
841
        env->eflags &= ~IF_MASK;
842
    }
843
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
844
}
845

    
846
#ifdef TARGET_X86_64
847

    
848
#define PUSHQ(sp, val)\
849
{\
850
    sp -= 8;\
851
    stq_kernel(sp, (val));\
852
}
853

    
854
#define POPQ(sp, val)\
855
{\
856
    val = ldq_kernel(sp);\
857
    sp += 8;\
858
}
859

    
860
static inline target_ulong get_rsp_from_tss(int level)
861
{
862
    int index;
863

    
864
#if 0
865
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
866
           env->tr.base, env->tr.limit);
867
#endif
868

    
869
    if (!(env->tr.flags & DESC_P_MASK))
870
        cpu_abort(env, "invalid tss");
871
    index = 8 * level + 4;
872
    if ((index + 7) > env->tr.limit)
873
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
874
    return ldq_kernel(env->tr.base + index);
875
}
876

    
877
/* 64 bit interrupt */
878
static void do_interrupt64(int intno, int is_int, int error_code,
879
                           target_ulong next_eip, int is_hw)
880
{
881
    SegmentCache *dt;
882
    target_ulong ptr;
883
    int type, dpl, selector, cpl, ist;
884
    int has_error_code, new_stack;
885
    uint32_t e1, e2, e3, ss;
886
    target_ulong old_eip, esp, offset;
887

    
888
    has_error_code = 0;
889
    if (!is_int && !is_hw) {
890
        switch(intno) {
891
        case 8:
892
        case 10:
893
        case 11:
894
        case 12:
895
        case 13:
896
        case 14:
897
        case 17:
898
            has_error_code = 1;
899
            break;
900
        }
901
    }
902
    if (is_int)
903
        old_eip = next_eip;
904
    else
905
        old_eip = env->eip;
906

    
907
    dt = &env->idt;
908
    if (intno * 16 + 15 > dt->limit)
909
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
910
    ptr = dt->base + intno * 16;
911
    e1 = ldl_kernel(ptr);
912
    e2 = ldl_kernel(ptr + 4);
913
    e3 = ldl_kernel(ptr + 8);
914
    /* check gate type */
915
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
916
    switch(type) {
917
    case 14: /* 386 interrupt gate */
918
    case 15: /* 386 trap gate */
919
        break;
920
    default:
921
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
922
        break;
923
    }
924
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
925
    cpl = env->hflags & HF_CPL_MASK;
926
    /* check privilege if software int */
927
    if (is_int && dpl < cpl)
928
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
929
    /* check valid bit */
930
    if (!(e2 & DESC_P_MASK))
931
        raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
932
    selector = e1 >> 16;
933
    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
934
    ist = e2 & 7;
935
    if ((selector & 0xfffc) == 0)
936
        raise_exception_err(EXCP0D_GPF, 0);
937

    
938
    if (load_segment(&e1, &e2, selector) != 0)
939
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
940
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
941
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
942
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
943
    if (dpl > cpl)
944
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
945
    if (!(e2 & DESC_P_MASK))
946
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
947
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
948
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
949
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
950
        /* to inner privilege */
951
        if (ist != 0)
952
            esp = get_rsp_from_tss(ist + 3);
953
        else
954
            esp = get_rsp_from_tss(dpl);
955
        esp &= ~0xfLL; /* align stack */
956
        ss = 0;
957
        new_stack = 1;
958
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
959
        /* to same privilege */
960
        if (env->eflags & VM_MASK)
961
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
962
        new_stack = 0;
963
        if (ist != 0)
964
            esp = get_rsp_from_tss(ist + 3);
965
        else
966
            esp = ESP;
967
        esp &= ~0xfLL; /* align stack */
968
        dpl = cpl;
969
    } else {
970
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
971
        new_stack = 0; /* avoid warning */
972
        esp = 0; /* avoid warning */
973
    }
974

    
975
    PUSHQ(esp, env->segs[R_SS].selector);
976
    PUSHQ(esp, ESP);
977
    PUSHQ(esp, compute_eflags());
978
    PUSHQ(esp, env->segs[R_CS].selector);
979
    PUSHQ(esp, old_eip);
980
    if (has_error_code) {
981
        PUSHQ(esp, error_code);
982
    }
983

    
984
    if (new_stack) {
985
        ss = 0 | dpl;
986
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
987
    }
988
    ESP = esp;
989

    
990
    selector = (selector & ~3) | dpl;
991
    cpu_x86_load_seg_cache(env, R_CS, selector,
992
                   get_seg_base(e1, e2),
993
                   get_seg_limit(e1, e2),
994
                   e2);
995
    cpu_x86_set_cpl(env, dpl);
996
    env->eip = offset;
997

    
998
    /* interrupt gate clear IF mask */
999
    if ((type & 1) == 0) {
1000
        env->eflags &= ~IF_MASK;
1001
    }
1002
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
1003
}
1004
#endif
1005

    
1006
#ifdef TARGET_X86_64
1007
#if defined(CONFIG_USER_ONLY)
1008
void helper_syscall(int next_eip_addend)
1009
{
1010
    env->exception_index = EXCP_SYSCALL;
1011
    env->exception_next_eip = env->eip + next_eip_addend;
1012
    cpu_loop_exit();
1013
}
1014
#else
1015
void helper_syscall(int next_eip_addend)
1016
{
1017
    int selector;
1018

    
1019
    if (!(env->efer & MSR_EFER_SCE)) {
1020
        raise_exception_err(EXCP06_ILLOP, 0);
1021
    }
1022
    selector = (env->star >> 32) & 0xffff;
1023
    if (env->hflags & HF_LMA_MASK) {
1024
        int code64;
1025

    
1026
        ECX = env->eip + next_eip_addend;
1027
        env->regs[11] = compute_eflags();
1028

    
1029
        code64 = env->hflags & HF_CS64_MASK;
1030

    
1031
        cpu_x86_set_cpl(env, 0);
1032
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1033
                           0, 0xffffffff,
1034
                               DESC_G_MASK | DESC_P_MASK |
1035
                               DESC_S_MASK |
1036
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1037
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1038
                               0, 0xffffffff,
1039
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1040
                               DESC_S_MASK |
1041
                               DESC_W_MASK | DESC_A_MASK);
1042
        env->eflags &= ~env->fmask;
1043
        load_eflags(env->eflags, 0);
1044
        if (code64)
1045
            env->eip = env->lstar;
1046
        else
1047
            env->eip = env->cstar;
1048
    } else {
1049
        ECX = (uint32_t)(env->eip + next_eip_addend);
1050

    
1051
        cpu_x86_set_cpl(env, 0);
1052
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1053
                           0, 0xffffffff,
1054
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1055
                               DESC_S_MASK |
1056
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1057
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1058
                               0, 0xffffffff,
1059
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1060
                               DESC_S_MASK |
1061
                               DESC_W_MASK | DESC_A_MASK);
1062
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1063
        env->eip = (uint32_t)env->star;
1064
    }
1065
}
1066
#endif
1067
#endif
1068

    
1069
#ifdef TARGET_X86_64
1070
void helper_sysret(int dflag)
1071
{
1072
    int cpl, selector;
1073

    
1074
    if (!(env->efer & MSR_EFER_SCE)) {
1075
        raise_exception_err(EXCP06_ILLOP, 0);
1076
    }
1077
    cpl = env->hflags & HF_CPL_MASK;
1078
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1079
        raise_exception_err(EXCP0D_GPF, 0);
1080
    }
1081
    selector = (env->star >> 48) & 0xffff;
1082
    if (env->hflags & HF_LMA_MASK) {
1083
        if (dflag == 2) {
1084
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1085
                                   0, 0xffffffff,
1086
                                   DESC_G_MASK | DESC_P_MASK |
1087
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1088
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1089
                                   DESC_L_MASK);
1090
            env->eip = ECX;
1091
        } else {
1092
            cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1093
                                   0, 0xffffffff,
1094
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1095
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1096
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1097
            env->eip = (uint32_t)ECX;
1098
        }
1099
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1100
                               0, 0xffffffff,
1101
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1102
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1103
                               DESC_W_MASK | DESC_A_MASK);
1104
        load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1105
                    IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1106
        cpu_x86_set_cpl(env, 3);
1107
    } else {
1108
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1109
                               0, 0xffffffff,
1110
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1111
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1112
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1113
        env->eip = (uint32_t)ECX;
1114
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1115
                               0, 0xffffffff,
1116
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1117
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1118
                               DESC_W_MASK | DESC_A_MASK);
1119
        env->eflags |= IF_MASK;
1120
        cpu_x86_set_cpl(env, 3);
1121
    }
1122
#ifdef USE_KQEMU
1123
    if (kqemu_is_ok(env)) {
1124
        if (env->hflags & HF_LMA_MASK)
1125
            CC_OP = CC_OP_EFLAGS;
1126
        env->exception_index = -1;
1127
        cpu_loop_exit();
1128
    }
1129
#endif
1130
}
1131
#endif
1132

    
1133
/* real mode interrupt */
1134
static void do_interrupt_real(int intno, int is_int, int error_code,
1135
                              unsigned int next_eip)
1136
{
1137
    SegmentCache *dt;
1138
    target_ulong ptr, ssp;
1139
    int selector;
1140
    uint32_t offset, esp;
1141
    uint32_t old_cs, old_eip;
1142

    
1143
    /* real mode (simpler !) */
1144
    dt = &env->idt;
1145
    if (intno * 4 + 3 > dt->limit)
1146
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1147
    ptr = dt->base + intno * 4;
1148
    offset = lduw_kernel(ptr);
1149
    selector = lduw_kernel(ptr + 2);
1150
    esp = ESP;
1151
    ssp = env->segs[R_SS].base;
1152
    if (is_int)
1153
        old_eip = next_eip;
1154
    else
1155
        old_eip = env->eip;
1156
    old_cs = env->segs[R_CS].selector;
1157
    /* XXX: use SS segment size ? */
1158
    PUSHW(ssp, esp, 0xffff, compute_eflags());
1159
    PUSHW(ssp, esp, 0xffff, old_cs);
1160
    PUSHW(ssp, esp, 0xffff, old_eip);
1161

    
1162
    /* update processor state */
1163
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1164
    env->eip = offset;
1165
    env->segs[R_CS].selector = selector;
1166
    env->segs[R_CS].base = (selector << 4);
1167
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1168
}
1169

    
1170
/* fake user mode interrupt */
1171
void do_interrupt_user(int intno, int is_int, int error_code,
1172
                       target_ulong next_eip)
1173
{
1174
    SegmentCache *dt;
1175
    target_ulong ptr;
1176
    int dpl, cpl, shift;
1177
    uint32_t e2;
1178

    
1179
    dt = &env->idt;
1180
    if (env->hflags & HF_LMA_MASK) {
1181
        shift = 4;
1182
    } else {
1183
        shift = 3;
1184
    }
1185
    ptr = dt->base + (intno << shift);
1186
    e2 = ldl_kernel(ptr + 4);
1187

    
1188
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1189
    cpl = env->hflags & HF_CPL_MASK;
1190
    /* check privilege if software int */
1191
    if (is_int && dpl < cpl)
1192
        raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1193

    
1194
    /* Since we emulate only user space, we cannot do more than
1195
       exiting the emulation with the suitable exception and error
1196
       code */
1197
    if (is_int)
1198
        EIP = next_eip;
1199
}
1200

    
1201
/*
1202
 * Begin execution of an interruption. is_int is TRUE if coming from
1203
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1204
 * instruction. It is only relevant if is_int is TRUE.
1205
 */
1206
void do_interrupt(int intno, int is_int, int error_code,
1207
                  target_ulong next_eip, int is_hw)
1208
{
1209
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
1210
        if ((env->cr[0] & CR0_PE_MASK)) {
1211
            static int count;
1212
            qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1213
                    count, intno, error_code, is_int,
1214
                    env->hflags & HF_CPL_MASK,
1215
                    env->segs[R_CS].selector, EIP,
1216
                    (int)env->segs[R_CS].base + EIP,
1217
                    env->segs[R_SS].selector, ESP);
1218
            if (intno == 0x0e) {
1219
                qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
1220
            } else {
1221
                qemu_log(" EAX=" TARGET_FMT_lx, EAX);
1222
            }
1223
            qemu_log("\n");
1224
            log_cpu_state(env, X86_DUMP_CCOP);
1225
#if 0
1226
            {
1227
                int i;
1228
                uint8_t *ptr;
1229
                qemu_log("       code=");
1230
                ptr = env->segs[R_CS].base + env->eip;
1231
                for(i = 0; i < 16; i++) {
1232
                    qemu_log(" %02x", ldub(ptr + i));
1233
                }
1234
                qemu_log("\n");
1235
            }
1236
#endif
1237
            count++;
1238
        }
1239
    }
1240
    if (env->cr[0] & CR0_PE_MASK) {
1241
#ifdef TARGET_X86_64
1242
        if (env->hflags & HF_LMA_MASK) {
1243
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1244
        } else
1245
#endif
1246
        {
1247
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1248
        }
1249
    } else {
1250
        do_interrupt_real(intno, is_int, error_code, next_eip);
1251
    }
1252
}
1253

    
1254
/* This should come from sysemu.h - if we could include it here... */
1255
void qemu_system_reset_request(void);
1256

    
1257
/*
1258
 * Check nested exceptions and change to double or triple fault if
1259
 * needed. It should only be called, if this is not an interrupt.
1260
 * Returns the new exception number.
1261
 */
1262
static int check_exception(int intno, int *error_code)
1263
{
1264
    int first_contributory = env->old_exception == 0 ||
1265
                              (env->old_exception >= 10 &&
1266
                               env->old_exception <= 13);
1267
    int second_contributory = intno == 0 ||
1268
                               (intno >= 10 && intno <= 13);
1269

    
1270
    qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
1271
                env->old_exception, intno);
1272

    
1273
#if !defined(CONFIG_USER_ONLY)
1274
    if (env->old_exception == EXCP08_DBLE) {
1275
        if (env->hflags & HF_SVMI_MASK)
1276
            helper_vmexit(SVM_EXIT_SHUTDOWN, 0); /* does not return */
1277

    
1278
        qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1279

    
1280
        qemu_system_reset_request();
1281
        return EXCP_HLT;
1282
    }
1283
#endif
1284

    
1285
    if ((first_contributory && second_contributory)
1286
        || (env->old_exception == EXCP0E_PAGE &&
1287
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1288
        intno = EXCP08_DBLE;
1289
        *error_code = 0;
1290
    }
1291

    
1292
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1293
        (intno == EXCP08_DBLE))
1294
        env->old_exception = intno;
1295

    
1296
    return intno;
1297
}
1298

    
1299
/*
1300
 * Signal an interruption. It is executed in the main CPU loop.
1301
 * is_int is TRUE if coming from the int instruction. next_eip is the
1302
 * EIP value AFTER the interrupt instruction. It is only relevant if
1303
 * is_int is TRUE.
1304
 */
1305
static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
1306
                                          int next_eip_addend)
1307
{
1308
    if (!is_int) {
1309
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1310
        intno = check_exception(intno, &error_code);
1311
    } else {
1312
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1313
    }
1314

    
1315
    env->exception_index = intno;
1316
    env->error_code = error_code;
1317
    env->exception_is_int = is_int;
1318
    env->exception_next_eip = env->eip + next_eip_addend;
1319
    cpu_loop_exit();
1320
}
1321

    
1322
/* shortcuts to generate exceptions */
1323

    
1324
void raise_exception_err(int exception_index, int error_code)
1325
{
1326
    raise_interrupt(exception_index, 0, error_code, 0);
1327
}
1328

    
1329
void raise_exception(int exception_index)
1330
{
1331
    raise_interrupt(exception_index, 0, 0, 0);
1332
}
1333

    
1334
/* SMM support */
1335

    
1336
#if defined(CONFIG_USER_ONLY)
1337

    
1338
void do_smm_enter(void)
1339
{
1340
}
1341

    
1342
void helper_rsm(void)
1343
{
1344
}
1345

    
1346
#else
1347

    
1348
#ifdef TARGET_X86_64
1349
#define SMM_REVISION_ID 0x00020064
1350
#else
1351
#define SMM_REVISION_ID 0x00020000
1352
#endif
1353

    
1354
void do_smm_enter(void)
1355
{
1356
    target_ulong sm_state;
1357
    SegmentCache *dt;
1358
    int i, offset;
1359

    
1360
    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
1361
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1362

    
1363
    env->hflags |= HF_SMM_MASK;
1364
    cpu_smm_update(env);
1365

    
1366
    sm_state = env->smbase + 0x8000;
1367

    
1368
#ifdef TARGET_X86_64
1369
    for(i = 0; i < 6; i++) {
1370
        dt = &env->segs[i];
1371
        offset = 0x7e00 + i * 16;
1372
        stw_phys(sm_state + offset, dt->selector);
1373
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1374
        stl_phys(sm_state + offset + 4, dt->limit);
1375
        stq_phys(sm_state + offset + 8, dt->base);
1376
    }
1377

    
1378
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1379
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1380

    
1381
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1382
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1383
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1384
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1385

    
1386
    stq_phys(sm_state + 0x7e88, env->idt.base);
1387
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1388

    
1389
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1390
    stq_phys(sm_state + 0x7e98, env->tr.base);
1391
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1392
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1393

    
1394
    stq_phys(sm_state + 0x7ed0, env->efer);
1395

    
1396
    stq_phys(sm_state + 0x7ff8, EAX);
1397
    stq_phys(sm_state + 0x7ff0, ECX);
1398
    stq_phys(sm_state + 0x7fe8, EDX);
1399
    stq_phys(sm_state + 0x7fe0, EBX);
1400
    stq_phys(sm_state + 0x7fd8, ESP);
1401
    stq_phys(sm_state + 0x7fd0, EBP);
1402
    stq_phys(sm_state + 0x7fc8, ESI);
1403
    stq_phys(sm_state + 0x7fc0, EDI);
1404
    for(i = 8; i < 16; i++)
1405
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1406
    stq_phys(sm_state + 0x7f78, env->eip);
1407
    stl_phys(sm_state + 0x7f70, compute_eflags());
1408
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1409
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1410

    
1411
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1412
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1413
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1414

    
1415
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1416
    stl_phys(sm_state + 0x7f00, env->smbase);
1417
#else
1418
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1419
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1420
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1421
    stl_phys(sm_state + 0x7ff0, env->eip);
1422
    stl_phys(sm_state + 0x7fec, EDI);
1423
    stl_phys(sm_state + 0x7fe8, ESI);
1424
    stl_phys(sm_state + 0x7fe4, EBP);
1425
    stl_phys(sm_state + 0x7fe0, ESP);
1426
    stl_phys(sm_state + 0x7fdc, EBX);
1427
    stl_phys(sm_state + 0x7fd8, EDX);
1428
    stl_phys(sm_state + 0x7fd4, ECX);
1429
    stl_phys(sm_state + 0x7fd0, EAX);
1430
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1431
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1432

    
1433
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1434
    stl_phys(sm_state + 0x7f64, env->tr.base);
1435
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1436
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1437

    
1438
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1439
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1440
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1441
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1442

    
1443
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1444
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1445

    
1446
    stl_phys(sm_state + 0x7f58, env->idt.base);
1447
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1448

    
1449
    for(i = 0; i < 6; i++) {
1450
        dt = &env->segs[i];
1451
        if (i < 3)
1452
            offset = 0x7f84 + i * 12;
1453
        else
1454
            offset = 0x7f2c + (i - 3) * 12;
1455
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1456
        stl_phys(sm_state + offset + 8, dt->base);
1457
        stl_phys(sm_state + offset + 4, dt->limit);
1458
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1459
    }
1460
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1461

    
1462
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1463
    stl_phys(sm_state + 0x7ef8, env->smbase);
1464
#endif
1465
    /* init SMM cpu state */
1466

    
1467
#ifdef TARGET_X86_64
1468
    cpu_load_efer(env, 0);
1469
#endif
1470
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1471
    env->eip = 0x00008000;
1472
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1473
                           0xffffffff, 0);
1474
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1475
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1476
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1477
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1478
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1479

    
1480
    cpu_x86_update_cr0(env,
1481
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1482
    cpu_x86_update_cr4(env, 0);
1483
    env->dr[7] = 0x00000400;
1484
    CC_OP = CC_OP_EFLAGS;
1485
}
1486

    
1487
void helper_rsm(void)
1488
{
1489
    target_ulong sm_state;
1490
    int i, offset;
1491
    uint32_t val;
1492

    
1493
    sm_state = env->smbase + 0x8000;
1494
#ifdef TARGET_X86_64
1495
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1496

    
1497
    for(i = 0; i < 6; i++) {
1498
        offset = 0x7e00 + i * 16;
1499
        cpu_x86_load_seg_cache(env, i,
1500
                               lduw_phys(sm_state + offset),
1501
                               ldq_phys(sm_state + offset + 8),
1502
                               ldl_phys(sm_state + offset + 4),
1503
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1504
    }
1505

    
1506
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1507
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1508

    
1509
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1510
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1511
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1512
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1513

    
1514
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1515
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1516

    
1517
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1518
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1519
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1520
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1521

    
1522
    EAX = ldq_phys(sm_state + 0x7ff8);
1523
    ECX = ldq_phys(sm_state + 0x7ff0);
1524
    EDX = ldq_phys(sm_state + 0x7fe8);
1525
    EBX = ldq_phys(sm_state + 0x7fe0);
1526
    ESP = ldq_phys(sm_state + 0x7fd8);
1527
    EBP = ldq_phys(sm_state + 0x7fd0);
1528
    ESI = ldq_phys(sm_state + 0x7fc8);
1529
    EDI = ldq_phys(sm_state + 0x7fc0);
1530
    for(i = 8; i < 16; i++)
1531
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1532
    env->eip = ldq_phys(sm_state + 0x7f78);
1533
    load_eflags(ldl_phys(sm_state + 0x7f70),
1534
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1535
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1536
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1537

    
1538
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1539
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1540
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1541

    
1542
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1543
    if (val & 0x20000) {
1544
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1545
    }
1546
#else
1547
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1548
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1549
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1550
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1551
    env->eip = ldl_phys(sm_state + 0x7ff0);
1552
    EDI = ldl_phys(sm_state + 0x7fec);
1553
    ESI = ldl_phys(sm_state + 0x7fe8);
1554
    EBP = ldl_phys(sm_state + 0x7fe4);
1555
    ESP = ldl_phys(sm_state + 0x7fe0);
1556
    EBX = ldl_phys(sm_state + 0x7fdc);
1557
    EDX = ldl_phys(sm_state + 0x7fd8);
1558
    ECX = ldl_phys(sm_state + 0x7fd4);
1559
    EAX = ldl_phys(sm_state + 0x7fd0);
1560
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1561
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1562

    
1563
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1564
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1565
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1566
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1567

    
1568
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1569
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1570
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1571
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1572

    
1573
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1574
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1575

    
1576
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1577
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1578

    
1579
    for(i = 0; i < 6; i++) {
1580
        if (i < 3)
1581
            offset = 0x7f84 + i * 12;
1582
        else
1583
            offset = 0x7f2c + (i - 3) * 12;
1584
        cpu_x86_load_seg_cache(env, i,
1585
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1586
                               ldl_phys(sm_state + offset + 8),
1587
                               ldl_phys(sm_state + offset + 4),
1588
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1589
    }
1590
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1591

    
1592
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1593
    if (val & 0x20000) {
1594
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1595
    }
1596
#endif
1597
    CC_OP = CC_OP_EFLAGS;
1598
    env->hflags &= ~HF_SMM_MASK;
1599
    cpu_smm_update(env);
1600

    
1601
    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
1602
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1603
}
1604

    
1605
#endif /* !CONFIG_USER_ONLY */
1606

    
1607

    
1608
/* division, flags are undefined */
1609

    
1610
void helper_divb_AL(target_ulong t0)
1611
{
1612
    unsigned int num, den, q, r;
1613

    
1614
    num = (EAX & 0xffff);
1615
    den = (t0 & 0xff);
1616
    if (den == 0) {
1617
        raise_exception(EXCP00_DIVZ);
1618
    }
1619
    q = (num / den);
1620
    if (q > 0xff)
1621
        raise_exception(EXCP00_DIVZ);
1622
    q &= 0xff;
1623
    r = (num % den) & 0xff;
1624
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1625
}
1626

    
1627
void helper_idivb_AL(target_ulong t0)
1628
{
1629
    int num, den, q, r;
1630

    
1631
    num = (int16_t)EAX;
1632
    den = (int8_t)t0;
1633
    if (den == 0) {
1634
        raise_exception(EXCP00_DIVZ);
1635
    }
1636
    q = (num / den);
1637
    if (q != (int8_t)q)
1638
        raise_exception(EXCP00_DIVZ);
1639
    q &= 0xff;
1640
    r = (num % den) & 0xff;
1641
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1642
}
1643

    
1644
void helper_divw_AX(target_ulong t0)
1645
{
1646
    unsigned int num, den, q, r;
1647

    
1648
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1649
    den = (t0 & 0xffff);
1650
    if (den == 0) {
1651
        raise_exception(EXCP00_DIVZ);
1652
    }
1653
    q = (num / den);
1654
    if (q > 0xffff)
1655
        raise_exception(EXCP00_DIVZ);
1656
    q &= 0xffff;
1657
    r = (num % den) & 0xffff;
1658
    EAX = (EAX & ~0xffff) | q;
1659
    EDX = (EDX & ~0xffff) | r;
1660
}
1661

    
1662
void helper_idivw_AX(target_ulong t0)
1663
{
1664
    int num, den, q, r;
1665

    
1666
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1667
    den = (int16_t)t0;
1668
    if (den == 0) {
1669
        raise_exception(EXCP00_DIVZ);
1670
    }
1671
    q = (num / den);
1672
    if (q != (int16_t)q)
1673
        raise_exception(EXCP00_DIVZ);
1674
    q &= 0xffff;
1675
    r = (num % den) & 0xffff;
1676
    EAX = (EAX & ~0xffff) | q;
1677
    EDX = (EDX & ~0xffff) | r;
1678
}
1679

    
1680
void helper_divl_EAX(target_ulong t0)
1681
{
1682
    unsigned int den, r;
1683
    uint64_t num, q;
1684

    
1685
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1686
    den = t0;
1687
    if (den == 0) {
1688
        raise_exception(EXCP00_DIVZ);
1689
    }
1690
    q = (num / den);
1691
    r = (num % den);
1692
    if (q > 0xffffffff)
1693
        raise_exception(EXCP00_DIVZ);
1694
    EAX = (uint32_t)q;
1695
    EDX = (uint32_t)r;
1696
}
1697

    
1698
void helper_idivl_EAX(target_ulong t0)
1699
{
1700
    int den, r;
1701
    int64_t num, q;
1702

    
1703
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1704
    den = t0;
1705
    if (den == 0) {
1706
        raise_exception(EXCP00_DIVZ);
1707
    }
1708
    q = (num / den);
1709
    r = (num % den);
1710
    if (q != (int32_t)q)
1711
        raise_exception(EXCP00_DIVZ);
1712
    EAX = (uint32_t)q;
1713
    EDX = (uint32_t)r;
1714
}
1715

    
1716
/* bcd */
1717

    
1718
/* XXX: exception */
1719
void helper_aam(int base)
1720
{
1721
    int al, ah;
1722
    al = EAX & 0xff;
1723
    ah = al / base;
1724
    al = al % base;
1725
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1726
    CC_DST = al;
1727
}
1728

    
1729
void helper_aad(int base)
1730
{
1731
    int al, ah;
1732
    al = EAX & 0xff;
1733
    ah = (EAX >> 8) & 0xff;
1734
    al = ((ah * base) + al) & 0xff;
1735
    EAX = (EAX & ~0xffff) | al;
1736
    CC_DST = al;
1737
}
1738

    
1739
void helper_aaa(void)
1740
{
1741
    int icarry;
1742
    int al, ah, af;
1743
    int eflags;
1744

    
1745
    eflags = helper_cc_compute_all(CC_OP);
1746
    af = eflags & CC_A;
1747
    al = EAX & 0xff;
1748
    ah = (EAX >> 8) & 0xff;
1749

    
1750
    icarry = (al > 0xf9);
1751
    if (((al & 0x0f) > 9 ) || af) {
1752
        al = (al + 6) & 0x0f;
1753
        ah = (ah + 1 + icarry) & 0xff;
1754
        eflags |= CC_C | CC_A;
1755
    } else {
1756
        eflags &= ~(CC_C | CC_A);
1757
        al &= 0x0f;
1758
    }
1759
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1760
    CC_SRC = eflags;
1761
}
1762

    
1763
void helper_aas(void)
1764
{
1765
    int icarry;
1766
    int al, ah, af;
1767
    int eflags;
1768

    
1769
    eflags = helper_cc_compute_all(CC_OP);
1770
    af = eflags & CC_A;
1771
    al = EAX & 0xff;
1772
    ah = (EAX >> 8) & 0xff;
1773

    
1774
    icarry = (al < 6);
1775
    if (((al & 0x0f) > 9 ) || af) {
1776
        al = (al - 6) & 0x0f;
1777
        ah = (ah - 1 - icarry) & 0xff;
1778
        eflags |= CC_C | CC_A;
1779
    } else {
1780
        eflags &= ~(CC_C | CC_A);
1781
        al &= 0x0f;
1782
    }
1783
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1784
    CC_SRC = eflags;
1785
}
1786

    
1787
void helper_daa(void)
1788
{
1789
    int al, af, cf;
1790
    int eflags;
1791

    
1792
    eflags = helper_cc_compute_all(CC_OP);
1793
    cf = eflags & CC_C;
1794
    af = eflags & CC_A;
1795
    al = EAX & 0xff;
1796

    
1797
    eflags = 0;
1798
    if (((al & 0x0f) > 9 ) || af) {
1799
        al = (al + 6) & 0xff;
1800
        eflags |= CC_A;
1801
    }
1802
    if ((al > 0x9f) || cf) {
1803
        al = (al + 0x60) & 0xff;
1804
        eflags |= CC_C;
1805
    }
1806
    EAX = (EAX & ~0xff) | al;
1807
    /* well, speed is not an issue here, so we compute the flags by hand */
1808
    eflags |= (al == 0) << 6; /* zf */
1809
    eflags |= parity_table[al]; /* pf */
1810
    eflags |= (al & 0x80); /* sf */
1811
    CC_SRC = eflags;
1812
}
1813

    
1814
void helper_das(void)
1815
{
1816
    int al, al1, af, cf;
1817
    int eflags;
1818

    
1819
    eflags = helper_cc_compute_all(CC_OP);
1820
    cf = eflags & CC_C;
1821
    af = eflags & CC_A;
1822
    al = EAX & 0xff;
1823

    
1824
    eflags = 0;
1825
    al1 = al;
1826
    if (((al & 0x0f) > 9 ) || af) {
1827
        eflags |= CC_A;
1828
        if (al < 6 || cf)
1829
            eflags |= CC_C;
1830
        al = (al - 6) & 0xff;
1831
    }
1832
    if ((al1 > 0x99) || cf) {
1833
        al = (al - 0x60) & 0xff;
1834
        eflags |= CC_C;
1835
    }
1836
    EAX = (EAX & ~0xff) | al;
1837
    /* well, speed is not an issue here, so we compute the flags by hand */
1838
    eflags |= (al == 0) << 6; /* zf */
1839
    eflags |= parity_table[al]; /* pf */
1840
    eflags |= (al & 0x80); /* sf */
1841
    CC_SRC = eflags;
1842
}
1843

    
1844
void helper_into(int next_eip_addend)
1845
{
1846
    int eflags;
1847
    eflags = helper_cc_compute_all(CC_OP);
1848
    if (eflags & CC_O) {
1849
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1850
    }
1851
}
1852

    
1853
void helper_cmpxchg8b(target_ulong a0)
1854
{
1855
    uint64_t d;
1856
    int eflags;
1857

    
1858
    eflags = helper_cc_compute_all(CC_OP);
1859
    d = ldq(a0);
1860
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1861
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1862
        eflags |= CC_Z;
1863
    } else {
1864
        /* always do the store */
1865
        stq(a0, d); 
1866
        EDX = (uint32_t)(d >> 32);
1867
        EAX = (uint32_t)d;
1868
        eflags &= ~CC_Z;
1869
    }
1870
    CC_SRC = eflags;
1871
}
1872

    
1873
#ifdef TARGET_X86_64
1874
void helper_cmpxchg16b(target_ulong a0)
1875
{
1876
    uint64_t d0, d1;
1877
    int eflags;
1878

    
1879
    if ((a0 & 0xf) != 0)
1880
        raise_exception(EXCP0D_GPF);
1881
    eflags = helper_cc_compute_all(CC_OP);
1882
    d0 = ldq(a0);
1883
    d1 = ldq(a0 + 8);
1884
    if (d0 == EAX && d1 == EDX) {
1885
        stq(a0, EBX);
1886
        stq(a0 + 8, ECX);
1887
        eflags |= CC_Z;
1888
    } else {
1889
        /* always do the store */
1890
        stq(a0, d0); 
1891
        stq(a0 + 8, d1); 
1892
        EDX = d1;
1893
        EAX = d0;
1894
        eflags &= ~CC_Z;
1895
    }
1896
    CC_SRC = eflags;
1897
}
1898
#endif
1899

    
1900
void helper_single_step(void)
1901
{
1902
#ifndef CONFIG_USER_ONLY
1903
    check_hw_breakpoints(env, 1);
1904
    env->dr[6] |= DR6_BS;
1905
#endif
1906
    raise_exception(EXCP01_DB);
1907
}
1908

    
1909
void helper_cpuid(void)
1910
{
1911
    uint32_t eax, ebx, ecx, edx;
1912

    
1913
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1914

    
1915
    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
1916
    EAX = eax;
1917
    EBX = ebx;
1918
    ECX = ecx;
1919
    EDX = edx;
1920
}
1921

    
1922
void helper_enter_level(int level, int data32, target_ulong t1)
1923
{
1924
    target_ulong ssp;
1925
    uint32_t esp_mask, esp, ebp;
1926

    
1927
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1928
    ssp = env->segs[R_SS].base;
1929
    ebp = EBP;
1930
    esp = ESP;
1931
    if (data32) {
1932
        /* 32 bit */
1933
        esp -= 4;
1934
        while (--level) {
1935
            esp -= 4;
1936
            ebp -= 4;
1937
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1938
        }
1939
        esp -= 4;
1940
        stl(ssp + (esp & esp_mask), t1);
1941
    } else {
1942
        /* 16 bit */
1943
        esp -= 2;
1944
        while (--level) {
1945
            esp -= 2;
1946
            ebp -= 2;
1947
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1948
        }
1949
        esp -= 2;
1950
        stw(ssp + (esp & esp_mask), t1);
1951
    }
1952
}
1953

    
1954
#ifdef TARGET_X86_64
1955
void helper_enter64_level(int level, int data64, target_ulong t1)
1956
{
1957
    target_ulong esp, ebp;
1958
    ebp = EBP;
1959
    esp = ESP;
1960

    
1961
    if (data64) {
1962
        /* 64 bit */
1963
        esp -= 8;
1964
        while (--level) {
1965
            esp -= 8;
1966
            ebp -= 8;
1967
            stq(esp, ldq(ebp));
1968
        }
1969
        esp -= 8;
1970
        stq(esp, t1);
1971
    } else {
1972
        /* 16 bit */
1973
        esp -= 2;
1974
        while (--level) {
1975
            esp -= 2;
1976
            ebp -= 2;
1977
            stw(esp, lduw(ebp));
1978
        }
1979
        esp -= 2;
1980
        stw(esp, t1);
1981
    }
1982
}
1983
#endif
1984

    
1985
void helper_lldt(int selector)
1986
{
1987
    SegmentCache *dt;
1988
    uint32_t e1, e2;
1989
    int index, entry_limit;
1990
    target_ulong ptr;
1991

    
1992
    selector &= 0xffff;
1993
    if ((selector & 0xfffc) == 0) {
1994
        /* XXX: NULL selector case: invalid LDT */
1995
        env->ldt.base = 0;
1996
        env->ldt.limit = 0;
1997
    } else {
1998
        if (selector & 0x4)
1999
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2000
        dt = &env->gdt;
2001
        index = selector & ~7;
2002
#ifdef TARGET_X86_64
2003
        if (env->hflags & HF_LMA_MASK)
2004
            entry_limit = 15;
2005
        else
2006
#endif
2007
            entry_limit = 7;
2008
        if ((index + entry_limit) > dt->limit)
2009
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2010
        ptr = dt->base + index;
2011
        e1 = ldl_kernel(ptr);
2012
        e2 = ldl_kernel(ptr + 4);
2013
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2014
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2015
        if (!(e2 & DESC_P_MASK))
2016
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2017
#ifdef TARGET_X86_64
2018
        if (env->hflags & HF_LMA_MASK) {
2019
            uint32_t e3;
2020
            e3 = ldl_kernel(ptr + 8);
2021
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2022
            env->ldt.base |= (target_ulong)e3 << 32;
2023
        } else
2024
#endif
2025
        {
2026
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2027
        }
2028
    }
2029
    env->ldt.selector = selector;
2030
}
2031

    
2032
void helper_ltr(int selector)
2033
{
2034
    SegmentCache *dt;
2035
    uint32_t e1, e2;
2036
    int index, type, entry_limit;
2037
    target_ulong ptr;
2038

    
2039
    selector &= 0xffff;
2040
    if ((selector & 0xfffc) == 0) {
2041
        /* NULL selector case: invalid TR */
2042
        env->tr.base = 0;
2043
        env->tr.limit = 0;
2044
        env->tr.flags = 0;
2045
    } else {
2046
        if (selector & 0x4)
2047
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2048
        dt = &env->gdt;
2049
        index = selector & ~7;
2050
#ifdef TARGET_X86_64
2051
        if (env->hflags & HF_LMA_MASK)
2052
            entry_limit = 15;
2053
        else
2054
#endif
2055
            entry_limit = 7;
2056
        if ((index + entry_limit) > dt->limit)
2057
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2058
        ptr = dt->base + index;
2059
        e1 = ldl_kernel(ptr);
2060
        e2 = ldl_kernel(ptr + 4);
2061
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2062
        if ((e2 & DESC_S_MASK) ||
2063
            (type != 1 && type != 9))
2064
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2065
        if (!(e2 & DESC_P_MASK))
2066
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2067
#ifdef TARGET_X86_64
2068
        if (env->hflags & HF_LMA_MASK) {
2069
            uint32_t e3, e4;
2070
            e3 = ldl_kernel(ptr + 8);
2071
            e4 = ldl_kernel(ptr + 12);
2072
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2073
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2074
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2075
            env->tr.base |= (target_ulong)e3 << 32;
2076
        } else
2077
#endif
2078
        {
2079
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2080
        }
2081
        e2 |= DESC_TSS_BUSY_MASK;
2082
        stl_kernel(ptr + 4, e2);
2083
    }
2084
    env->tr.selector = selector;
2085
}
2086

    
2087
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2088
void helper_load_seg(int seg_reg, int selector)
2089
{
2090
    uint32_t e1, e2;
2091
    int cpl, dpl, rpl;
2092
    SegmentCache *dt;
2093
    int index;
2094
    target_ulong ptr;
2095

    
2096
    selector &= 0xffff;
2097
    cpl = env->hflags & HF_CPL_MASK;
2098
    if ((selector & 0xfffc) == 0) {
2099
        /* null selector case */
2100
        if (seg_reg == R_SS
2101
#ifdef TARGET_X86_64
2102
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2103
#endif
2104
            )
2105
            raise_exception_err(EXCP0D_GPF, 0);
2106
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2107
    } else {
2108

    
2109
        if (selector & 0x4)
2110
            dt = &env->ldt;
2111
        else
2112
            dt = &env->gdt;
2113
        index = selector & ~7;
2114
        if ((index + 7) > dt->limit)
2115
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2116
        ptr = dt->base + index;
2117
        e1 = ldl_kernel(ptr);
2118
        e2 = ldl_kernel(ptr + 4);
2119

    
2120
        if (!(e2 & DESC_S_MASK))
2121
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2122
        rpl = selector & 3;
2123
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2124
        if (seg_reg == R_SS) {
2125
            /* must be writable segment */
2126
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2127
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2128
            if (rpl != cpl || dpl != cpl)
2129
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2130
        } else {
2131
            /* must be readable segment */
2132
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2133
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2134

    
2135
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2136
                /* if not conforming code, test rights */
2137
                if (dpl < cpl || dpl < rpl)
2138
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2139
            }
2140
        }
2141

    
2142
        if (!(e2 & DESC_P_MASK)) {
2143
            if (seg_reg == R_SS)
2144
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2145
            else
2146
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2147
        }
2148

    
2149
        /* set the access bit if not already set */
2150
        if (!(e2 & DESC_A_MASK)) {
2151
            e2 |= DESC_A_MASK;
2152
            stl_kernel(ptr + 4, e2);
2153
        }
2154

    
2155
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2156
                       get_seg_base(e1, e2),
2157
                       get_seg_limit(e1, e2),
2158
                       e2);
2159
#if 0
2160
        qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2161
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2162
#endif
2163
    }
2164
}
2165

    
2166
/* protected mode jump */
2167
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2168
                           int next_eip_addend)
2169
{
2170
    int gate_cs, type;
2171
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2172
    target_ulong next_eip;
2173

    
2174
    if ((new_cs & 0xfffc) == 0)
2175
        raise_exception_err(EXCP0D_GPF, 0);
2176
    if (load_segment(&e1, &e2, new_cs) != 0)
2177
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2178
    cpl = env->hflags & HF_CPL_MASK;
2179
    if (e2 & DESC_S_MASK) {
2180
        if (!(e2 & DESC_CS_MASK))
2181
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2182
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2183
        if (e2 & DESC_C_MASK) {
2184
            /* conforming code segment */
2185
            if (dpl > cpl)
2186
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2187
        } else {
2188
            /* non conforming code segment */
2189
            rpl = new_cs & 3;
2190
            if (rpl > cpl)
2191
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2192
            if (dpl != cpl)
2193
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2194
        }
2195
        if (!(e2 & DESC_P_MASK))
2196
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2197
        limit = get_seg_limit(e1, e2);
2198
        if (new_eip > limit &&
2199
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2200
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2201
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2202
                       get_seg_base(e1, e2), limit, e2);
2203
        EIP = new_eip;
2204
    } else {
2205
        /* jump to call or task gate */
2206
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2207
        rpl = new_cs & 3;
2208
        cpl = env->hflags & HF_CPL_MASK;
2209
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2210
        switch(type) {
2211
        case 1: /* 286 TSS */
2212
        case 9: /* 386 TSS */
2213
        case 5: /* task gate */
2214
            if (dpl < cpl || dpl < rpl)
2215
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2216
            next_eip = env->eip + next_eip_addend;
2217
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2218
            CC_OP = CC_OP_EFLAGS;
2219
            break;
2220
        case 4: /* 286 call gate */
2221
        case 12: /* 386 call gate */
2222
            if ((dpl < cpl) || (dpl < rpl))
2223
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2224
            if (!(e2 & DESC_P_MASK))
2225
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2226
            gate_cs = e1 >> 16;
2227
            new_eip = (e1 & 0xffff);
2228
            if (type == 12)
2229
                new_eip |= (e2 & 0xffff0000);
2230
            if (load_segment(&e1, &e2, gate_cs) != 0)
2231
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2232
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2233
            /* must be code segment */
2234
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2235
                 (DESC_S_MASK | DESC_CS_MASK)))
2236
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2237
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2238
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2239
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2240
            if (!(e2 & DESC_P_MASK))
2241
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2242
            limit = get_seg_limit(e1, e2);
2243
            if (new_eip > limit)
2244
                raise_exception_err(EXCP0D_GPF, 0);
2245
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2246
                                   get_seg_base(e1, e2), limit, e2);
2247
            EIP = new_eip;
2248
            break;
2249
        default:
2250
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2251
            break;
2252
        }
2253
    }
2254
}
2255

    
2256
/* real mode call */
2257
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2258
                       int shift, int next_eip)
2259
{
2260
    int new_eip;
2261
    uint32_t esp, esp_mask;
2262
    target_ulong ssp;
2263

    
2264
    new_eip = new_eip1;
2265
    esp = ESP;
2266
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2267
    ssp = env->segs[R_SS].base;
2268
    if (shift) {
2269
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2270
        PUSHL(ssp, esp, esp_mask, next_eip);
2271
    } else {
2272
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2273
        PUSHW(ssp, esp, esp_mask, next_eip);
2274
    }
2275

    
2276
    SET_ESP(esp, esp_mask);
2277
    env->eip = new_eip;
2278
    env->segs[R_CS].selector = new_cs;
2279
    env->segs[R_CS].base = (new_cs << 4);
2280
}
2281

    
2282
/* protected mode call */
2283
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2284
                            int shift, int next_eip_addend)
2285
{
2286
    int new_stack, i;
2287
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2288
    uint32_t ss = 0, ss_e1 = 0, ss_e2 = 0, sp, type, ss_dpl, sp_mask;
2289
    uint32_t val, limit, old_sp_mask;
2290
    target_ulong ssp, old_ssp, next_eip;
2291

    
2292
    next_eip = env->eip + next_eip_addend;
2293
    LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
2294
    LOG_PCALL_STATE(env);
2295
    if ((new_cs & 0xfffc) == 0)
2296
        raise_exception_err(EXCP0D_GPF, 0);
2297
    if (load_segment(&e1, &e2, new_cs) != 0)
2298
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2299
    cpl = env->hflags & HF_CPL_MASK;
2300
    LOG_PCALL("desc=%08x:%08x\n", e1, e2);
2301
    if (e2 & DESC_S_MASK) {
2302
        if (!(e2 & DESC_CS_MASK))
2303
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2304
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2305
        if (e2 & DESC_C_MASK) {
2306
            /* conforming code segment */
2307
            if (dpl > cpl)
2308
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2309
        } else {
2310
            /* non conforming code segment */
2311
            rpl = new_cs & 3;
2312
            if (rpl > cpl)
2313
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2314
            if (dpl != cpl)
2315
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2316
        }
2317
        if (!(e2 & DESC_P_MASK))
2318
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2319

    
2320
#ifdef TARGET_X86_64
2321
        /* XXX: check 16/32 bit cases in long mode */
2322
        if (shift == 2) {
2323
            target_ulong rsp;
2324
            /* 64 bit case */
2325
            rsp = ESP;
2326
            PUSHQ(rsp, env->segs[R_CS].selector);
2327
            PUSHQ(rsp, next_eip);
2328
            /* from this point, not restartable */
2329
            ESP = rsp;
2330
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2331
                                   get_seg_base(e1, e2),
2332
                                   get_seg_limit(e1, e2), e2);
2333
            EIP = new_eip;
2334
        } else
2335
#endif
2336
        {
2337
            sp = ESP;
2338
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2339
            ssp = env->segs[R_SS].base;
2340
            if (shift) {
2341
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2342
                PUSHL(ssp, sp, sp_mask, next_eip);
2343
            } else {
2344
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2345
                PUSHW(ssp, sp, sp_mask, next_eip);
2346
            }
2347

    
2348
            limit = get_seg_limit(e1, e2);
2349
            if (new_eip > limit)
2350
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2351
            /* from this point, not restartable */
2352
            SET_ESP(sp, sp_mask);
2353
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2354
                                   get_seg_base(e1, e2), limit, e2);
2355
            EIP = new_eip;
2356
        }
2357
    } else {
2358
        /* check gate type */
2359
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2360
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2361
        rpl = new_cs & 3;
2362
        switch(type) {
2363
        case 1: /* available 286 TSS */
2364
        case 9: /* available 386 TSS */
2365
        case 5: /* task gate */
2366
            if (dpl < cpl || dpl < rpl)
2367
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2368
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2369
            CC_OP = CC_OP_EFLAGS;
2370
            return;
2371
        case 4: /* 286 call gate */
2372
        case 12: /* 386 call gate */
2373
            break;
2374
        default:
2375
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2376
            break;
2377
        }
2378
        shift = type >> 3;
2379

    
2380
        if (dpl < cpl || dpl < rpl)
2381
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2382
        /* check valid bit */
2383
        if (!(e2 & DESC_P_MASK))
2384
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2385
        selector = e1 >> 16;
2386
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2387
        param_count = e2 & 0x1f;
2388
        if ((selector & 0xfffc) == 0)
2389
            raise_exception_err(EXCP0D_GPF, 0);
2390

    
2391
        if (load_segment(&e1, &e2, selector) != 0)
2392
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2393
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2394
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2395
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2396
        if (dpl > cpl)
2397
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2398
        if (!(e2 & DESC_P_MASK))
2399
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2400

    
2401
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2402
            /* to inner privilege */
2403
            get_ss_esp_from_tss(&ss, &sp, dpl);
2404
            LOG_PCALL("new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2405
                        ss, sp, param_count, ESP);
2406
            if ((ss & 0xfffc) == 0)
2407
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2408
            if ((ss & 3) != dpl)
2409
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2410
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2411
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2412
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2413
            if (ss_dpl != dpl)
2414
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2415
            if (!(ss_e2 & DESC_S_MASK) ||
2416
                (ss_e2 & DESC_CS_MASK) ||
2417
                !(ss_e2 & DESC_W_MASK))
2418
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2419
            if (!(ss_e2 & DESC_P_MASK))
2420
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2421

    
2422
            //            push_size = ((param_count * 2) + 8) << shift;
2423

    
2424
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2425
            old_ssp = env->segs[R_SS].base;
2426

    
2427
            sp_mask = get_sp_mask(ss_e2);
2428
            ssp = get_seg_base(ss_e1, ss_e2);
2429
            if (shift) {
2430
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2431
                PUSHL(ssp, sp, sp_mask, ESP);
2432
                for(i = param_count - 1; i >= 0; i--) {
2433
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2434
                    PUSHL(ssp, sp, sp_mask, val);
2435
                }
2436
            } else {
2437
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2438
                PUSHW(ssp, sp, sp_mask, ESP);
2439
                for(i = param_count - 1; i >= 0; i--) {
2440
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2441
                    PUSHW(ssp, sp, sp_mask, val);
2442
                }
2443
            }
2444
            new_stack = 1;
2445
        } else {
2446
            /* to same privilege */
2447
            sp = ESP;
2448
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2449
            ssp = env->segs[R_SS].base;
2450
            //            push_size = (4 << shift);
2451
            new_stack = 0;
2452
        }
2453

    
2454
        if (shift) {
2455
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2456
            PUSHL(ssp, sp, sp_mask, next_eip);
2457
        } else {
2458
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2459
            PUSHW(ssp, sp, sp_mask, next_eip);
2460
        }
2461

    
2462
        /* from this point, not restartable */
2463

    
2464
        if (new_stack) {
2465
            ss = (ss & ~3) | dpl;
2466
            cpu_x86_load_seg_cache(env, R_SS, ss,
2467
                                   ssp,
2468
                                   get_seg_limit(ss_e1, ss_e2),
2469
                                   ss_e2);
2470
        }
2471

    
2472
        selector = (selector & ~3) | dpl;
2473
        cpu_x86_load_seg_cache(env, R_CS, selector,
2474
                       get_seg_base(e1, e2),
2475
                       get_seg_limit(e1, e2),
2476
                       e2);
2477
        cpu_x86_set_cpl(env, dpl);
2478
        SET_ESP(sp, sp_mask);
2479
        EIP = offset;
2480
    }
2481
#ifdef USE_KQEMU
2482
    if (kqemu_is_ok(env)) {
2483
        env->exception_index = -1;
2484
        cpu_loop_exit();
2485
    }
2486
#endif
2487
}
2488

    
2489
/* real and vm86 mode iret */
2490
void helper_iret_real(int shift)
2491
{
2492
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2493
    target_ulong ssp;
2494
    int eflags_mask;
2495

    
2496
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2497
    sp = ESP;
2498
    ssp = env->segs[R_SS].base;
2499
    if (shift == 1) {
2500
        /* 32 bits */
2501
        POPL(ssp, sp, sp_mask, new_eip);
2502
        POPL(ssp, sp, sp_mask, new_cs);
2503
        new_cs &= 0xffff;
2504
        POPL(ssp, sp, sp_mask, new_eflags);
2505
    } else {
2506
        /* 16 bits */
2507
        POPW(ssp, sp, sp_mask, new_eip);
2508
        POPW(ssp, sp, sp_mask, new_cs);
2509
        POPW(ssp, sp, sp_mask, new_eflags);
2510
    }
2511
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2512
    env->segs[R_CS].selector = new_cs;
2513
    env->segs[R_CS].base = (new_cs << 4);
2514
    env->eip = new_eip;
2515
    if (env->eflags & VM_MASK)
2516
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2517
    else
2518
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2519
    if (shift == 0)
2520
        eflags_mask &= 0xffff;
2521
    load_eflags(new_eflags, eflags_mask);
2522
    env->hflags2 &= ~HF2_NMI_MASK;
2523
}
2524

    
2525
static inline void validate_seg(int seg_reg, int cpl)
2526
{
2527
    int dpl;
2528
    uint32_t e2;
2529

    
2530
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2531
       they may still contain a valid base. I would be interested to
2532
       know how a real x86_64 CPU behaves */
2533
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2534
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2535
        return;
2536

    
2537
    e2 = env->segs[seg_reg].flags;
2538
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2539
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2540
        /* data or non conforming code segment */
2541
        if (dpl < cpl) {
2542
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2543
        }
2544
    }
2545
}
2546

    
2547
/* protected mode iret */
2548
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2549
{
2550
    uint32_t new_cs, new_eflags, new_ss;
2551
    uint32_t new_es, new_ds, new_fs, new_gs;
2552
    uint32_t e1, e2, ss_e1, ss_e2;
2553
    int cpl, dpl, rpl, eflags_mask, iopl;
2554
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2555

    
2556
#ifdef TARGET_X86_64
2557
    if (shift == 2)
2558
        sp_mask = -1;
2559
    else
2560
#endif
2561
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2562
    sp = ESP;
2563
    ssp = env->segs[R_SS].base;
2564
    new_eflags = 0; /* avoid warning */
2565
#ifdef TARGET_X86_64
2566
    if (shift == 2) {
2567
        POPQ(sp, new_eip);
2568
        POPQ(sp, new_cs);
2569
        new_cs &= 0xffff;
2570
        if (is_iret) {
2571
            POPQ(sp, new_eflags);
2572
        }
2573
    } else
2574
#endif
2575
    if (shift == 1) {
2576
        /* 32 bits */
2577
        POPL(ssp, sp, sp_mask, new_eip);
2578
        POPL(ssp, sp, sp_mask, new_cs);
2579
        new_cs &= 0xffff;
2580
        if (is_iret) {
2581
            POPL(ssp, sp, sp_mask, new_eflags);
2582
            if (new_eflags & VM_MASK)
2583
                goto return_to_vm86;
2584
        }
2585
    } else {
2586
        /* 16 bits */
2587
        POPW(ssp, sp, sp_mask, new_eip);
2588
        POPW(ssp, sp, sp_mask, new_cs);
2589
        if (is_iret)
2590
            POPW(ssp, sp, sp_mask, new_eflags);
2591
    }
2592
    LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2593
              new_cs, new_eip, shift, addend);
2594
    LOG_PCALL_STATE(env);
2595
    if ((new_cs & 0xfffc) == 0)
2596
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2597
    if (load_segment(&e1, &e2, new_cs) != 0)
2598
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2599
    if (!(e2 & DESC_S_MASK) ||
2600
        !(e2 & DESC_CS_MASK))
2601
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2602
    cpl = env->hflags & HF_CPL_MASK;
2603
    rpl = new_cs & 3;
2604
    if (rpl < cpl)
2605
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2606
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2607
    if (e2 & DESC_C_MASK) {
2608
        if (dpl > rpl)
2609
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2610
    } else {
2611
        if (dpl != rpl)
2612
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2613
    }
2614
    if (!(e2 & DESC_P_MASK))
2615
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2616

    
2617
    sp += addend;
2618
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2619
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2620
        /* return to same privilege level */
2621
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2622
                       get_seg_base(e1, e2),
2623
                       get_seg_limit(e1, e2),
2624
                       e2);
2625
    } else {
2626
        /* return to different privilege level */
2627
#ifdef TARGET_X86_64
2628
        if (shift == 2) {
2629
            POPQ(sp, new_esp);
2630
            POPQ(sp, new_ss);
2631
            new_ss &= 0xffff;
2632
        } else
2633
#endif
2634
        if (shift == 1) {
2635
            /* 32 bits */
2636
            POPL(ssp, sp, sp_mask, new_esp);
2637
            POPL(ssp, sp, sp_mask, new_ss);
2638
            new_ss &= 0xffff;
2639
        } else {
2640
            /* 16 bits */
2641
            POPW(ssp, sp, sp_mask, new_esp);
2642
            POPW(ssp, sp, sp_mask, new_ss);
2643
        }
2644
        LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",
2645
                    new_ss, new_esp);
2646
        if ((new_ss & 0xfffc) == 0) {
2647
#ifdef TARGET_X86_64
2648
            /* NULL ss is allowed in long mode if cpl != 3*/
2649
            /* XXX: test CS64 ? */
2650
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2651
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2652
                                       0, 0xffffffff,
2653
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2654
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2655
                                       DESC_W_MASK | DESC_A_MASK);
2656
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2657
            } else
2658
#endif
2659
            {
2660
                raise_exception_err(EXCP0D_GPF, 0);
2661
            }
2662
        } else {
2663
            if ((new_ss & 3) != rpl)
2664
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2665
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2666
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2667
            if (!(ss_e2 & DESC_S_MASK) ||
2668
                (ss_e2 & DESC_CS_MASK) ||
2669
                !(ss_e2 & DESC_W_MASK))
2670
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2671
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2672
            if (dpl != rpl)
2673
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2674
            if (!(ss_e2 & DESC_P_MASK))
2675
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2676
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2677
                                   get_seg_base(ss_e1, ss_e2),
2678
                                   get_seg_limit(ss_e1, ss_e2),
2679
                                   ss_e2);
2680
        }
2681

    
2682
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2683
                       get_seg_base(e1, e2),
2684
                       get_seg_limit(e1, e2),
2685
                       e2);
2686
        cpu_x86_set_cpl(env, rpl);
2687
        sp = new_esp;
2688
#ifdef TARGET_X86_64
2689
        if (env->hflags & HF_CS64_MASK)
2690
            sp_mask = -1;
2691
        else
2692
#endif
2693
            sp_mask = get_sp_mask(ss_e2);
2694

    
2695
        /* validate data segments */
2696
        validate_seg(R_ES, rpl);
2697
        validate_seg(R_DS, rpl);
2698
        validate_seg(R_FS, rpl);
2699
        validate_seg(R_GS, rpl);
2700

    
2701
        sp += addend;
2702
    }
2703
    SET_ESP(sp, sp_mask);
2704
    env->eip = new_eip;
2705
    if (is_iret) {
2706
        /* NOTE: 'cpl' is the _old_ CPL */
2707
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2708
        if (cpl == 0)
2709
            eflags_mask |= IOPL_MASK;
2710
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2711
        if (cpl <= iopl)
2712
            eflags_mask |= IF_MASK;
2713
        if (shift == 0)
2714
            eflags_mask &= 0xffff;
2715
        load_eflags(new_eflags, eflags_mask);
2716
    }
2717
    return;
2718

    
2719
 return_to_vm86:
2720
    POPL(ssp, sp, sp_mask, new_esp);
2721
    POPL(ssp, sp, sp_mask, new_ss);
2722
    POPL(ssp, sp, sp_mask, new_es);
2723
    POPL(ssp, sp, sp_mask, new_ds);
2724
    POPL(ssp, sp, sp_mask, new_fs);
2725
    POPL(ssp, sp, sp_mask, new_gs);
2726

    
2727
    /* modify processor state */
2728
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2729
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2730
    load_seg_vm(R_CS, new_cs & 0xffff);
2731
    cpu_x86_set_cpl(env, 3);
2732
    load_seg_vm(R_SS, new_ss & 0xffff);
2733
    load_seg_vm(R_ES, new_es & 0xffff);
2734
    load_seg_vm(R_DS, new_ds & 0xffff);
2735
    load_seg_vm(R_FS, new_fs & 0xffff);
2736
    load_seg_vm(R_GS, new_gs & 0xffff);
2737

    
2738
    env->eip = new_eip & 0xffff;
2739
    ESP = new_esp;
2740
}
2741

    
2742
void helper_iret_protected(int shift, int next_eip)
2743
{
2744
    int tss_selector, type;
2745
    uint32_t e1, e2;
2746

    
2747
    /* specific case for TSS */
2748
    if (env->eflags & NT_MASK) {
2749
#ifdef TARGET_X86_64
2750
        if (env->hflags & HF_LMA_MASK)
2751
            raise_exception_err(EXCP0D_GPF, 0);
2752
#endif
2753
        tss_selector = lduw_kernel(env->tr.base + 0);
2754
        if (tss_selector & 4)
2755
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2756
        if (load_segment(&e1, &e2, tss_selector) != 0)
2757
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2758
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2759
        /* NOTE: we check both segment and busy TSS */
2760
        if (type != 3)
2761
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2762
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2763
    } else {
2764
        helper_ret_protected(shift, 1, 0);
2765
    }
2766
    env->hflags2 &= ~HF2_NMI_MASK;
2767
#ifdef USE_KQEMU
2768
    if (kqemu_is_ok(env)) {
2769
        CC_OP = CC_OP_EFLAGS;
2770
        env->exception_index = -1;
2771
        cpu_loop_exit();
2772
    }
2773
#endif
2774
}
2775

    
2776
void helper_lret_protected(int shift, int addend)
2777
{
2778
    helper_ret_protected(shift, 0, addend);
2779
#ifdef USE_KQEMU
2780
    if (kqemu_is_ok(env)) {
2781
        env->exception_index = -1;
2782
        cpu_loop_exit();
2783
    }
2784
#endif
2785
}
2786

    
2787
void helper_sysenter(void)
2788
{
2789
    if (env->sysenter_cs == 0) {
2790
        raise_exception_err(EXCP0D_GPF, 0);
2791
    }
2792
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2793
    cpu_x86_set_cpl(env, 0);
2794

    
2795
#ifdef TARGET_X86_64
2796
    if (env->hflags & HF_LMA_MASK) {
2797
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2798
                               0, 0xffffffff,
2799
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2800
                               DESC_S_MASK |
2801
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2802
    } else
2803
#endif
2804
    {
2805
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2806
                               0, 0xffffffff,
2807
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2808
                               DESC_S_MASK |
2809
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2810
    }
2811
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2812
                           0, 0xffffffff,
2813
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2814
                           DESC_S_MASK |
2815
                           DESC_W_MASK | DESC_A_MASK);
2816
    ESP = env->sysenter_esp;
2817
    EIP = env->sysenter_eip;
2818
}
2819

    
2820
void helper_sysexit(int dflag)
2821
{
2822
    int cpl;
2823

    
2824
    cpl = env->hflags & HF_CPL_MASK;
2825
    if (env->sysenter_cs == 0 || cpl != 0) {
2826
        raise_exception_err(EXCP0D_GPF, 0);
2827
    }
2828
    cpu_x86_set_cpl(env, 3);
2829
#ifdef TARGET_X86_64
2830
    if (dflag == 2) {
2831
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3,
2832
                               0, 0xffffffff,
2833
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2834
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2835
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2836
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3,
2837
                               0, 0xffffffff,
2838
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2839
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2840
                               DESC_W_MASK | DESC_A_MASK);
2841
    } else
2842
#endif
2843
    {
2844
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2845
                               0, 0xffffffff,
2846
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2847
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2848
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2849
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2850
                               0, 0xffffffff,
2851
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2852
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2853
                               DESC_W_MASK | DESC_A_MASK);
2854
    }
2855
    ESP = ECX;
2856
    EIP = EDX;
2857
#ifdef USE_KQEMU
2858
    if (kqemu_is_ok(env)) {
2859
        env->exception_index = -1;
2860
        cpu_loop_exit();
2861
    }
2862
#endif
2863
}
2864

    
2865
#if defined(CONFIG_USER_ONLY)
2866
target_ulong helper_read_crN(int reg)
2867
{
2868
    return 0;
2869
}
2870

    
2871
void helper_write_crN(int reg, target_ulong t0)
2872
{
2873
}
2874

    
2875
void helper_movl_drN_T0(int reg, target_ulong t0)
2876
{
2877
}
2878
#else
2879
target_ulong helper_read_crN(int reg)
2880
{
2881
    target_ulong val;
2882

    
2883
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
2884
    switch(reg) {
2885
    default:
2886
        val = env->cr[reg];
2887
        break;
2888
    case 8:
2889
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2890
            val = cpu_get_apic_tpr(env);
2891
        } else {
2892
            val = env->v_tpr;
2893
        }
2894
        break;
2895
    }
2896
    return val;
2897
}
2898

    
2899
void helper_write_crN(int reg, target_ulong t0)
2900
{
2901
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
2902
    switch(reg) {
2903
    case 0:
2904
        cpu_x86_update_cr0(env, t0);
2905
        break;
2906
    case 3:
2907
        cpu_x86_update_cr3(env, t0);
2908
        break;
2909
    case 4:
2910
        cpu_x86_update_cr4(env, t0);
2911
        break;
2912
    case 8:
2913
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2914
            cpu_set_apic_tpr(env, t0);
2915
        }
2916
        env->v_tpr = t0 & 0x0f;
2917
        break;
2918
    default:
2919
        env->cr[reg] = t0;
2920
        break;
2921
    }
2922
}
2923

    
2924
void helper_movl_drN_T0(int reg, target_ulong t0)
2925
{
2926
    int i;
2927

    
2928
    if (reg < 4) {
2929
        hw_breakpoint_remove(env, reg);
2930
        env->dr[reg] = t0;
2931
        hw_breakpoint_insert(env, reg);
2932
    } else if (reg == 7) {
2933
        for (i = 0; i < 4; i++)
2934
            hw_breakpoint_remove(env, i);
2935
        env->dr[7] = t0;
2936
        for (i = 0; i < 4; i++)
2937
            hw_breakpoint_insert(env, i);
2938
    } else
2939
        env->dr[reg] = t0;
2940
}
2941
#endif
2942

    
2943
void helper_lmsw(target_ulong t0)
2944
{
2945
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2946
       if already set to one. */
2947
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2948
    helper_write_crN(0, t0);
2949
}
2950

    
2951
void helper_clts(void)
2952
{
2953
    env->cr[0] &= ~CR0_TS_MASK;
2954
    env->hflags &= ~HF_TS_MASK;
2955
}
2956

    
2957
void helper_invlpg(target_ulong addr)
2958
{
2959
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
2960
    tlb_flush_page(env, addr);
2961
}
2962

    
2963
void helper_rdtsc(void)
2964
{
2965
    uint64_t val;
2966

    
2967
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2968
        raise_exception(EXCP0D_GPF);
2969
    }
2970
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
2971

    
2972
    val = cpu_get_tsc(env) + env->tsc_offset;
2973
    EAX = (uint32_t)(val);
2974
    EDX = (uint32_t)(val >> 32);
2975
}
2976

    
2977
void helper_rdpmc(void)
2978
{
2979
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2980
        raise_exception(EXCP0D_GPF);
2981
    }
2982
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
2983
    
2984
    /* currently unimplemented */
2985
    raise_exception_err(EXCP06_ILLOP, 0);
2986
}
2987

    
2988
#if defined(CONFIG_USER_ONLY)
2989
void helper_wrmsr(void)
2990
{
2991
}
2992

    
2993
void helper_rdmsr(void)
2994
{
2995
}
2996
#else
2997
void helper_wrmsr(void)
2998
{
2999
    uint64_t val;
3000

    
3001
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3002

    
3003
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3004

    
3005
    switch((uint32_t)ECX) {
3006
    case MSR_IA32_SYSENTER_CS:
3007
        env->sysenter_cs = val & 0xffff;
3008
        break;
3009
    case MSR_IA32_SYSENTER_ESP:
3010
        env->sysenter_esp = val;
3011
        break;
3012
    case MSR_IA32_SYSENTER_EIP:
3013
        env->sysenter_eip = val;
3014
        break;
3015
    case MSR_IA32_APICBASE:
3016
        cpu_set_apic_base(env, val);
3017
        break;
3018
    case MSR_EFER:
3019
        {
3020
            uint64_t update_mask;
3021
            update_mask = 0;
3022
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3023
                update_mask |= MSR_EFER_SCE;
3024
            if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3025
                update_mask |= MSR_EFER_LME;
3026
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3027
                update_mask |= MSR_EFER_FFXSR;
3028
            if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3029
                update_mask |= MSR_EFER_NXE;
3030
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3031
                update_mask |= MSR_EFER_SVME;
3032
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3033
                update_mask |= MSR_EFER_FFXSR;
3034
            cpu_load_efer(env, (env->efer & ~update_mask) |
3035
                          (val & update_mask));
3036
        }
3037
        break;
3038
    case MSR_STAR:
3039
        env->star = val;
3040
        break;
3041
    case MSR_PAT:
3042
        env->pat = val;
3043
        break;
3044
    case MSR_VM_HSAVE_PA:
3045
        env->vm_hsave = val;
3046
        break;
3047
#ifdef TARGET_X86_64
3048
    case MSR_LSTAR:
3049
        env->lstar = val;
3050
        break;
3051
    case MSR_CSTAR:
3052
        env->cstar = val;
3053
        break;
3054
    case MSR_FMASK:
3055
        env->fmask = val;
3056
        break;
3057
    case MSR_FSBASE:
3058
        env->segs[R_FS].base = val;
3059
        break;
3060
    case MSR_GSBASE:
3061
        env->segs[R_GS].base = val;
3062
        break;
3063
    case MSR_KERNELGSBASE:
3064
        env->kernelgsbase = val;
3065
        break;
3066
#endif
3067
    case MSR_MTRRphysBase(0):
3068
    case MSR_MTRRphysBase(1):
3069
    case MSR_MTRRphysBase(2):
3070
    case MSR_MTRRphysBase(3):
3071
    case MSR_MTRRphysBase(4):
3072
    case MSR_MTRRphysBase(5):
3073
    case MSR_MTRRphysBase(6):
3074
    case MSR_MTRRphysBase(7):
3075
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
3076
        break;
3077
    case MSR_MTRRphysMask(0):
3078
    case MSR_MTRRphysMask(1):
3079
    case MSR_MTRRphysMask(2):
3080
    case MSR_MTRRphysMask(3):
3081
    case MSR_MTRRphysMask(4):
3082
    case MSR_MTRRphysMask(5):
3083
    case MSR_MTRRphysMask(6):
3084
    case MSR_MTRRphysMask(7):
3085
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
3086
        break;
3087
    case MSR_MTRRfix64K_00000:
3088
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
3089
        break;
3090
    case MSR_MTRRfix16K_80000:
3091
    case MSR_MTRRfix16K_A0000:
3092
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
3093
        break;
3094
    case MSR_MTRRfix4K_C0000:
3095
    case MSR_MTRRfix4K_C8000:
3096
    case MSR_MTRRfix4K_D0000:
3097
    case MSR_MTRRfix4K_D8000:
3098
    case MSR_MTRRfix4K_E0000:
3099
    case MSR_MTRRfix4K_E8000:
3100
    case MSR_MTRRfix4K_F0000:
3101
    case MSR_MTRRfix4K_F8000:
3102
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
3103
        break;
3104
    case MSR_MTRRdefType:
3105
        env->mtrr_deftype = val;
3106
        break;
3107
    default:
3108
        /* XXX: exception ? */
3109
        break;
3110
    }
3111
}
3112

    
3113
void helper_rdmsr(void)
3114
{
3115
    uint64_t val;
3116

    
3117
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3118

    
3119
    switch((uint32_t)ECX) {
3120
    case MSR_IA32_SYSENTER_CS:
3121
        val = env->sysenter_cs;
3122
        break;
3123
    case MSR_IA32_SYSENTER_ESP:
3124
        val = env->sysenter_esp;
3125
        break;
3126
    case MSR_IA32_SYSENTER_EIP:
3127
        val = env->sysenter_eip;
3128
        break;
3129
    case MSR_IA32_APICBASE:
3130
        val = cpu_get_apic_base(env);
3131
        break;
3132
    case MSR_EFER:
3133
        val = env->efer;
3134
        break;
3135
    case MSR_STAR:
3136
        val = env->star;
3137
        break;
3138
    case MSR_PAT:
3139
        val = env->pat;
3140
        break;
3141
    case MSR_VM_HSAVE_PA:
3142
        val = env->vm_hsave;
3143
        break;
3144
    case MSR_IA32_PERF_STATUS:
3145
        /* tsc_increment_by_tick */
3146
        val = 1000ULL;
3147
        /* CPU multiplier */
3148
        val |= (((uint64_t)4ULL) << 40);
3149
        break;
3150
#ifdef TARGET_X86_64
3151
    case MSR_LSTAR:
3152
        val = env->lstar;
3153
        break;
3154
    case MSR_CSTAR:
3155
        val = env->cstar;
3156
        break;
3157
    case MSR_FMASK:
3158
        val = env->fmask;
3159
        break;
3160
    case MSR_FSBASE:
3161
        val = env->segs[R_FS].base;
3162
        break;
3163
    case MSR_GSBASE:
3164
        val = env->segs[R_GS].base;
3165
        break;
3166
    case MSR_KERNELGSBASE:
3167
        val = env->kernelgsbase;
3168
        break;
3169
#endif
3170
#ifdef USE_KQEMU
3171
    case MSR_QPI_COMMBASE:
3172
        if (env->kqemu_enabled) {
3173
            val = kqemu_comm_base;
3174
        } else {
3175
            val = 0;
3176
        }
3177
        break;
3178
#endif
3179
    case MSR_MTRRphysBase(0):
3180
    case MSR_MTRRphysBase(1):
3181
    case MSR_MTRRphysBase(2):
3182
    case MSR_MTRRphysBase(3):
3183
    case MSR_MTRRphysBase(4):
3184
    case MSR_MTRRphysBase(5):
3185
    case MSR_MTRRphysBase(6):
3186
    case MSR_MTRRphysBase(7):
3187
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;
3188
        break;
3189
    case MSR_MTRRphysMask(0):
3190
    case MSR_MTRRphysMask(1):
3191
    case MSR_MTRRphysMask(2):
3192
    case MSR_MTRRphysMask(3):
3193
    case MSR_MTRRphysMask(4):
3194
    case MSR_MTRRphysMask(5):
3195
    case MSR_MTRRphysMask(6):
3196
    case MSR_MTRRphysMask(7):
3197
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;
3198
        break;
3199
    case MSR_MTRRfix64K_00000:
3200
        val = env->mtrr_fixed[0];
3201
        break;
3202
    case MSR_MTRRfix16K_80000:
3203
    case MSR_MTRRfix16K_A0000:
3204
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];
3205
        break;
3206
    case MSR_MTRRfix4K_C0000:
3207
    case MSR_MTRRfix4K_C8000:
3208
    case MSR_MTRRfix4K_D0000:
3209
    case MSR_MTRRfix4K_D8000:
3210
    case MSR_MTRRfix4K_E0000:
3211
    case MSR_MTRRfix4K_E8000:
3212
    case MSR_MTRRfix4K_F0000:
3213
    case MSR_MTRRfix4K_F8000:
3214
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];
3215
        break;
3216
    case MSR_MTRRdefType:
3217
        val = env->mtrr_deftype;
3218
        break;
3219
    case MSR_MTRRcap:
3220
        if (env->cpuid_features & CPUID_MTRR)
3221
            val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED;
3222
        else
3223
            /* XXX: exception ? */
3224
            val = 0;
3225
        break;
3226
    default:
3227
        /* XXX: exception ? */
3228
        val = 0;
3229
        break;
3230
    }
3231
    EAX = (uint32_t)(val);
3232
    EDX = (uint32_t)(val >> 32);
3233
}
3234
#endif
3235

    
3236
target_ulong helper_lsl(target_ulong selector1)
3237
{
3238
    unsigned int limit;
3239
    uint32_t e1, e2, eflags, selector;
3240
    int rpl, dpl, cpl, type;
3241

    
3242
    selector = selector1 & 0xffff;
3243
    eflags = helper_cc_compute_all(CC_OP);
3244
    if ((selector & 0xfffc) == 0)
3245
        goto fail;
3246
    if (load_segment(&e1, &e2, selector) != 0)
3247
        goto fail;
3248
    rpl = selector & 3;
3249
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3250
    cpl = env->hflags & HF_CPL_MASK;
3251
    if (e2 & DESC_S_MASK) {
3252
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3253
            /* conforming */
3254
        } else {
3255
            if (dpl < cpl || dpl < rpl)
3256
                goto fail;
3257
        }
3258
    } else {
3259
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3260
        switch(type) {
3261
        case 1:
3262
        case 2:
3263
        case 3:
3264
        case 9:
3265
        case 11:
3266
            break;
3267
        default:
3268
            goto fail;
3269
        }
3270
        if (dpl < cpl || dpl < rpl) {
3271
        fail:
3272
            CC_SRC = eflags & ~CC_Z;
3273
            return 0;
3274
        }
3275
    }
3276
    limit = get_seg_limit(e1, e2);
3277
    CC_SRC = eflags | CC_Z;
3278
    return limit;
3279
}
3280

    
3281
target_ulong helper_lar(target_ulong selector1)
3282
{
3283
    uint32_t e1, e2, eflags, selector;
3284
    int rpl, dpl, cpl, type;
3285

    
3286
    selector = selector1 & 0xffff;
3287
    eflags = helper_cc_compute_all(CC_OP);
3288
    if ((selector & 0xfffc) == 0)
3289
        goto fail;
3290
    if (load_segment(&e1, &e2, selector) != 0)
3291
        goto fail;
3292
    rpl = selector & 3;
3293
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3294
    cpl = env->hflags & HF_CPL_MASK;
3295
    if (e2 & DESC_S_MASK) {
3296
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3297
            /* conforming */
3298
        } else {
3299
            if (dpl < cpl || dpl < rpl)
3300
                goto fail;
3301
        }
3302
    } else {
3303
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3304
        switch(type) {
3305
        case 1:
3306
        case 2:
3307
        case 3:
3308
        case 4:
3309
        case 5:
3310
        case 9:
3311
        case 11:
3312
        case 12:
3313
            break;
3314
        default:
3315
            goto fail;
3316
        }
3317
        if (dpl < cpl || dpl < rpl) {
3318
        fail:
3319
            CC_SRC = eflags & ~CC_Z;
3320
            return 0;
3321
        }
3322
    }
3323
    CC_SRC = eflags | CC_Z;
3324
    return e2 & 0x00f0ff00;
3325
}
3326

    
3327
void helper_verr(target_ulong selector1)
3328
{
3329
    uint32_t e1, e2, eflags, selector;
3330
    int rpl, dpl, cpl;
3331

    
3332
    selector = selector1 & 0xffff;
3333
    eflags = helper_cc_compute_all(CC_OP);
3334
    if ((selector & 0xfffc) == 0)
3335
        goto fail;
3336
    if (load_segment(&e1, &e2, selector) != 0)
3337
        goto fail;
3338
    if (!(e2 & DESC_S_MASK))
3339
        goto fail;
3340
    rpl = selector & 3;
3341
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3342
    cpl = env->hflags & HF_CPL_MASK;
3343
    if (e2 & DESC_CS_MASK) {
3344
        if (!(e2 & DESC_R_MASK))
3345
            goto fail;
3346
        if (!(e2 & DESC_C_MASK)) {
3347
            if (dpl < cpl || dpl < rpl)
3348
                goto fail;
3349
        }
3350
    } else {
3351
        if (dpl < cpl || dpl < rpl) {
3352
        fail:
3353
            CC_SRC = eflags & ~CC_Z;
3354
            return;
3355
        }
3356
    }
3357
    CC_SRC = eflags | CC_Z;
3358
}
3359

    
3360
void helper_verw(target_ulong selector1)
3361
{
3362
    uint32_t e1, e2, eflags, selector;
3363
    int rpl, dpl, cpl;
3364

    
3365
    selector = selector1 & 0xffff;
3366
    eflags = helper_cc_compute_all(CC_OP);
3367
    if ((selector & 0xfffc) == 0)
3368
        goto fail;
3369
    if (load_segment(&e1, &e2, selector) != 0)
3370
        goto fail;
3371
    if (!(e2 & DESC_S_MASK))
3372
        goto fail;
3373
    rpl = selector & 3;
3374
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3375
    cpl = env->hflags & HF_CPL_MASK;
3376
    if (e2 & DESC_CS_MASK) {
3377
        goto fail;
3378
    } else {
3379
        if (dpl < cpl || dpl < rpl)
3380
            goto fail;
3381
        if (!(e2 & DESC_W_MASK)) {
3382
        fail:
3383
            CC_SRC = eflags & ~CC_Z;
3384
            return;
3385
        }
3386
    }
3387
    CC_SRC = eflags | CC_Z;
3388
}
3389

    
3390
/* x87 FPU helpers */
3391

    
3392
static void fpu_set_exception(int mask)
3393
{
3394
    env->fpus |= mask;
3395
    if (env->fpus & (~env->fpuc & FPUC_EM))
3396
        env->fpus |= FPUS_SE | FPUS_B;
3397
}
3398

    
3399
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3400
{
3401
    if (b == 0.0)
3402
        fpu_set_exception(FPUS_ZE);
3403
    return a / b;
3404
}
3405

    
3406
static void fpu_raise_exception(void)
3407
{
3408
    if (env->cr[0] & CR0_NE_MASK) {
3409
        raise_exception(EXCP10_COPR);
3410
    }
3411
#if !defined(CONFIG_USER_ONLY)
3412
    else {
3413
        cpu_set_ferr(env);
3414
    }
3415
#endif
3416
}
3417

    
3418
void helper_flds_FT0(uint32_t val)
3419
{
3420
    union {
3421
        float32 f;
3422
        uint32_t i;
3423
    } u;
3424
    u.i = val;
3425
    FT0 = float32_to_floatx(u.f, &env->fp_status);
3426
}
3427

    
3428
void helper_fldl_FT0(uint64_t val)
3429
{
3430
    union {
3431
        float64 f;
3432
        uint64_t i;
3433
    } u;
3434
    u.i = val;
3435
    FT0 = float64_to_floatx(u.f, &env->fp_status);
3436
}
3437

    
3438
void helper_fildl_FT0(int32_t val)
3439
{
3440
    FT0 = int32_to_floatx(val, &env->fp_status);
3441
}
3442

    
3443
void helper_flds_ST0(uint32_t val)
3444
{
3445
    int new_fpstt;
3446
    union {
3447
        float32 f;
3448
        uint32_t i;
3449
    } u;
3450
    new_fpstt = (env->fpstt - 1) & 7;
3451
    u.i = val;
3452
    env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3453
    env->fpstt = new_fpstt;
3454
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3455
}
3456

    
3457
void helper_fldl_ST0(uint64_t val)
3458
{
3459
    int new_fpstt;
3460
    union {
3461
        float64 f;
3462
        uint64_t i;
3463
    } u;
3464
    new_fpstt = (env->fpstt - 1) & 7;
3465
    u.i = val;
3466
    env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3467
    env->fpstt = new_fpstt;
3468
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3469
}
3470

    
3471
void helper_fildl_ST0(int32_t val)
3472
{
3473
    int new_fpstt;
3474
    new_fpstt = (env->fpstt - 1) & 7;
3475
    env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3476
    env->fpstt = new_fpstt;
3477
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3478
}
3479

    
3480
void helper_fildll_ST0(int64_t val)
3481
{
3482
    int new_fpstt;
3483
    new_fpstt = (env->fpstt - 1) & 7;
3484
    env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3485
    env->fpstt = new_fpstt;
3486
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3487
}
3488

    
3489
uint32_t helper_fsts_ST0(void)
3490
{
3491
    union {
3492
        float32 f;
3493
        uint32_t i;
3494
    } u;
3495
    u.f = floatx_to_float32(ST0, &env->fp_status);
3496
    return u.i;
3497
}
3498

    
3499
uint64_t helper_fstl_ST0(void)
3500
{
3501
    union {
3502
        float64 f;
3503
        uint64_t i;
3504
    } u;
3505
    u.f = floatx_to_float64(ST0, &env->fp_status);
3506
    return u.i;
3507
}
3508

    
3509
int32_t helper_fist_ST0(void)
3510
{
3511
    int32_t val;
3512
    val = floatx_to_int32(ST0, &env->fp_status);
3513
    if (val != (int16_t)val)
3514
        val = -32768;
3515
    return val;
3516
}
3517

    
3518
int32_t helper_fistl_ST0(void)
3519
{
3520
    int32_t val;
3521
    val = floatx_to_int32(ST0, &env->fp_status);
3522
    return val;
3523
}
3524

    
3525
int64_t helper_fistll_ST0(void)
3526
{
3527
    int64_t val;
3528
    val = floatx_to_int64(ST0, &env->fp_status);
3529
    return val;
3530
}
3531

    
3532
int32_t helper_fistt_ST0(void)
3533
{
3534
    int32_t val;
3535
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3536
    if (val != (int16_t)val)
3537
        val = -32768;
3538
    return val;
3539
}
3540

    
3541
int32_t helper_fisttl_ST0(void)
3542
{
3543
    int32_t val;
3544
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3545
    return val;
3546
}
3547

    
3548
int64_t helper_fisttll_ST0(void)
3549
{
3550
    int64_t val;
3551
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3552
    return val;
3553
}
3554

    
3555
void helper_fldt_ST0(target_ulong ptr)
3556
{
3557
    int new_fpstt;
3558
    new_fpstt = (env->fpstt - 1) & 7;
3559
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3560
    env->fpstt = new_fpstt;
3561
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3562
}
3563

    
3564
void helper_fstt_ST0(target_ulong ptr)
3565
{
3566
    helper_fstt(ST0, ptr);
3567
}
3568

    
3569
void helper_fpush(void)
3570
{
3571
    fpush();
3572
}
3573

    
3574
void helper_fpop(void)
3575
{
3576
    fpop();
3577
}
3578

    
3579
void helper_fdecstp(void)
3580
{
3581
    env->fpstt = (env->fpstt - 1) & 7;
3582
    env->fpus &= (~0x4700);
3583
}
3584

    
3585
void helper_fincstp(void)
3586
{
3587
    env->fpstt = (env->fpstt + 1) & 7;
3588
    env->fpus &= (~0x4700);
3589
}
3590

    
3591
/* FPU move */
3592

    
3593
void helper_ffree_STN(int st_index)
3594
{
3595
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3596
}
3597

    
3598
void helper_fmov_ST0_FT0(void)
3599
{
3600
    ST0 = FT0;
3601
}
3602

    
3603
void helper_fmov_FT0_STN(int st_index)
3604
{
3605
    FT0 = ST(st_index);
3606
}
3607

    
3608
void helper_fmov_ST0_STN(int st_index)
3609
{
3610
    ST0 = ST(st_index);
3611
}
3612

    
3613
void helper_fmov_STN_ST0(int st_index)
3614
{
3615
    ST(st_index) = ST0;
3616
}
3617

    
3618
void helper_fxchg_ST0_STN(int st_index)
3619
{
3620
    CPU86_LDouble tmp;
3621
    tmp = ST(st_index);
3622
    ST(st_index) = ST0;
3623
    ST0 = tmp;
3624
}
3625

    
3626
/* FPU operations */
3627

    
3628
static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
3629

    
3630
void helper_fcom_ST0_FT0(void)
3631
{
3632
    int ret;
3633

    
3634
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3635
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3636
}
3637

    
3638
void helper_fucom_ST0_FT0(void)
3639
{
3640
    int ret;
3641

    
3642
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3643
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3644
}
3645

    
3646
static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
3647

    
3648
void helper_fcomi_ST0_FT0(void)
3649
{
3650
    int eflags;
3651
    int ret;
3652

    
3653
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3654
    eflags = helper_cc_compute_all(CC_OP);
3655
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3656
    CC_SRC = eflags;
3657
}
3658

    
3659
void helper_fucomi_ST0_FT0(void)
3660
{
3661
    int eflags;
3662
    int ret;
3663

    
3664
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3665
    eflags = helper_cc_compute_all(CC_OP);
3666
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3667
    CC_SRC = eflags;
3668
}
3669

    
3670
void helper_fadd_ST0_FT0(void)
3671
{
3672
    ST0 += FT0;
3673
}
3674

    
3675
void helper_fmul_ST0_FT0(void)
3676
{
3677
    ST0 *= FT0;
3678
}
3679

    
3680
void helper_fsub_ST0_FT0(void)
3681
{
3682
    ST0 -= FT0;
3683
}
3684

    
3685
void helper_fsubr_ST0_FT0(void)
3686
{
3687
    ST0 = FT0 - ST0;
3688
}
3689

    
3690
void helper_fdiv_ST0_FT0(void)
3691
{
3692
    ST0 = helper_fdiv(ST0, FT0);
3693
}
3694

    
3695
void helper_fdivr_ST0_FT0(void)
3696
{
3697
    ST0 = helper_fdiv(FT0, ST0);
3698
}
3699

    
3700
/* fp operations between STN and ST0 */
3701

    
3702
void helper_fadd_STN_ST0(int st_index)
3703
{
3704
    ST(st_index) += ST0;
3705
}
3706

    
3707
void helper_fmul_STN_ST0(int st_index)
3708
{
3709
    ST(st_index) *= ST0;
3710
}
3711

    
3712
void helper_fsub_STN_ST0(int st_index)
3713
{
3714
    ST(st_index) -= ST0;
3715
}
3716

    
3717
void helper_fsubr_STN_ST0(int st_index)
3718
{
3719
    CPU86_LDouble *p;
3720
    p = &ST(st_index);
3721
    *p = ST0 - *p;
3722
}
3723

    
3724
void helper_fdiv_STN_ST0(int st_index)
3725
{
3726
    CPU86_LDouble *p;
3727
    p = &ST(st_index);
3728
    *p = helper_fdiv(*p, ST0);
3729
}
3730

    
3731
void helper_fdivr_STN_ST0(int st_index)
3732
{
3733
    CPU86_LDouble *p;
3734
    p = &ST(st_index);
3735
    *p = helper_fdiv(ST0, *p);
3736
}
3737

    
3738
/* misc FPU operations */
3739
void helper_fchs_ST0(void)
3740
{
3741
    ST0 = floatx_chs(ST0);
3742
}
3743

    
3744
void helper_fabs_ST0(void)
3745
{
3746
    ST0 = floatx_abs(ST0);
3747
}
3748

    
3749
void helper_fld1_ST0(void)
3750
{
3751
    ST0 = f15rk[1];
3752
}
3753

    
3754
void helper_fldl2t_ST0(void)
3755
{
3756
    ST0 = f15rk[6];
3757
}
3758

    
3759
void helper_fldl2e_ST0(void)
3760
{
3761
    ST0 = f15rk[5];
3762
}
3763

    
3764
void helper_fldpi_ST0(void)
3765
{
3766
    ST0 = f15rk[2];
3767
}
3768

    
3769
void helper_fldlg2_ST0(void)
3770
{
3771
    ST0 = f15rk[3];
3772
}
3773

    
3774
void helper_fldln2_ST0(void)
3775
{
3776
    ST0 = f15rk[4];
3777
}
3778

    
3779
void helper_fldz_ST0(void)
3780
{
3781
    ST0 = f15rk[0];
3782
}
3783

    
3784
void helper_fldz_FT0(void)
3785
{
3786
    FT0 = f15rk[0];
3787
}
3788

    
3789
uint32_t helper_fnstsw(void)
3790
{
3791
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3792
}
3793

    
3794
uint32_t helper_fnstcw(void)
3795
{
3796
    return env->fpuc;
3797
}
3798

    
3799
static void update_fp_status(void)
3800
{
3801
    int rnd_type;
3802

    
3803
    /* set rounding mode */
3804
    switch(env->fpuc & RC_MASK) {
3805
    default:
3806
    case RC_NEAR:
3807
        rnd_type = float_round_nearest_even;
3808
        break;
3809
    case RC_DOWN:
3810
        rnd_type = float_round_down;
3811
        break;
3812
    case RC_UP:
3813
        rnd_type = float_round_up;
3814
        break;
3815
    case RC_CHOP:
3816
        rnd_type = float_round_to_zero;
3817
        break;
3818
    }
3819
    set_float_rounding_mode(rnd_type, &env->fp_status);
3820
#ifdef FLOATX80
3821
    switch((env->fpuc >> 8) & 3) {
3822
    case 0:
3823
        rnd_type = 32;
3824
        break;
3825
    case 2:
3826
        rnd_type = 64;
3827
        break;
3828
    case 3:
3829
    default:
3830
        rnd_type = 80;
3831
        break;
3832
    }
3833
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3834
#endif
3835
}
3836

    
3837
void helper_fldcw(uint32_t val)
3838
{
3839
    env->fpuc = val;
3840
    update_fp_status();
3841
}
3842

    
3843
void helper_fclex(void)
3844
{
3845
    env->fpus &= 0x7f00;
3846
}
3847

    
3848
void helper_fwait(void)
3849
{
3850
    if (env->fpus & FPUS_SE)
3851
        fpu_raise_exception();
3852
}
3853

    
3854
void helper_fninit(void)
3855
{
3856
    env->fpus = 0;
3857
    env->fpstt = 0;
3858
    env->fpuc = 0x37f;
3859
    env->fptags[0] = 1;
3860
    env->fptags[1] = 1;
3861
    env->fptags[2] = 1;
3862
    env->fptags[3] = 1;
3863
    env->fptags[4] = 1;
3864
    env->fptags[5] = 1;
3865
    env->fptags[6] = 1;
3866
    env->fptags[7] = 1;
3867
}
3868

    
3869
/* BCD ops */
3870

    
3871
void helper_fbld_ST0(target_ulong ptr)
3872
{
3873
    CPU86_LDouble tmp;
3874
    uint64_t val;
3875
    unsigned int v;
3876
    int i;
3877

    
3878
    val = 0;
3879
    for(i = 8; i >= 0; i--) {
3880
        v = ldub(ptr + i);
3881
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3882
    }
3883
    tmp = val;
3884
    if (ldub(ptr + 9) & 0x80)
3885
        tmp = -tmp;
3886
    fpush();
3887
    ST0 = tmp;
3888
}
3889

    
3890
void helper_fbst_ST0(target_ulong ptr)
3891
{
3892
    int v;
3893
    target_ulong mem_ref, mem_end;
3894
    int64_t val;
3895

    
3896
    val = floatx_to_int64(ST0, &env->fp_status);
3897
    mem_ref = ptr;
3898
    mem_end = mem_ref + 9;
3899
    if (val < 0) {
3900
        stb(mem_end, 0x80);
3901
        val = -val;
3902
    } else {
3903
        stb(mem_end, 0x00);
3904
    }
3905
    while (mem_ref < mem_end) {
3906
        if (val == 0)
3907
            break;
3908
        v = val % 100;
3909
        val = val / 100;
3910
        v = ((v / 10) << 4) | (v % 10);
3911
        stb(mem_ref++, v);
3912
    }
3913
    while (mem_ref < mem_end) {
3914
        stb(mem_ref++, 0);
3915
    }
3916
}
3917

    
3918
void helper_f2xm1(void)
3919
{
3920
    ST0 = pow(2.0,ST0) - 1.0;
3921
}
3922

    
3923
void helper_fyl2x(void)
3924
{
3925
    CPU86_LDouble fptemp;
3926

    
3927
    fptemp = ST0;
3928
    if (fptemp>0.0){
3929
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
3930
        ST1 *= fptemp;
3931
        fpop();
3932
    } else {
3933
        env->fpus &= (~0x4700);
3934
        env->fpus |= 0x400;
3935
    }
3936
}
3937

    
3938
void helper_fptan(void)
3939
{
3940
    CPU86_LDouble fptemp;
3941

    
3942
    fptemp = ST0;
3943
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3944
        env->fpus |= 0x400;
3945
    } else {
3946
        ST0 = tan(fptemp);
3947
        fpush();
3948
        ST0 = 1.0;
3949
        env->fpus &= (~0x400);  /* C2 <-- 0 */
3950
        /* the above code is for  |arg| < 2**52 only */
3951
    }
3952
}
3953

    
3954
void helper_fpatan(void)
3955
{
3956
    CPU86_LDouble fptemp, fpsrcop;
3957

    
3958
    fpsrcop = ST1;
3959
    fptemp = ST0;
3960
    ST1 = atan2(fpsrcop,fptemp);
3961
    fpop();
3962
}
3963

    
3964
void helper_fxtract(void)
3965
{
3966
    CPU86_LDoubleU temp;
3967
    unsigned int expdif;
3968

    
3969
    temp.d = ST0;
3970
    expdif = EXPD(temp) - EXPBIAS;
3971
    /*DP exponent bias*/
3972
    ST0 = expdif;
3973
    fpush();
3974
    BIASEXPONENT(temp);
3975
    ST0 = temp.d;
3976
}
3977

    
3978
void helper_fprem1(void)
3979
{
3980
    CPU86_LDouble dblq, fpsrcop, fptemp;
3981
    CPU86_LDoubleU fpsrcop1, fptemp1;
3982
    int expdif;
3983
    signed long long int q;
3984

    
3985
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3986
        ST0 = 0.0 / 0.0; /* NaN */
3987
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3988
        return;
3989
    }
3990

    
3991
    fpsrcop = ST0;
3992
    fptemp = ST1;
3993
    fpsrcop1.d = fpsrcop;
3994
    fptemp1.d = fptemp;
3995
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3996

    
3997
    if (expdif < 0) {
3998
        /* optimisation? taken from the AMD docs */
3999
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4000
        /* ST0 is unchanged */
4001
        return;
4002
    }
4003

    
4004
    if (expdif < 53) {
4005
        dblq = fpsrcop / fptemp;
4006
        /* round dblq towards nearest integer */
4007
        dblq = rint(dblq);
4008
        ST0 = fpsrcop - fptemp * dblq;
4009

    
4010
        /* convert dblq to q by truncating towards zero */
4011
        if (dblq < 0.0)
4012
           q = (signed long long int)(-dblq);
4013
        else
4014
           q = (signed long long int)dblq;
4015

    
4016
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4017
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4018
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4019
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4020
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4021
    } else {
4022
        env->fpus |= 0x400;  /* C2 <-- 1 */
4023
        fptemp = pow(2.0, expdif - 50);
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_fprem(void)
4033
{
4034
    CPU86_LDouble dblq, fpsrcop, fptemp;
4035
    CPU86_LDoubleU fpsrcop1, fptemp1;
4036
    int expdif;
4037
    signed long long int q;
4038

    
4039
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
4040
       ST0 = 0.0 / 0.0; /* NaN */
4041
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4042
       return;
4043
    }
4044

    
4045
    fpsrcop = (CPU86_LDouble)ST0;
4046
    fptemp = (CPU86_LDouble)ST1;
4047
    fpsrcop1.d = fpsrcop;
4048
    fptemp1.d = fptemp;
4049
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4050

    
4051
    if (expdif < 0) {
4052
        /* optimisation? taken from the AMD docs */
4053
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4054
        /* ST0 is unchanged */
4055
        return;
4056
    }
4057

    
4058
    if ( expdif < 53 ) {
4059
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4060
        /* round dblq towards zero */
4061
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4062
        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
4063

    
4064
        /* convert dblq to q by truncating towards zero */
4065
        if (dblq < 0.0)
4066
           q = (signed long long int)(-dblq);
4067
        else
4068
           q = (signed long long int)dblq;
4069

    
4070
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4071
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4072
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4073
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4074
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4075
    } else {
4076
        int N = 32 + (expdif % 32); /* as per AMD docs */
4077
        env->fpus |= 0x400;  /* C2 <-- 1 */
4078
        fptemp = pow(2.0, (double)(expdif - N));
4079
        fpsrcop = (ST0 / ST1) / fptemp;
4080
        /* fpsrcop = integer obtained by chopping */
4081
        fpsrcop = (fpsrcop < 0.0) ?
4082
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4083
        ST0 -= (ST1 * fpsrcop * fptemp);
4084
    }
4085
}
4086

    
4087
void helper_fyl2xp1(void)
4088
{
4089
    CPU86_LDouble fptemp;
4090

    
4091
    fptemp = ST0;
4092
    if ((fptemp+1.0)>0.0) {
4093
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4094
        ST1 *= fptemp;
4095
        fpop();
4096
    } else {
4097
        env->fpus &= (~0x4700);
4098
        env->fpus |= 0x400;
4099
    }
4100
}
4101

    
4102
void helper_fsqrt(void)
4103
{
4104
    CPU86_LDouble fptemp;
4105

    
4106
    fptemp = ST0;
4107
    if (fptemp<0.0) {
4108
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4109
        env->fpus |= 0x400;
4110
    }
4111
    ST0 = sqrt(fptemp);
4112
}
4113

    
4114
void helper_fsincos(void)
4115
{
4116
    CPU86_LDouble fptemp;
4117

    
4118
    fptemp = ST0;
4119
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4120
        env->fpus |= 0x400;
4121
    } else {
4122
        ST0 = sin(fptemp);
4123
        fpush();
4124
        ST0 = cos(fptemp);
4125
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4126
        /* the above code is for  |arg| < 2**63 only */
4127
    }
4128
}
4129

    
4130
void helper_frndint(void)
4131
{
4132
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4133
}
4134

    
4135
void helper_fscale(void)
4136
{
4137
    ST0 = ldexp (ST0, (int)(ST1));
4138
}
4139

    
4140
void helper_fsin(void)
4141
{
4142
    CPU86_LDouble fptemp;
4143

    
4144
    fptemp = ST0;
4145
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4146
        env->fpus |= 0x400;
4147
    } else {
4148
        ST0 = sin(fptemp);
4149
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4150
        /* the above code is for  |arg| < 2**53 only */
4151
    }
4152
}
4153

    
4154
void helper_fcos(void)
4155
{
4156
    CPU86_LDouble fptemp;
4157

    
4158
    fptemp = ST0;
4159
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4160
        env->fpus |= 0x400;
4161
    } else {
4162
        ST0 = cos(fptemp);
4163
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4164
        /* the above code is for  |arg5 < 2**63 only */
4165
    }
4166
}
4167

    
4168
void helper_fxam_ST0(void)
4169
{
4170
    CPU86_LDoubleU temp;
4171
    int expdif;
4172

    
4173
    temp.d = ST0;
4174

    
4175
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4176
    if (SIGND(temp))
4177
        env->fpus |= 0x200; /* C1 <-- 1 */
4178

    
4179
    /* XXX: test fptags too */
4180
    expdif = EXPD(temp);
4181
    if (expdif == MAXEXPD) {
4182
#ifdef USE_X86LDOUBLE
4183
        if (MANTD(temp) == 0x8000000000000000ULL)
4184
#else
4185
        if (MANTD(temp) == 0)
4186
#endif
4187
            env->fpus |=  0x500 /*Infinity*/;
4188
        else
4189
            env->fpus |=  0x100 /*NaN*/;
4190
    } else if (expdif == 0) {
4191
        if (MANTD(temp) == 0)
4192
            env->fpus |=  0x4000 /*Zero*/;
4193
        else
4194
            env->fpus |= 0x4400 /*Denormal*/;
4195
    } else {
4196
        env->fpus |= 0x400;
4197
    }
4198
}
4199

    
4200
void helper_fstenv(target_ulong ptr, int data32)
4201
{
4202
    int fpus, fptag, exp, i;
4203
    uint64_t mant;
4204
    CPU86_LDoubleU tmp;
4205

    
4206
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4207
    fptag = 0;
4208
    for (i=7; i>=0; i--) {
4209
        fptag <<= 2;
4210
        if (env->fptags[i]) {
4211
            fptag |= 3;
4212
        } else {
4213
            tmp.d = env->fpregs[i].d;
4214
            exp = EXPD(tmp);
4215
            mant = MANTD(tmp);
4216
            if (exp == 0 && mant == 0) {
4217
                /* zero */
4218
                fptag |= 1;
4219
            } else if (exp == 0 || exp == MAXEXPD
4220
#ifdef USE_X86LDOUBLE
4221
                       || (mant & (1LL << 63)) == 0
4222
#endif
4223
                       ) {
4224
                /* NaNs, infinity, denormal */
4225
                fptag |= 2;
4226
            }
4227
        }
4228
    }
4229
    if (data32) {
4230
        /* 32 bit */
4231
        stl(ptr, env->fpuc);
4232
        stl(ptr + 4, fpus);
4233
        stl(ptr + 8, fptag);
4234
        stl(ptr + 12, 0); /* fpip */
4235
        stl(ptr + 16, 0); /* fpcs */
4236
        stl(ptr + 20, 0); /* fpoo */
4237
        stl(ptr + 24, 0); /* fpos */
4238
    } else {
4239
        /* 16 bit */
4240
        stw(ptr, env->fpuc);
4241
        stw(ptr + 2, fpus);
4242
        stw(ptr + 4, fptag);
4243
        stw(ptr + 6, 0);
4244
        stw(ptr + 8, 0);
4245
        stw(ptr + 10, 0);
4246
        stw(ptr + 12, 0);
4247
    }
4248
}
4249

    
4250
void helper_fldenv(target_ulong ptr, int data32)
4251
{
4252
    int i, fpus, fptag;
4253

    
4254
    if (data32) {
4255
        env->fpuc = lduw(ptr);
4256
        fpus = lduw(ptr + 4);
4257
        fptag = lduw(ptr + 8);
4258
    }
4259
    else {
4260
        env->fpuc = lduw(ptr);
4261
        fpus = lduw(ptr + 2);
4262
        fptag = lduw(ptr + 4);
4263
    }
4264
    env->fpstt = (fpus >> 11) & 7;
4265
    env->fpus = fpus & ~0x3800;
4266
    for(i = 0;i < 8; i++) {
4267
        env->fptags[i] = ((fptag & 3) == 3);
4268
        fptag >>= 2;
4269
    }
4270
}
4271

    
4272
void helper_fsave(target_ulong ptr, int data32)
4273
{
4274
    CPU86_LDouble tmp;
4275
    int i;
4276

    
4277
    helper_fstenv(ptr, data32);
4278

    
4279
    ptr += (14 << data32);
4280
    for(i = 0;i < 8; i++) {
4281
        tmp = ST(i);
4282
        helper_fstt(tmp, ptr);
4283
        ptr += 10;
4284
    }
4285

    
4286
    /* fninit */
4287
    env->fpus = 0;
4288
    env->fpstt = 0;
4289
    env->fpuc = 0x37f;
4290
    env->fptags[0] = 1;
4291
    env->fptags[1] = 1;
4292
    env->fptags[2] = 1;
4293
    env->fptags[3] = 1;
4294
    env->fptags[4] = 1;
4295
    env->fptags[5] = 1;
4296
    env->fptags[6] = 1;
4297
    env->fptags[7] = 1;
4298
}
4299

    
4300
void helper_frstor(target_ulong ptr, int data32)
4301
{
4302
    CPU86_LDouble tmp;
4303
    int i;
4304

    
4305
    helper_fldenv(ptr, data32);
4306
    ptr += (14 << data32);
4307

    
4308
    for(i = 0;i < 8; i++) {
4309
        tmp = helper_fldt(ptr);
4310
        ST(i) = tmp;
4311
        ptr += 10;
4312
    }
4313
}
4314

    
4315
void helper_fxsave(target_ulong ptr, int data64)
4316
{
4317
    int fpus, fptag, i, nb_xmm_regs;
4318
    CPU86_LDouble tmp;
4319
    target_ulong addr;
4320

    
4321
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4322
    fptag = 0;
4323
    for(i = 0; i < 8; i++) {
4324
        fptag |= (env->fptags[i] << i);
4325
    }
4326
    stw(ptr, env->fpuc);
4327
    stw(ptr + 2, fpus);
4328
    stw(ptr + 4, fptag ^ 0xff);
4329
#ifdef TARGET_X86_64
4330
    if (data64) {
4331
        stq(ptr + 0x08, 0); /* rip */
4332
        stq(ptr + 0x10, 0); /* rdp */
4333
    } else 
4334
#endif
4335
    {
4336
        stl(ptr + 0x08, 0); /* eip */
4337
        stl(ptr + 0x0c, 0); /* sel  */
4338
        stl(ptr + 0x10, 0); /* dp */
4339
        stl(ptr + 0x14, 0); /* sel  */
4340
    }
4341

    
4342
    addr = ptr + 0x20;
4343
    for(i = 0;i < 8; i++) {
4344
        tmp = ST(i);
4345
        helper_fstt(tmp, addr);
4346
        addr += 16;
4347
    }
4348

    
4349
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4350
        /* XXX: finish it */
4351
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4352
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4353
        if (env->hflags & HF_CS64_MASK)
4354
            nb_xmm_regs = 16;
4355
        else
4356
            nb_xmm_regs = 8;
4357
        addr = ptr + 0xa0;
4358
        /* Fast FXSAVE leaves out the XMM registers */
4359
        if (!(env->efer & MSR_EFER_FFXSR)
4360
          || (env->hflags & HF_CPL_MASK)
4361
          || !(env->hflags & HF_LMA_MASK)) {
4362
            for(i = 0; i < nb_xmm_regs; i++) {
4363
                stq(addr, env->xmm_regs[i].XMM_Q(0));
4364
                stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4365
                addr += 16;
4366
            }
4367
        }
4368
    }
4369
}
4370

    
4371
void helper_fxrstor(target_ulong ptr, int data64)
4372
{
4373
    int i, fpus, fptag, nb_xmm_regs;
4374
    CPU86_LDouble tmp;
4375
    target_ulong addr;
4376

    
4377
    env->fpuc = lduw(ptr);
4378
    fpus = lduw(ptr + 2);
4379
    fptag = lduw(ptr + 4);
4380
    env->fpstt = (fpus >> 11) & 7;
4381
    env->fpus = fpus & ~0x3800;
4382
    fptag ^= 0xff;
4383
    for(i = 0;i < 8; i++) {
4384
        env->fptags[i] = ((fptag >> i) & 1);
4385
    }
4386

    
4387
    addr = ptr + 0x20;
4388
    for(i = 0;i < 8; i++) {
4389
        tmp = helper_fldt(addr);
4390
        ST(i) = tmp;
4391
        addr += 16;
4392
    }
4393

    
4394
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4395
        /* XXX: finish it */
4396
        env->mxcsr = ldl(ptr + 0x18);
4397
        //ldl(ptr + 0x1c);
4398
        if (env->hflags & HF_CS64_MASK)
4399
            nb_xmm_regs = 16;
4400
        else
4401
            nb_xmm_regs = 8;
4402
        addr = ptr + 0xa0;
4403
        /* Fast FXRESTORE leaves out the XMM registers */
4404
        if (!(env->efer & MSR_EFER_FFXSR)
4405
          || (env->hflags & HF_CPL_MASK)
4406
          || !(env->hflags & HF_LMA_MASK)) {
4407
            for(i = 0; i < nb_xmm_regs; i++) {
4408
                env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4409
                env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4410
                addr += 16;
4411
            }
4412
        }
4413
    }
4414
}
4415

    
4416
#ifndef USE_X86LDOUBLE
4417

    
4418
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4419
{
4420
    CPU86_LDoubleU temp;
4421
    int e;
4422

    
4423
    temp.d = f;
4424
    /* mantissa */
4425
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4426
    /* exponent + sign */
4427
    e = EXPD(temp) - EXPBIAS + 16383;
4428
    e |= SIGND(temp) >> 16;
4429
    *pexp = e;
4430
}
4431

    
4432
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4433
{
4434
    CPU86_LDoubleU temp;
4435
    int e;
4436
    uint64_t ll;
4437

    
4438
    /* XXX: handle overflow ? */
4439
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4440
    e |= (upper >> 4) & 0x800; /* sign */
4441
    ll = (mant >> 11) & ((1LL << 52) - 1);
4442
#ifdef __arm__
4443
    temp.l.upper = (e << 20) | (ll >> 32);
4444
    temp.l.lower = ll;
4445
#else
4446
    temp.ll = ll | ((uint64_t)e << 52);
4447
#endif
4448
    return temp.d;
4449
}
4450

    
4451
#else
4452

    
4453
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4454
{
4455
    CPU86_LDoubleU temp;
4456

    
4457
    temp.d = f;
4458
    *pmant = temp.l.lower;
4459
    *pexp = temp.l.upper;
4460
}
4461

    
4462
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4463
{
4464
    CPU86_LDoubleU temp;
4465

    
4466
    temp.l.upper = upper;
4467
    temp.l.lower = mant;
4468
    return temp.d;
4469
}
4470
#endif
4471

    
4472
#ifdef TARGET_X86_64
4473

    
4474
//#define DEBUG_MULDIV
4475

    
4476
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4477
{
4478
    *plow += a;
4479
    /* carry test */
4480
    if (*plow < a)
4481
        (*phigh)++;
4482
    *phigh += b;
4483
}
4484

    
4485
static void neg128(uint64_t *plow, uint64_t *phigh)
4486
{
4487
    *plow = ~ *plow;
4488
    *phigh = ~ *phigh;
4489
    add128(plow, phigh, 1, 0);
4490
}
4491

    
4492
/* return TRUE if overflow */
4493
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4494
{
4495
    uint64_t q, r, a1, a0;
4496
    int i, qb, ab;
4497

    
4498
    a0 = *plow;
4499
    a1 = *phigh;
4500
    if (a1 == 0) {
4501
        q = a0 / b;
4502
        r = a0 % b;
4503
        *plow = q;
4504
        *phigh = r;
4505
    } else {
4506
        if (a1 >= b)
4507
            return 1;
4508
        /* XXX: use a better algorithm */
4509
        for(i = 0; i < 64; i++) {
4510
            ab = a1 >> 63;
4511
            a1 = (a1 << 1) | (a0 >> 63);
4512
            if (ab || a1 >= b) {
4513
                a1 -= b;
4514
                qb = 1;
4515
            } else {
4516
                qb = 0;
4517
            }
4518
            a0 = (a0 << 1) | qb;
4519
        }
4520
#if defined(DEBUG_MULDIV)
4521
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4522
               *phigh, *plow, b, a0, a1);
4523
#endif
4524
        *plow = a0;
4525
        *phigh = a1;
4526
    }
4527
    return 0;
4528
}
4529

    
4530
/* return TRUE if overflow */
4531
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4532
{
4533
    int sa, sb;
4534
    sa = ((int64_t)*phigh < 0);
4535
    if (sa)
4536
        neg128(plow, phigh);
4537
    sb = (b < 0);
4538
    if (sb)
4539
        b = -b;
4540
    if (div64(plow, phigh, b) != 0)
4541
        return 1;
4542
    if (sa ^ sb) {
4543
        if (*plow > (1ULL << 63))
4544
            return 1;
4545
        *plow = - *plow;
4546
    } else {
4547
        if (*plow >= (1ULL << 63))
4548
            return 1;
4549
    }
4550
    if (sa)
4551
        *phigh = - *phigh;
4552
    return 0;
4553
}
4554

    
4555
void helper_mulq_EAX_T0(target_ulong t0)
4556
{
4557
    uint64_t r0, r1;
4558

    
4559
    mulu64(&r0, &r1, EAX, t0);
4560
    EAX = r0;
4561
    EDX = r1;
4562
    CC_DST = r0;
4563
    CC_SRC = r1;
4564
}
4565

    
4566
void helper_imulq_EAX_T0(target_ulong t0)
4567
{
4568
    uint64_t r0, r1;
4569

    
4570
    muls64(&r0, &r1, EAX, t0);
4571
    EAX = r0;
4572
    EDX = r1;
4573
    CC_DST = r0;
4574
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4575
}
4576

    
4577
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4578
{
4579
    uint64_t r0, r1;
4580

    
4581
    muls64(&r0, &r1, t0, t1);
4582
    CC_DST = r0;
4583
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4584
    return r0;
4585
}
4586

    
4587
void helper_divq_EAX(target_ulong t0)
4588
{
4589
    uint64_t r0, r1;
4590
    if (t0 == 0) {
4591
        raise_exception(EXCP00_DIVZ);
4592
    }
4593
    r0 = EAX;
4594
    r1 = EDX;
4595
    if (div64(&r0, &r1, t0))
4596
        raise_exception(EXCP00_DIVZ);
4597
    EAX = r0;
4598
    EDX = r1;
4599
}
4600

    
4601
void helper_idivq_EAX(target_ulong t0)
4602
{
4603
    uint64_t r0, r1;
4604
    if (t0 == 0) {
4605
        raise_exception(EXCP00_DIVZ);
4606
    }
4607
    r0 = EAX;
4608
    r1 = EDX;
4609
    if (idiv64(&r0, &r1, t0))
4610
        raise_exception(EXCP00_DIVZ);
4611
    EAX = r0;
4612
    EDX = r1;
4613
}
4614
#endif
4615

    
4616
static void do_hlt(void)
4617
{
4618
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4619
    env->halted = 1;
4620
    env->exception_index = EXCP_HLT;
4621
    cpu_loop_exit();
4622
}
4623

    
4624
void helper_hlt(int next_eip_addend)
4625
{
4626
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4627
    EIP += next_eip_addend;
4628
    
4629
    do_hlt();
4630
}
4631

    
4632
void helper_monitor(target_ulong ptr)
4633
{
4634
    if ((uint32_t)ECX != 0)
4635
        raise_exception(EXCP0D_GPF);
4636
    /* XXX: store address ? */
4637
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4638
}
4639

    
4640
void helper_mwait(int next_eip_addend)
4641
{
4642
    if ((uint32_t)ECX != 0)
4643
        raise_exception(EXCP0D_GPF);
4644
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4645
    EIP += next_eip_addend;
4646

    
4647
    /* XXX: not complete but not completely erroneous */
4648
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4649
        /* more than one CPU: do not sleep because another CPU may
4650
           wake this one */
4651
    } else {
4652
        do_hlt();
4653
    }
4654
}
4655

    
4656
void helper_debug(void)
4657
{
4658
    env->exception_index = EXCP_DEBUG;
4659
    cpu_loop_exit();
4660
}
4661

    
4662
void helper_raise_interrupt(int intno, int next_eip_addend)
4663
{
4664
    raise_interrupt(intno, 1, 0, next_eip_addend);
4665
}
4666

    
4667
void helper_raise_exception(int exception_index)
4668
{
4669
    raise_exception(exception_index);
4670
}
4671

    
4672
void helper_cli(void)
4673
{
4674
    env->eflags &= ~IF_MASK;
4675
}
4676

    
4677
void helper_sti(void)
4678
{
4679
    env->eflags |= IF_MASK;
4680
}
4681

    
4682
#if 0
4683
/* vm86plus instructions */
4684
void helper_cli_vm(void)
4685
{
4686
    env->eflags &= ~VIF_MASK;
4687
}
4688

4689
void helper_sti_vm(void)
4690
{
4691
    env->eflags |= VIF_MASK;
4692
    if (env->eflags & VIP_MASK) {
4693
        raise_exception(EXCP0D_GPF);
4694
    }
4695
}
4696
#endif
4697

    
4698
void helper_set_inhibit_irq(void)
4699
{
4700
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4701
}
4702

    
4703
void helper_reset_inhibit_irq(void)
4704
{
4705
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4706
}
4707

    
4708
void helper_boundw(target_ulong a0, int v)
4709
{
4710
    int low, high;
4711
    low = ldsw(a0);
4712
    high = ldsw(a0 + 2);
4713
    v = (int16_t)v;
4714
    if (v < low || v > high) {
4715
        raise_exception(EXCP05_BOUND);
4716
    }
4717
}
4718

    
4719
void helper_boundl(target_ulong a0, int v)
4720
{
4721
    int low, high;
4722
    low = ldl(a0);
4723
    high = ldl(a0 + 4);
4724
    if (v < low || v > high) {
4725
        raise_exception(EXCP05_BOUND);
4726
    }
4727
}
4728

    
4729
static float approx_rsqrt(float a)
4730
{
4731
    return 1.0 / sqrt(a);
4732
}
4733

    
4734
static float approx_rcp(float a)
4735
{
4736
    return 1.0 / a;
4737
}
4738

    
4739
#if !defined(CONFIG_USER_ONLY)
4740

    
4741
#define MMUSUFFIX _mmu
4742

    
4743
#define SHIFT 0
4744
#include "softmmu_template.h"
4745

    
4746
#define SHIFT 1
4747
#include "softmmu_template.h"
4748

    
4749
#define SHIFT 2
4750
#include "softmmu_template.h"
4751

    
4752
#define SHIFT 3
4753
#include "softmmu_template.h"
4754

    
4755
#endif
4756

    
4757
#if !defined(CONFIG_USER_ONLY)
4758
/* try to fill the TLB and return an exception if error. If retaddr is
4759
   NULL, it means that the function was called in C code (i.e. not
4760
   from generated code or from helper.c) */
4761
/* XXX: fix it to restore all registers */
4762
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4763
{
4764
    TranslationBlock *tb;
4765
    int ret;
4766
    unsigned long pc;
4767
    CPUX86State *saved_env;
4768

    
4769
    /* XXX: hack to restore env in all cases, even if not called from
4770
       generated code */
4771
    saved_env = env;
4772
    env = cpu_single_env;
4773

    
4774
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4775
    if (ret) {
4776
        if (retaddr) {
4777
            /* now we have a real cpu fault */
4778
            pc = (unsigned long)retaddr;
4779
            tb = tb_find_pc(pc);
4780
            if (tb) {
4781
                /* the PC is inside the translated code. It means that we have
4782
                   a virtual CPU fault */
4783
                cpu_restore_state(tb, env, pc, NULL);
4784
            }
4785
        }
4786
        raise_exception_err(env->exception_index, env->error_code);
4787
    }
4788
    env = saved_env;
4789
}
4790
#endif
4791

    
4792
/* Secure Virtual Machine helpers */
4793

    
4794
#if defined(CONFIG_USER_ONLY)
4795

    
4796
void helper_vmrun(int aflag, int next_eip_addend)
4797
{ 
4798
}
4799
void helper_vmmcall(void) 
4800
{ 
4801
}
4802
void helper_vmload(int aflag)
4803
{ 
4804
}
4805
void helper_vmsave(int aflag)
4806
{ 
4807
}
4808
void helper_stgi(void)
4809
{
4810
}
4811
void helper_clgi(void)
4812
{
4813
}
4814
void helper_skinit(void) 
4815
{ 
4816
}
4817
void helper_invlpga(int aflag)
4818
{ 
4819
}
4820
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4821
{ 
4822
}
4823
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4824
{
4825
}
4826

    
4827
void helper_svm_check_io(uint32_t port, uint32_t param, 
4828
                         uint32_t next_eip_addend)
4829
{
4830
}
4831
#else
4832

    
4833
static inline void svm_save_seg(target_phys_addr_t addr,
4834
                                const SegmentCache *sc)
4835
{
4836
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4837
             sc->selector);
4838
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4839
             sc->base);
4840
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4841
             sc->limit);
4842
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4843
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4844
}
4845
                                
4846
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4847
{
4848
    unsigned int flags;
4849

    
4850
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4851
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4852
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4853
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4854
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4855
}
4856

    
4857
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4858
                                      CPUState *env, int seg_reg)
4859
{
4860
    SegmentCache sc1, *sc = &sc1;
4861
    svm_load_seg(addr, sc);
4862
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4863
                           sc->base, sc->limit, sc->flags);
4864
}
4865

    
4866
void helper_vmrun(int aflag, int next_eip_addend)
4867
{
4868
    target_ulong addr;
4869
    uint32_t event_inj;
4870
    uint32_t int_ctl;
4871

    
4872
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4873

    
4874
    if (aflag == 2)
4875
        addr = EAX;
4876
    else
4877
        addr = (uint32_t)EAX;
4878

    
4879
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
4880

    
4881
    env->vm_vmcb = addr;
4882

    
4883
    /* save the current CPU state in the hsave page */
4884
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4885
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4886

    
4887
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4888
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4889

    
4890
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4891
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4892
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4893
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4894
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4895
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4896

    
4897
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4898
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4899

    
4900
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4901
                  &env->segs[R_ES]);
4902
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4903
                 &env->segs[R_CS]);
4904
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4905
                 &env->segs[R_SS]);
4906
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4907
                 &env->segs[R_DS]);
4908

    
4909
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
4910
             EIP + next_eip_addend);
4911
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4912
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4913

    
4914
    /* load the interception bitmaps so we do not need to access the
4915
       vmcb in svm mode */
4916
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4917
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4918
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4919
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4920
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4921
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4922

    
4923
    /* enable intercepts */
4924
    env->hflags |= HF_SVMI_MASK;
4925

    
4926
    env->tsc_offset = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.tsc_offset));
4927

    
4928
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4929
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4930

    
4931
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4932
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4933

    
4934
    /* clear exit_info_2 so we behave like the real hardware */
4935
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
4936

    
4937
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4938
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4939
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4940
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4941
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4942
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4943
    if (int_ctl & V_INTR_MASKING_MASK) {
4944
        env->v_tpr = int_ctl & V_TPR_MASK;
4945
        env->hflags2 |= HF2_VINTR_MASK;
4946
        if (env->eflags & IF_MASK)
4947
            env->hflags2 |= HF2_HIF_MASK;
4948
    }
4949

    
4950
    cpu_load_efer(env, 
4951
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4952
    env->eflags = 0;
4953
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4954
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4955
    CC_OP = CC_OP_EFLAGS;
4956

    
4957
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4958
                       env, R_ES);
4959
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4960
                       env, R_CS);
4961
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4962
                       env, R_SS);
4963
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4964
                       env, R_DS);
4965

    
4966
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4967
    env->eip = EIP;
4968
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4969
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4970
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4971
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4972
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4973

    
4974
    /* FIXME: guest state consistency checks */
4975

    
4976
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4977
        case TLB_CONTROL_DO_NOTHING:
4978
            break;
4979
        case TLB_CONTROL_FLUSH_ALL_ASID:
4980
            /* FIXME: this is not 100% correct but should work for now */
4981
            tlb_flush(env, 1);
4982
        break;
4983
    }
4984

    
4985
    env->hflags2 |= HF2_GIF_MASK;
4986

    
4987
    if (int_ctl & V_IRQ_MASK) {
4988
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4989
    }
4990

    
4991
    /* maybe we need to inject an event */
4992
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4993
    if (event_inj & SVM_EVTINJ_VALID) {
4994
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4995
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4996
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4997
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4998

    
4999
        qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
5000
        /* FIXME: need to implement valid_err */
5001
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
5002
        case SVM_EVTINJ_TYPE_INTR:
5003
                env->exception_index = vector;
5004
                env->error_code = event_inj_err;
5005
                env->exception_is_int = 0;
5006
                env->exception_next_eip = -1;
5007
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
5008
                /* XXX: is it always correct ? */
5009
                do_interrupt(vector, 0, 0, 0, 1);
5010
                break;
5011
        case SVM_EVTINJ_TYPE_NMI:
5012
                env->exception_index = EXCP02_NMI;
5013
                env->error_code = event_inj_err;
5014
                env->exception_is_int = 0;
5015
                env->exception_next_eip = EIP;
5016
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
5017
                cpu_loop_exit();
5018
                break;
5019
        case SVM_EVTINJ_TYPE_EXEPT:
5020
                env->exception_index = vector;
5021
                env->error_code = event_inj_err;
5022
                env->exception_is_int = 0;
5023
                env->exception_next_eip = -1;
5024
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
5025
                cpu_loop_exit();
5026
                break;
5027
        case SVM_EVTINJ_TYPE_SOFT:
5028
                env->exception_index = vector;
5029
                env->error_code = event_inj_err;
5030
                env->exception_is_int = 1;
5031
                env->exception_next_eip = EIP;
5032
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
5033
                cpu_loop_exit();
5034
                break;
5035
        }
5036
        qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index, env->error_code);
5037
    }
5038
}
5039

    
5040
void helper_vmmcall(void)
5041
{
5042
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
5043
    raise_exception(EXCP06_ILLOP);
5044
}
5045

    
5046
void helper_vmload(int aflag)
5047
{
5048
    target_ulong addr;
5049
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
5050

    
5051
    if (aflag == 2)
5052
        addr = EAX;
5053
    else
5054
        addr = (uint32_t)EAX;
5055

    
5056
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5057
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5058
                env->segs[R_FS].base);
5059

    
5060
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
5061
                       env, R_FS);
5062
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
5063
                       env, R_GS);
5064
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
5065
                 &env->tr);
5066
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
5067
                 &env->ldt);
5068

    
5069
#ifdef TARGET_X86_64
5070
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
5071
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
5072
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
5073
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
5074
#endif
5075
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
5076
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
5077
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
5078
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
5079
}
5080

    
5081
void helper_vmsave(int aflag)
5082
{
5083
    target_ulong addr;
5084
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5085

    
5086
    if (aflag == 2)
5087
        addr = EAX;
5088
    else
5089
        addr = (uint32_t)EAX;
5090

    
5091
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5092
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5093
                env->segs[R_FS].base);
5094

    
5095
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5096
                 &env->segs[R_FS]);
5097
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5098
                 &env->segs[R_GS]);
5099
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5100
                 &env->tr);
5101
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5102
                 &env->ldt);
5103

    
5104
#ifdef TARGET_X86_64
5105
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
5106
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
5107
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
5108
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
5109
#endif
5110
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
5111
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
5112
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
5113
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
5114
}
5115

    
5116
void helper_stgi(void)
5117
{
5118
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5119
    env->hflags2 |= HF2_GIF_MASK;
5120
}
5121

    
5122
void helper_clgi(void)
5123
{
5124
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5125
    env->hflags2 &= ~HF2_GIF_MASK;
5126
}
5127

    
5128
void helper_skinit(void)
5129
{
5130
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5131
    /* XXX: not implemented */
5132
    raise_exception(EXCP06_ILLOP);
5133
}
5134

    
5135
void helper_invlpga(int aflag)
5136
{
5137
    target_ulong addr;
5138
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5139
    
5140
    if (aflag == 2)
5141
        addr = EAX;
5142
    else
5143
        addr = (uint32_t)EAX;
5144

    
5145
    /* XXX: could use the ASID to see if it is needed to do the
5146
       flush */
5147
    tlb_flush_page(env, addr);
5148
}
5149

    
5150
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5151
{
5152
    if (likely(!(env->hflags & HF_SVMI_MASK)))
5153
        return;
5154
    switch(type) {
5155
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5156
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5157
            helper_vmexit(type, param);
5158
        }
5159
        break;
5160
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5161
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
5162
            helper_vmexit(type, param);
5163
        }
5164
        break;
5165
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
5166
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
5167
            helper_vmexit(type, param);
5168
        }
5169
        break;
5170
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
5171
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
5172
            helper_vmexit(type, param);
5173
        }
5174
        break;
5175
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
5176
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
5177
            helper_vmexit(type, param);
5178
        }
5179
        break;
5180
    case SVM_EXIT_MSR:
5181
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5182
            /* FIXME: this should be read in at vmrun (faster this way?) */
5183
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5184
            uint32_t t0, t1;
5185
            switch((uint32_t)ECX) {
5186
            case 0 ... 0x1fff:
5187
                t0 = (ECX * 2) % 8;
5188
                t1 = ECX / 8;
5189
                break;
5190
            case 0xc0000000 ... 0xc0001fff:
5191
                t0 = (8192 + ECX - 0xc0000000) * 2;
5192
                t1 = (t0 / 8);
5193
                t0 %= 8;
5194
                break;
5195
            case 0xc0010000 ... 0xc0011fff:
5196
                t0 = (16384 + ECX - 0xc0010000) * 2;
5197
                t1 = (t0 / 8);
5198
                t0 %= 8;
5199
                break;
5200
            default:
5201
                helper_vmexit(type, param);
5202
                t0 = 0;
5203
                t1 = 0;
5204
                break;
5205
            }
5206
            if (ldub_phys(addr + t1) & ((1 << param) << t0))
5207
                helper_vmexit(type, param);
5208
        }
5209
        break;
5210
    default:
5211
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5212
            helper_vmexit(type, param);
5213
        }
5214
        break;
5215
    }
5216
}
5217

    
5218
void helper_svm_check_io(uint32_t port, uint32_t param, 
5219
                         uint32_t next_eip_addend)
5220
{
5221
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5222
        /* FIXME: this should be read in at vmrun (faster this way?) */
5223
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5224
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5225
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5226
            /* next EIP */
5227
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5228
                     env->eip + next_eip_addend);
5229
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5230
        }
5231
    }
5232
}
5233

    
5234
/* Note: currently only 32 bits of exit_code are used */
5235
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5236
{
5237
    uint32_t int_ctl;
5238

    
5239
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5240
                exit_code, exit_info_1,
5241
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5242
                EIP);
5243

    
5244
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5245
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5246
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5247
    } else {
5248
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5249
    }
5250

    
5251
    /* Save the VM state in the vmcb */
5252
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5253
                 &env->segs[R_ES]);
5254
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5255
                 &env->segs[R_CS]);
5256
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5257
                 &env->segs[R_SS]);
5258
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5259
                 &env->segs[R_DS]);
5260

    
5261
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5262
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5263

    
5264
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5265
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5266

    
5267
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5268
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5269
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5270
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5271
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5272

    
5273
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5274
    int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
5275
    int_ctl |= env->v_tpr & V_TPR_MASK;
5276
    if (env->interrupt_request & CPU_INTERRUPT_VIRQ)
5277
        int_ctl |= V_IRQ_MASK;
5278
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5279

    
5280
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5281
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5282
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5283
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5284
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5285
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5286
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5287

    
5288
    /* Reload the host state from vm_hsave */
5289
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5290
    env->hflags &= ~HF_SVMI_MASK;
5291
    env->intercept = 0;
5292
    env->intercept_exceptions = 0;
5293
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5294
    env->tsc_offset = 0;
5295

    
5296
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5297
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5298

    
5299
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5300
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5301

    
5302
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5303
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5304
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5305
    /* we need to set the efer after the crs so the hidden flags get
5306
       set properly */
5307
    cpu_load_efer(env, 
5308
                  ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
5309
    env->eflags = 0;
5310
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5311
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5312
    CC_OP = CC_OP_EFLAGS;
5313

    
5314
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5315
                       env, R_ES);
5316
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5317
                       env, R_CS);
5318
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5319
                       env, R_SS);
5320
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5321
                       env, R_DS);
5322

    
5323
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5324
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5325
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5326

    
5327
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5328
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5329

    
5330
    /* other setups */
5331
    cpu_x86_set_cpl(env, 0);
5332
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5333
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5334

    
5335
    env->hflags2 &= ~HF2_GIF_MASK;
5336
    /* FIXME: Resets the current ASID register to zero (host ASID). */
5337

    
5338
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5339

    
5340
    /* Clears the TSC_OFFSET inside the processor. */
5341

    
5342
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5343
       from the page table indicated the host's CR3. If the PDPEs contain
5344
       illegal state, the processor causes a shutdown. */
5345

    
5346
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5347
    env->cr[0] |= CR0_PE_MASK;
5348
    env->eflags &= ~VM_MASK;
5349

    
5350
    /* Disables all breakpoints in the host DR7 register. */
5351

    
5352
    /* Checks the reloaded host state for consistency. */
5353

    
5354
    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5355
       host's code segment or non-canonical (in the case of long mode), a
5356
       #GP fault is delivered inside the host.) */
5357

    
5358
    /* remove any pending exception */
5359
    env->exception_index = -1;
5360
    env->error_code = 0;
5361
    env->old_exception = -1;
5362

    
5363
    cpu_loop_exit();
5364
}
5365

    
5366
#endif
5367

    
5368
/* MMX/SSE */
5369
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5370
void helper_enter_mmx(void)
5371
{
5372
    env->fpstt = 0;
5373
    *(uint32_t *)(env->fptags) = 0;
5374
    *(uint32_t *)(env->fptags + 4) = 0;
5375
}
5376

    
5377
void helper_emms(void)
5378
{
5379
    /* set to empty state */
5380
    *(uint32_t *)(env->fptags) = 0x01010101;
5381
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5382
}
5383

    
5384
/* XXX: suppress */
5385
void helper_movq(void *d, void *s)
5386
{
5387
    *(uint64_t *)d = *(uint64_t *)s;
5388
}
5389

    
5390
#define SHIFT 0
5391
#include "ops_sse.h"
5392

    
5393
#define SHIFT 1
5394
#include "ops_sse.h"
5395

    
5396
#define SHIFT 0
5397
#include "helper_template.h"
5398
#undef SHIFT
5399

    
5400
#define SHIFT 1
5401
#include "helper_template.h"
5402
#undef SHIFT
5403

    
5404
#define SHIFT 2
5405
#include "helper_template.h"
5406
#undef SHIFT
5407

    
5408
#ifdef TARGET_X86_64
5409

    
5410
#define SHIFT 3
5411
#include "helper_template.h"
5412
#undef SHIFT
5413

    
5414
#endif
5415

    
5416
/* bit operations */
5417
target_ulong helper_bsf(target_ulong t0)
5418
{
5419
    int count;
5420
    target_ulong res;
5421

    
5422
    res = t0;
5423
    count = 0;
5424
    while ((res & 1) == 0) {
5425
        count++;
5426
        res >>= 1;
5427
    }
5428
    return count;
5429
}
5430

    
5431
target_ulong helper_bsr(target_ulong t0)
5432
{
5433
    int count;
5434
    target_ulong res, mask;
5435
    
5436
    res = t0;
5437
    count = TARGET_LONG_BITS - 1;
5438
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5439
    while ((res & mask) == 0) {
5440
        count--;
5441
        res <<= 1;
5442
    }
5443
    return count;
5444
}
5445

    
5446

    
5447
static int compute_all_eflags(void)
5448
{
5449
    return CC_SRC;
5450
}
5451

    
5452
static int compute_c_eflags(void)
5453
{
5454
    return CC_SRC & CC_C;
5455
}
5456

    
5457
uint32_t helper_cc_compute_all(int op)
5458
{
5459
    switch (op) {
5460
    default: /* should never happen */ return 0;
5461

    
5462
    case CC_OP_EFLAGS: return compute_all_eflags();
5463

    
5464
    case CC_OP_MULB: return compute_all_mulb();
5465
    case CC_OP_MULW: return compute_all_mulw();
5466
    case CC_OP_MULL: return compute_all_mull();
5467

    
5468
    case CC_OP_ADDB: return compute_all_addb();
5469
    case CC_OP_ADDW: return compute_all_addw();
5470
    case CC_OP_ADDL: return compute_all_addl();
5471

    
5472
    case CC_OP_ADCB: return compute_all_adcb();
5473
    case CC_OP_ADCW: return compute_all_adcw();
5474
    case CC_OP_ADCL: return compute_all_adcl();
5475

    
5476
    case CC_OP_SUBB: return compute_all_subb();
5477
    case CC_OP_SUBW: return compute_all_subw();
5478
    case CC_OP_SUBL: return compute_all_subl();
5479

    
5480
    case CC_OP_SBBB: return compute_all_sbbb();
5481
    case CC_OP_SBBW: return compute_all_sbbw();
5482
    case CC_OP_SBBL: return compute_all_sbbl();
5483

    
5484
    case CC_OP_LOGICB: return compute_all_logicb();
5485
    case CC_OP_LOGICW: return compute_all_logicw();
5486
    case CC_OP_LOGICL: return compute_all_logicl();
5487

    
5488
    case CC_OP_INCB: return compute_all_incb();
5489
    case CC_OP_INCW: return compute_all_incw();
5490
    case CC_OP_INCL: return compute_all_incl();
5491

    
5492
    case CC_OP_DECB: return compute_all_decb();
5493
    case CC_OP_DECW: return compute_all_decw();
5494
    case CC_OP_DECL: return compute_all_decl();
5495

    
5496
    case CC_OP_SHLB: return compute_all_shlb();
5497
    case CC_OP_SHLW: return compute_all_shlw();
5498
    case CC_OP_SHLL: return compute_all_shll();
5499

    
5500
    case CC_OP_SARB: return compute_all_sarb();
5501
    case CC_OP_SARW: return compute_all_sarw();
5502
    case CC_OP_SARL: return compute_all_sarl();
5503

    
5504
#ifdef TARGET_X86_64
5505
    case CC_OP_MULQ: return compute_all_mulq();
5506

    
5507
    case CC_OP_ADDQ: return compute_all_addq();
5508

    
5509
    case CC_OP_ADCQ: return compute_all_adcq();
5510

    
5511
    case CC_OP_SUBQ: return compute_all_subq();
5512

    
5513
    case CC_OP_SBBQ: return compute_all_sbbq();
5514

    
5515
    case CC_OP_LOGICQ: return compute_all_logicq();
5516

    
5517
    case CC_OP_INCQ: return compute_all_incq();
5518

    
5519
    case CC_OP_DECQ: return compute_all_decq();
5520

    
5521
    case CC_OP_SHLQ: return compute_all_shlq();
5522

    
5523
    case CC_OP_SARQ: return compute_all_sarq();
5524
#endif
5525
    }
5526
}
5527

    
5528
uint32_t helper_cc_compute_c(int op)
5529
{
5530
    switch (op) {
5531
    default: /* should never happen */ return 0;
5532

    
5533
    case CC_OP_EFLAGS: return compute_c_eflags();
5534

    
5535
    case CC_OP_MULB: return compute_c_mull();
5536
    case CC_OP_MULW: return compute_c_mull();
5537
    case CC_OP_MULL: return compute_c_mull();
5538

    
5539
    case CC_OP_ADDB: return compute_c_addb();
5540
    case CC_OP_ADDW: return compute_c_addw();
5541
    case CC_OP_ADDL: return compute_c_addl();
5542

    
5543
    case CC_OP_ADCB: return compute_c_adcb();
5544
    case CC_OP_ADCW: return compute_c_adcw();
5545
    case CC_OP_ADCL: return compute_c_adcl();
5546

    
5547
    case CC_OP_SUBB: return compute_c_subb();
5548
    case CC_OP_SUBW: return compute_c_subw();
5549
    case CC_OP_SUBL: return compute_c_subl();
5550

    
5551
    case CC_OP_SBBB: return compute_c_sbbb();
5552
    case CC_OP_SBBW: return compute_c_sbbw();
5553
    case CC_OP_SBBL: return compute_c_sbbl();
5554

    
5555
    case CC_OP_LOGICB: return compute_c_logicb();
5556
    case CC_OP_LOGICW: return compute_c_logicw();
5557
    case CC_OP_LOGICL: return compute_c_logicl();
5558

    
5559
    case CC_OP_INCB: return compute_c_incl();
5560
    case CC_OP_INCW: return compute_c_incl();
5561
    case CC_OP_INCL: return compute_c_incl();
5562

    
5563
    case CC_OP_DECB: return compute_c_incl();
5564
    case CC_OP_DECW: return compute_c_incl();
5565
    case CC_OP_DECL: return compute_c_incl();
5566

    
5567
    case CC_OP_SHLB: return compute_c_shlb();
5568
    case CC_OP_SHLW: return compute_c_shlw();
5569
    case CC_OP_SHLL: return compute_c_shll();
5570

    
5571
    case CC_OP_SARB: return compute_c_sarl();
5572
    case CC_OP_SARW: return compute_c_sarl();
5573
    case CC_OP_SARL: return compute_c_sarl();
5574

    
5575
#ifdef TARGET_X86_64
5576
    case CC_OP_MULQ: return compute_c_mull();
5577

    
5578
    case CC_OP_ADDQ: return compute_c_addq();
5579

    
5580
    case CC_OP_ADCQ: return compute_c_adcq();
5581

    
5582
    case CC_OP_SUBQ: return compute_c_subq();
5583

    
5584
    case CC_OP_SBBQ: return compute_c_sbbq();
5585

    
5586
    case CC_OP_LOGICQ: return compute_c_logicq();
5587

    
5588
    case CC_OP_INCQ: return compute_c_incl();
5589

    
5590
    case CC_OP_DECQ: return compute_c_incl();
5591

    
5592
    case CC_OP_SHLQ: return compute_c_shlq();
5593

    
5594
    case CC_OP_SARQ: return compute_c_sarl();
5595
#endif
5596
    }
5597
}