Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ dd5e3b17

History | View | Annotate | Download (156.1 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
        if (loglevel & CPU_LOG_RESET)
1279
            fprintf(logfile, "Triple fault\n");
1280

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

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

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

    
1297
    return intno;
1298
}
1299

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

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

    
1323
/* shortcuts to generate exceptions */
1324

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

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

    
1335
/* SMM support */
1336

    
1337
#if defined(CONFIG_USER_ONLY)
1338

    
1339
void do_smm_enter(void)
1340
{
1341
}
1342

    
1343
void helper_rsm(void)
1344
{
1345
}
1346

    
1347
#else
1348

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1606
#endif /* !CONFIG_USER_ONLY */
1607

    
1608

    
1609
/* division, flags are undefined */
1610

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

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

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

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

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

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

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

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

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

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

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

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

    
1717
/* bcd */
1718

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1914
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1915

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3002
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3003

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

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

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

    
3116
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3117

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

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

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

    
3278
target_ulong helper_lar(target_ulong selector1)
3279
{
3280
    uint32_t e1, e2, eflags, selector;
3281
    int rpl, dpl, cpl, type;
3282

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

    
3324
void helper_verr(target_ulong selector1)
3325
{
3326
    uint32_t e1, e2, eflags, selector;
3327
    int rpl, dpl, cpl;
3328

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

    
3357
void helper_verw(target_ulong selector1)
3358
{
3359
    uint32_t e1, e2, eflags, selector;
3360
    int rpl, dpl, cpl;
3361

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

    
3387
/* x87 FPU helpers */
3388

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

    
3396
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3397
{
3398
    if (b == 0.0)
3399
        fpu_set_exception(FPUS_ZE);
3400
    return a / b;
3401
}
3402

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

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

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

    
3435
void helper_fildl_FT0(int32_t val)
3436
{
3437
    FT0 = int32_to_floatx(val, &env->fp_status);
3438
}
3439

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

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

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

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

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

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

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

    
3515
int32_t helper_fistl_ST0(void)
3516
{
3517
    int32_t val;
3518
    val = floatx_to_int32(ST0, &env->fp_status);
3519
    return val;
3520
}
3521

    
3522
int64_t helper_fistll_ST0(void)
3523
{
3524
    int64_t val;
3525
    val = floatx_to_int64(ST0, &env->fp_status);
3526
    return val;
3527
}
3528

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

    
3538
int32_t helper_fisttl_ST0(void)
3539
{
3540
    int32_t val;
3541
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3542
    return val;
3543
}
3544

    
3545
int64_t helper_fisttll_ST0(void)
3546
{
3547
    int64_t val;
3548
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3549
    return val;
3550
}
3551

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

    
3561
void helper_fstt_ST0(target_ulong ptr)
3562
{
3563
    helper_fstt(ST0, ptr);
3564
}
3565

    
3566
void helper_fpush(void)
3567
{
3568
    fpush();
3569
}
3570

    
3571
void helper_fpop(void)
3572
{
3573
    fpop();
3574
}
3575

    
3576
void helper_fdecstp(void)
3577
{
3578
    env->fpstt = (env->fpstt - 1) & 7;
3579
    env->fpus &= (~0x4700);
3580
}
3581

    
3582
void helper_fincstp(void)
3583
{
3584
    env->fpstt = (env->fpstt + 1) & 7;
3585
    env->fpus &= (~0x4700);
3586
}
3587

    
3588
/* FPU move */
3589

    
3590
void helper_ffree_STN(int st_index)
3591
{
3592
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3593
}
3594

    
3595
void helper_fmov_ST0_FT0(void)
3596
{
3597
    ST0 = FT0;
3598
}
3599

    
3600
void helper_fmov_FT0_STN(int st_index)
3601
{
3602
    FT0 = ST(st_index);
3603
}
3604

    
3605
void helper_fmov_ST0_STN(int st_index)
3606
{
3607
    ST0 = ST(st_index);
3608
}
3609

    
3610
void helper_fmov_STN_ST0(int st_index)
3611
{
3612
    ST(st_index) = ST0;
3613
}
3614

    
3615
void helper_fxchg_ST0_STN(int st_index)
3616
{
3617
    CPU86_LDouble tmp;
3618
    tmp = ST(st_index);
3619
    ST(st_index) = ST0;
3620
    ST0 = tmp;
3621
}
3622

    
3623
/* FPU operations */
3624

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

    
3627
void helper_fcom_ST0_FT0(void)
3628
{
3629
    int ret;
3630

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

    
3635
void helper_fucom_ST0_FT0(void)
3636
{
3637
    int ret;
3638

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

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

    
3645
void helper_fcomi_ST0_FT0(void)
3646
{
3647
    int eflags;
3648
    int ret;
3649

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

    
3656
void helper_fucomi_ST0_FT0(void)
3657
{
3658
    int eflags;
3659
    int ret;
3660

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

    
3667
void helper_fadd_ST0_FT0(void)
3668
{
3669
    ST0 += FT0;
3670
}
3671

    
3672
void helper_fmul_ST0_FT0(void)
3673
{
3674
    ST0 *= FT0;
3675
}
3676

    
3677
void helper_fsub_ST0_FT0(void)
3678
{
3679
    ST0 -= FT0;
3680
}
3681

    
3682
void helper_fsubr_ST0_FT0(void)
3683
{
3684
    ST0 = FT0 - ST0;
3685
}
3686

    
3687
void helper_fdiv_ST0_FT0(void)
3688
{
3689
    ST0 = helper_fdiv(ST0, FT0);
3690
}
3691

    
3692
void helper_fdivr_ST0_FT0(void)
3693
{
3694
    ST0 = helper_fdiv(FT0, ST0);
3695
}
3696

    
3697
/* fp operations between STN and ST0 */
3698

    
3699
void helper_fadd_STN_ST0(int st_index)
3700
{
3701
    ST(st_index) += ST0;
3702
}
3703

    
3704
void helper_fmul_STN_ST0(int st_index)
3705
{
3706
    ST(st_index) *= ST0;
3707
}
3708

    
3709
void helper_fsub_STN_ST0(int st_index)
3710
{
3711
    ST(st_index) -= ST0;
3712
}
3713

    
3714
void helper_fsubr_STN_ST0(int st_index)
3715
{
3716
    CPU86_LDouble *p;
3717
    p = &ST(st_index);
3718
    *p = ST0 - *p;
3719
}
3720

    
3721
void helper_fdiv_STN_ST0(int st_index)
3722
{
3723
    CPU86_LDouble *p;
3724
    p = &ST(st_index);
3725
    *p = helper_fdiv(*p, ST0);
3726
}
3727

    
3728
void helper_fdivr_STN_ST0(int st_index)
3729
{
3730
    CPU86_LDouble *p;
3731
    p = &ST(st_index);
3732
    *p = helper_fdiv(ST0, *p);
3733
}
3734

    
3735
/* misc FPU operations */
3736
void helper_fchs_ST0(void)
3737
{
3738
    ST0 = floatx_chs(ST0);
3739
}
3740

    
3741
void helper_fabs_ST0(void)
3742
{
3743
    ST0 = floatx_abs(ST0);
3744
}
3745

    
3746
void helper_fld1_ST0(void)
3747
{
3748
    ST0 = f15rk[1];
3749
}
3750

    
3751
void helper_fldl2t_ST0(void)
3752
{
3753
    ST0 = f15rk[6];
3754
}
3755

    
3756
void helper_fldl2e_ST0(void)
3757
{
3758
    ST0 = f15rk[5];
3759
}
3760

    
3761
void helper_fldpi_ST0(void)
3762
{
3763
    ST0 = f15rk[2];
3764
}
3765

    
3766
void helper_fldlg2_ST0(void)
3767
{
3768
    ST0 = f15rk[3];
3769
}
3770

    
3771
void helper_fldln2_ST0(void)
3772
{
3773
    ST0 = f15rk[4];
3774
}
3775

    
3776
void helper_fldz_ST0(void)
3777
{
3778
    ST0 = f15rk[0];
3779
}
3780

    
3781
void helper_fldz_FT0(void)
3782
{
3783
    FT0 = f15rk[0];
3784
}
3785

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

    
3791
uint32_t helper_fnstcw(void)
3792
{
3793
    return env->fpuc;
3794
}
3795

    
3796
static void update_fp_status(void)
3797
{
3798
    int rnd_type;
3799

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

    
3834
void helper_fldcw(uint32_t val)
3835
{
3836
    env->fpuc = val;
3837
    update_fp_status();
3838
}
3839

    
3840
void helper_fclex(void)
3841
{
3842
    env->fpus &= 0x7f00;
3843
}
3844

    
3845
void helper_fwait(void)
3846
{
3847
    if (env->fpus & FPUS_SE)
3848
        fpu_raise_exception();
3849
}
3850

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

    
3866
/* BCD ops */
3867

    
3868
void helper_fbld_ST0(target_ulong ptr)
3869
{
3870
    CPU86_LDouble tmp;
3871
    uint64_t val;
3872
    unsigned int v;
3873
    int i;
3874

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

    
3887
void helper_fbst_ST0(target_ulong ptr)
3888
{
3889
    int v;
3890
    target_ulong mem_ref, mem_end;
3891
    int64_t val;
3892

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

    
3915
void helper_f2xm1(void)
3916
{
3917
    ST0 = pow(2.0,ST0) - 1.0;
3918
}
3919

    
3920
void helper_fyl2x(void)
3921
{
3922
    CPU86_LDouble fptemp;
3923

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

    
3935
void helper_fptan(void)
3936
{
3937
    CPU86_LDouble fptemp;
3938

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

    
3951
void helper_fpatan(void)
3952
{
3953
    CPU86_LDouble fptemp, fpsrcop;
3954

    
3955
    fpsrcop = ST1;
3956
    fptemp = ST0;
3957
    ST1 = atan2(fpsrcop,fptemp);
3958
    fpop();
3959
}
3960

    
3961
void helper_fxtract(void)
3962
{
3963
    CPU86_LDoubleU temp;
3964
    unsigned int expdif;
3965

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

    
3975
void helper_fprem1(void)
3976
{
3977
    CPU86_LDouble dblq, fpsrcop, fptemp;
3978
    CPU86_LDoubleU fpsrcop1, fptemp1;
3979
    int expdif;
3980
    signed long long int q;
3981

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

    
3988
    fpsrcop = ST0;
3989
    fptemp = ST1;
3990
    fpsrcop1.d = fpsrcop;
3991
    fptemp1.d = fptemp;
3992
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3993

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

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

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

    
4013
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4014
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4015
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4016
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4017
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4018
    } else {
4019
        env->fpus |= 0x400;  /* C2 <-- 1 */
4020
        fptemp = pow(2.0, expdif - 50);
4021
        fpsrcop = (ST0 / ST1) / fptemp;
4022
        /* fpsrcop = integer obtained by chopping */
4023
        fpsrcop = (fpsrcop < 0.0) ?
4024
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4025
        ST0 -= (ST1 * fpsrcop * fptemp);
4026
    }
4027
}
4028

    
4029
void helper_fprem(void)
4030
{
4031
    CPU86_LDouble dblq, fpsrcop, fptemp;
4032
    CPU86_LDoubleU fpsrcop1, fptemp1;
4033
    int expdif;
4034
    signed long long int q;
4035

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

    
4042
    fpsrcop = (CPU86_LDouble)ST0;
4043
    fptemp = (CPU86_LDouble)ST1;
4044
    fpsrcop1.d = fpsrcop;
4045
    fptemp1.d = fptemp;
4046
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4047

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

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

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

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

    
4084
void helper_fyl2xp1(void)
4085
{
4086
    CPU86_LDouble fptemp;
4087

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

    
4099
void helper_fsqrt(void)
4100
{
4101
    CPU86_LDouble fptemp;
4102

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

    
4111
void helper_fsincos(void)
4112
{
4113
    CPU86_LDouble fptemp;
4114

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

    
4127
void helper_frndint(void)
4128
{
4129
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4130
}
4131

    
4132
void helper_fscale(void)
4133
{
4134
    ST0 = ldexp (ST0, (int)(ST1));
4135
}
4136

    
4137
void helper_fsin(void)
4138
{
4139
    CPU86_LDouble fptemp;
4140

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

    
4151
void helper_fcos(void)
4152
{
4153
    CPU86_LDouble fptemp;
4154

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

    
4165
void helper_fxam_ST0(void)
4166
{
4167
    CPU86_LDoubleU temp;
4168
    int expdif;
4169

    
4170
    temp.d = ST0;
4171

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

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

    
4197
void helper_fstenv(target_ulong ptr, int data32)
4198
{
4199
    int fpus, fptag, exp, i;
4200
    uint64_t mant;
4201
    CPU86_LDoubleU tmp;
4202

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

    
4247
void helper_fldenv(target_ulong ptr, int data32)
4248
{
4249
    int i, fpus, fptag;
4250

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

    
4269
void helper_fsave(target_ulong ptr, int data32)
4270
{
4271
    CPU86_LDouble tmp;
4272
    int i;
4273

    
4274
    helper_fstenv(ptr, data32);
4275

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

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

    
4297
void helper_frstor(target_ulong ptr, int data32)
4298
{
4299
    CPU86_LDouble tmp;
4300
    int i;
4301

    
4302
    helper_fldenv(ptr, data32);
4303
    ptr += (14 << data32);
4304

    
4305
    for(i = 0;i < 8; i++) {
4306
        tmp = helper_fldt(ptr);
4307
        ST(i) = tmp;
4308
        ptr += 10;
4309
    }
4310
}
4311

    
4312
void helper_fxsave(target_ulong ptr, int data64)
4313
{
4314
    int fpus, fptag, i, nb_xmm_regs;
4315
    CPU86_LDouble tmp;
4316
    target_ulong addr;
4317

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

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

    
4346
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4347
        /* XXX: finish it */
4348
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4349
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4350
        if (env->hflags & HF_CS64_MASK)
4351
            nb_xmm_regs = 16;
4352
        else
4353
            nb_xmm_regs = 8;
4354
        addr = ptr + 0xa0;
4355
        for(i = 0; i < nb_xmm_regs; i++) {
4356
            stq(addr, env->xmm_regs[i].XMM_Q(0));
4357
            stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4358
            addr += 16;
4359
        }
4360
    }
4361
}
4362

    
4363
void helper_fxrstor(target_ulong ptr, int data64)
4364
{
4365
    int i, fpus, fptag, nb_xmm_regs;
4366
    CPU86_LDouble tmp;
4367
    target_ulong addr;
4368

    
4369
    env->fpuc = lduw(ptr);
4370
    fpus = lduw(ptr + 2);
4371
    fptag = lduw(ptr + 4);
4372
    env->fpstt = (fpus >> 11) & 7;
4373
    env->fpus = fpus & ~0x3800;
4374
    fptag ^= 0xff;
4375
    for(i = 0;i < 8; i++) {
4376
        env->fptags[i] = ((fptag >> i) & 1);
4377
    }
4378

    
4379
    addr = ptr + 0x20;
4380
    for(i = 0;i < 8; i++) {
4381
        tmp = helper_fldt(addr);
4382
        ST(i) = tmp;
4383
        addr += 16;
4384
    }
4385

    
4386
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4387
        /* XXX: finish it */
4388
        env->mxcsr = ldl(ptr + 0x18);
4389
        //ldl(ptr + 0x1c);
4390
        if (env->hflags & HF_CS64_MASK)
4391
            nb_xmm_regs = 16;
4392
        else
4393
            nb_xmm_regs = 8;
4394
        addr = ptr + 0xa0;
4395
        for(i = 0; i < nb_xmm_regs; i++) {
4396
            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4397
            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4398
            addr += 16;
4399
        }
4400
    }
4401
}
4402

    
4403
#ifndef USE_X86LDOUBLE
4404

    
4405
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4406
{
4407
    CPU86_LDoubleU temp;
4408
    int e;
4409

    
4410
    temp.d = f;
4411
    /* mantissa */
4412
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4413
    /* exponent + sign */
4414
    e = EXPD(temp) - EXPBIAS + 16383;
4415
    e |= SIGND(temp) >> 16;
4416
    *pexp = e;
4417
}
4418

    
4419
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4420
{
4421
    CPU86_LDoubleU temp;
4422
    int e;
4423
    uint64_t ll;
4424

    
4425
    /* XXX: handle overflow ? */
4426
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4427
    e |= (upper >> 4) & 0x800; /* sign */
4428
    ll = (mant >> 11) & ((1LL << 52) - 1);
4429
#ifdef __arm__
4430
    temp.l.upper = (e << 20) | (ll >> 32);
4431
    temp.l.lower = ll;
4432
#else
4433
    temp.ll = ll | ((uint64_t)e << 52);
4434
#endif
4435
    return temp.d;
4436
}
4437

    
4438
#else
4439

    
4440
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4441
{
4442
    CPU86_LDoubleU temp;
4443

    
4444
    temp.d = f;
4445
    *pmant = temp.l.lower;
4446
    *pexp = temp.l.upper;
4447
}
4448

    
4449
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4450
{
4451
    CPU86_LDoubleU temp;
4452

    
4453
    temp.l.upper = upper;
4454
    temp.l.lower = mant;
4455
    return temp.d;
4456
}
4457
#endif
4458

    
4459
#ifdef TARGET_X86_64
4460

    
4461
//#define DEBUG_MULDIV
4462

    
4463
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4464
{
4465
    *plow += a;
4466
    /* carry test */
4467
    if (*plow < a)
4468
        (*phigh)++;
4469
    *phigh += b;
4470
}
4471

    
4472
static void neg128(uint64_t *plow, uint64_t *phigh)
4473
{
4474
    *plow = ~ *plow;
4475
    *phigh = ~ *phigh;
4476
    add128(plow, phigh, 1, 0);
4477
}
4478

    
4479
/* return TRUE if overflow */
4480
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4481
{
4482
    uint64_t q, r, a1, a0;
4483
    int i, qb, ab;
4484

    
4485
    a0 = *plow;
4486
    a1 = *phigh;
4487
    if (a1 == 0) {
4488
        q = a0 / b;
4489
        r = a0 % b;
4490
        *plow = q;
4491
        *phigh = r;
4492
    } else {
4493
        if (a1 >= b)
4494
            return 1;
4495
        /* XXX: use a better algorithm */
4496
        for(i = 0; i < 64; i++) {
4497
            ab = a1 >> 63;
4498
            a1 = (a1 << 1) | (a0 >> 63);
4499
            if (ab || a1 >= b) {
4500
                a1 -= b;
4501
                qb = 1;
4502
            } else {
4503
                qb = 0;
4504
            }
4505
            a0 = (a0 << 1) | qb;
4506
        }
4507
#if defined(DEBUG_MULDIV)
4508
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4509
               *phigh, *plow, b, a0, a1);
4510
#endif
4511
        *plow = a0;
4512
        *phigh = a1;
4513
    }
4514
    return 0;
4515
}
4516

    
4517
/* return TRUE if overflow */
4518
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4519
{
4520
    int sa, sb;
4521
    sa = ((int64_t)*phigh < 0);
4522
    if (sa)
4523
        neg128(plow, phigh);
4524
    sb = (b < 0);
4525
    if (sb)
4526
        b = -b;
4527
    if (div64(plow, phigh, b) != 0)
4528
        return 1;
4529
    if (sa ^ sb) {
4530
        if (*plow > (1ULL << 63))
4531
            return 1;
4532
        *plow = - *plow;
4533
    } else {
4534
        if (*plow >= (1ULL << 63))
4535
            return 1;
4536
    }
4537
    if (sa)
4538
        *phigh = - *phigh;
4539
    return 0;
4540
}
4541

    
4542
void helper_mulq_EAX_T0(target_ulong t0)
4543
{
4544
    uint64_t r0, r1;
4545

    
4546
    mulu64(&r0, &r1, EAX, t0);
4547
    EAX = r0;
4548
    EDX = r1;
4549
    CC_DST = r0;
4550
    CC_SRC = r1;
4551
}
4552

    
4553
void helper_imulq_EAX_T0(target_ulong t0)
4554
{
4555
    uint64_t r0, r1;
4556

    
4557
    muls64(&r0, &r1, EAX, t0);
4558
    EAX = r0;
4559
    EDX = r1;
4560
    CC_DST = r0;
4561
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4562
}
4563

    
4564
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4565
{
4566
    uint64_t r0, r1;
4567

    
4568
    muls64(&r0, &r1, t0, t1);
4569
    CC_DST = r0;
4570
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4571
    return r0;
4572
}
4573

    
4574
void helper_divq_EAX(target_ulong t0)
4575
{
4576
    uint64_t r0, r1;
4577
    if (t0 == 0) {
4578
        raise_exception(EXCP00_DIVZ);
4579
    }
4580
    r0 = EAX;
4581
    r1 = EDX;
4582
    if (div64(&r0, &r1, t0))
4583
        raise_exception(EXCP00_DIVZ);
4584
    EAX = r0;
4585
    EDX = r1;
4586
}
4587

    
4588
void helper_idivq_EAX(target_ulong t0)
4589
{
4590
    uint64_t r0, r1;
4591
    if (t0 == 0) {
4592
        raise_exception(EXCP00_DIVZ);
4593
    }
4594
    r0 = EAX;
4595
    r1 = EDX;
4596
    if (idiv64(&r0, &r1, t0))
4597
        raise_exception(EXCP00_DIVZ);
4598
    EAX = r0;
4599
    EDX = r1;
4600
}
4601
#endif
4602

    
4603
static void do_hlt(void)
4604
{
4605
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4606
    env->halted = 1;
4607
    env->exception_index = EXCP_HLT;
4608
    cpu_loop_exit();
4609
}
4610

    
4611
void helper_hlt(int next_eip_addend)
4612
{
4613
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4614
    EIP += next_eip_addend;
4615
    
4616
    do_hlt();
4617
}
4618

    
4619
void helper_monitor(target_ulong ptr)
4620
{
4621
    if ((uint32_t)ECX != 0)
4622
        raise_exception(EXCP0D_GPF);
4623
    /* XXX: store address ? */
4624
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4625
}
4626

    
4627
void helper_mwait(int next_eip_addend)
4628
{
4629
    if ((uint32_t)ECX != 0)
4630
        raise_exception(EXCP0D_GPF);
4631
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4632
    EIP += next_eip_addend;
4633

    
4634
    /* XXX: not complete but not completely erroneous */
4635
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4636
        /* more than one CPU: do not sleep because another CPU may
4637
           wake this one */
4638
    } else {
4639
        do_hlt();
4640
    }
4641
}
4642

    
4643
void helper_debug(void)
4644
{
4645
    env->exception_index = EXCP_DEBUG;
4646
    cpu_loop_exit();
4647
}
4648

    
4649
void helper_raise_interrupt(int intno, int next_eip_addend)
4650
{
4651
    raise_interrupt(intno, 1, 0, next_eip_addend);
4652
}
4653

    
4654
void helper_raise_exception(int exception_index)
4655
{
4656
    raise_exception(exception_index);
4657
}
4658

    
4659
void helper_cli(void)
4660
{
4661
    env->eflags &= ~IF_MASK;
4662
}
4663

    
4664
void helper_sti(void)
4665
{
4666
    env->eflags |= IF_MASK;
4667
}
4668

    
4669
#if 0
4670
/* vm86plus instructions */
4671
void helper_cli_vm(void)
4672
{
4673
    env->eflags &= ~VIF_MASK;
4674
}
4675

4676
void helper_sti_vm(void)
4677
{
4678
    env->eflags |= VIF_MASK;
4679
    if (env->eflags & VIP_MASK) {
4680
        raise_exception(EXCP0D_GPF);
4681
    }
4682
}
4683
#endif
4684

    
4685
void helper_set_inhibit_irq(void)
4686
{
4687
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4688
}
4689

    
4690
void helper_reset_inhibit_irq(void)
4691
{
4692
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4693
}
4694

    
4695
void helper_boundw(target_ulong a0, int v)
4696
{
4697
    int low, high;
4698
    low = ldsw(a0);
4699
    high = ldsw(a0 + 2);
4700
    v = (int16_t)v;
4701
    if (v < low || v > high) {
4702
        raise_exception(EXCP05_BOUND);
4703
    }
4704
}
4705

    
4706
void helper_boundl(target_ulong a0, int v)
4707
{
4708
    int low, high;
4709
    low = ldl(a0);
4710
    high = ldl(a0 + 4);
4711
    if (v < low || v > high) {
4712
        raise_exception(EXCP05_BOUND);
4713
    }
4714
}
4715

    
4716
static float approx_rsqrt(float a)
4717
{
4718
    return 1.0 / sqrt(a);
4719
}
4720

    
4721
static float approx_rcp(float a)
4722
{
4723
    return 1.0 / a;
4724
}
4725

    
4726
#if !defined(CONFIG_USER_ONLY)
4727

    
4728
#define MMUSUFFIX _mmu
4729

    
4730
#define SHIFT 0
4731
#include "softmmu_template.h"
4732

    
4733
#define SHIFT 1
4734
#include "softmmu_template.h"
4735

    
4736
#define SHIFT 2
4737
#include "softmmu_template.h"
4738

    
4739
#define SHIFT 3
4740
#include "softmmu_template.h"
4741

    
4742
#endif
4743

    
4744
#if !defined(CONFIG_USER_ONLY)
4745
/* try to fill the TLB and return an exception if error. If retaddr is
4746
   NULL, it means that the function was called in C code (i.e. not
4747
   from generated code or from helper.c) */
4748
/* XXX: fix it to restore all registers */
4749
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4750
{
4751
    TranslationBlock *tb;
4752
    int ret;
4753
    unsigned long pc;
4754
    CPUX86State *saved_env;
4755

    
4756
    /* XXX: hack to restore env in all cases, even if not called from
4757
       generated code */
4758
    saved_env = env;
4759
    env = cpu_single_env;
4760

    
4761
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4762
    if (ret) {
4763
        if (retaddr) {
4764
            /* now we have a real cpu fault */
4765
            pc = (unsigned long)retaddr;
4766
            tb = tb_find_pc(pc);
4767
            if (tb) {
4768
                /* the PC is inside the translated code. It means that we have
4769
                   a virtual CPU fault */
4770
                cpu_restore_state(tb, env, pc, NULL);
4771
            }
4772
        }
4773
        raise_exception_err(env->exception_index, env->error_code);
4774
    }
4775
    env = saved_env;
4776
}
4777
#endif
4778

    
4779
/* Secure Virtual Machine helpers */
4780

    
4781
#if defined(CONFIG_USER_ONLY)
4782

    
4783
void helper_vmrun(int aflag, int next_eip_addend)
4784
{ 
4785
}
4786
void helper_vmmcall(void) 
4787
{ 
4788
}
4789
void helper_vmload(int aflag)
4790
{ 
4791
}
4792
void helper_vmsave(int aflag)
4793
{ 
4794
}
4795
void helper_stgi(void)
4796
{
4797
}
4798
void helper_clgi(void)
4799
{
4800
}
4801
void helper_skinit(void) 
4802
{ 
4803
}
4804
void helper_invlpga(int aflag)
4805
{ 
4806
}
4807
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4808
{ 
4809
}
4810
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4811
{
4812
}
4813

    
4814
void helper_svm_check_io(uint32_t port, uint32_t param, 
4815
                         uint32_t next_eip_addend)
4816
{
4817
}
4818
#else
4819

    
4820
static inline void svm_save_seg(target_phys_addr_t addr,
4821
                                const SegmentCache *sc)
4822
{
4823
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4824
             sc->selector);
4825
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4826
             sc->base);
4827
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4828
             sc->limit);
4829
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4830
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4831
}
4832
                                
4833
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4834
{
4835
    unsigned int flags;
4836

    
4837
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4838
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4839
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4840
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4841
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4842
}
4843

    
4844
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4845
                                      CPUState *env, int seg_reg)
4846
{
4847
    SegmentCache sc1, *sc = &sc1;
4848
    svm_load_seg(addr, sc);
4849
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4850
                           sc->base, sc->limit, sc->flags);
4851
}
4852

    
4853
void helper_vmrun(int aflag, int next_eip_addend)
4854
{
4855
    target_ulong addr;
4856
    uint32_t event_inj;
4857
    uint32_t int_ctl;
4858

    
4859
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4860

    
4861
    if (aflag == 2)
4862
        addr = EAX;
4863
    else
4864
        addr = (uint32_t)EAX;
4865

    
4866
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
4867

    
4868
    env->vm_vmcb = addr;
4869

    
4870
    /* save the current CPU state in the hsave page */
4871
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4872
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4873

    
4874
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4875
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4876

    
4877
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4878
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4879
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4880
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4881
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4882
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4883

    
4884
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4885
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4886

    
4887
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4888
                  &env->segs[R_ES]);
4889
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4890
                 &env->segs[R_CS]);
4891
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4892
                 &env->segs[R_SS]);
4893
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4894
                 &env->segs[R_DS]);
4895

    
4896
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
4897
             EIP + next_eip_addend);
4898
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4899
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4900

    
4901
    /* load the interception bitmaps so we do not need to access the
4902
       vmcb in svm mode */
4903
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4904
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4905
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4906
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4907
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4908
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4909

    
4910
    /* enable intercepts */
4911
    env->hflags |= HF_SVMI_MASK;
4912

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

    
4915
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4916
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4917

    
4918
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4919
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4920

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

    
4924
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4925
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4926
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4927
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4928
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4929
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4930
    if (int_ctl & V_INTR_MASKING_MASK) {
4931
        env->v_tpr = int_ctl & V_TPR_MASK;
4932
        env->hflags2 |= HF2_VINTR_MASK;
4933
        if (env->eflags & IF_MASK)
4934
            env->hflags2 |= HF2_HIF_MASK;
4935
    }
4936

    
4937
    cpu_load_efer(env, 
4938
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4939
    env->eflags = 0;
4940
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4941
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4942
    CC_OP = CC_OP_EFLAGS;
4943

    
4944
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4945
                       env, R_ES);
4946
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4947
                       env, R_CS);
4948
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4949
                       env, R_SS);
4950
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4951
                       env, R_DS);
4952

    
4953
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4954
    env->eip = EIP;
4955
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4956
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4957
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4958
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4959
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4960

    
4961
    /* FIXME: guest state consistency checks */
4962

    
4963
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4964
        case TLB_CONTROL_DO_NOTHING:
4965
            break;
4966
        case TLB_CONTROL_FLUSH_ALL_ASID:
4967
            /* FIXME: this is not 100% correct but should work for now */
4968
            tlb_flush(env, 1);
4969
        break;
4970
    }
4971

    
4972
    env->hflags2 |= HF2_GIF_MASK;
4973

    
4974
    if (int_ctl & V_IRQ_MASK) {
4975
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4976
    }
4977

    
4978
    /* maybe we need to inject an event */
4979
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4980
    if (event_inj & SVM_EVTINJ_VALID) {
4981
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4982
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4983
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4984
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4985

    
4986
        qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
4987
        /* FIXME: need to implement valid_err */
4988
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4989
        case SVM_EVTINJ_TYPE_INTR:
4990
                env->exception_index = vector;
4991
                env->error_code = event_inj_err;
4992
                env->exception_is_int = 0;
4993
                env->exception_next_eip = -1;
4994
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
4995
                /* XXX: is it always correct ? */
4996
                do_interrupt(vector, 0, 0, 0, 1);
4997
                break;
4998
        case SVM_EVTINJ_TYPE_NMI:
4999
                env->exception_index = EXCP02_NMI;
5000
                env->error_code = event_inj_err;
5001
                env->exception_is_int = 0;
5002
                env->exception_next_eip = EIP;
5003
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
5004
                cpu_loop_exit();
5005
                break;
5006
        case SVM_EVTINJ_TYPE_EXEPT:
5007
                env->exception_index = vector;
5008
                env->error_code = event_inj_err;
5009
                env->exception_is_int = 0;
5010
                env->exception_next_eip = -1;
5011
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
5012
                cpu_loop_exit();
5013
                break;
5014
        case SVM_EVTINJ_TYPE_SOFT:
5015
                env->exception_index = vector;
5016
                env->error_code = event_inj_err;
5017
                env->exception_is_int = 1;
5018
                env->exception_next_eip = EIP;
5019
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
5020
                cpu_loop_exit();
5021
                break;
5022
        }
5023
        qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index, env->error_code);
5024
    }
5025
}
5026

    
5027
void helper_vmmcall(void)
5028
{
5029
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
5030
    raise_exception(EXCP06_ILLOP);
5031
}
5032

    
5033
void helper_vmload(int aflag)
5034
{
5035
    target_ulong addr;
5036
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
5037

    
5038
    if (aflag == 2)
5039
        addr = EAX;
5040
    else
5041
        addr = (uint32_t)EAX;
5042

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

    
5047
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
5048
                       env, R_FS);
5049
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
5050
                       env, R_GS);
5051
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
5052
                 &env->tr);
5053
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
5054
                 &env->ldt);
5055

    
5056
#ifdef TARGET_X86_64
5057
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
5058
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
5059
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
5060
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
5061
#endif
5062
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
5063
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
5064
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
5065
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
5066
}
5067

    
5068
void helper_vmsave(int aflag)
5069
{
5070
    target_ulong addr;
5071
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5072

    
5073
    if (aflag == 2)
5074
        addr = EAX;
5075
    else
5076
        addr = (uint32_t)EAX;
5077

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

    
5082
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5083
                 &env->segs[R_FS]);
5084
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5085
                 &env->segs[R_GS]);
5086
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5087
                 &env->tr);
5088
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5089
                 &env->ldt);
5090

    
5091
#ifdef TARGET_X86_64
5092
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
5093
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
5094
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
5095
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
5096
#endif
5097
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
5098
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
5099
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
5100
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
5101
}
5102

    
5103
void helper_stgi(void)
5104
{
5105
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5106
    env->hflags2 |= HF2_GIF_MASK;
5107
}
5108

    
5109
void helper_clgi(void)
5110
{
5111
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5112
    env->hflags2 &= ~HF2_GIF_MASK;
5113
}
5114

    
5115
void helper_skinit(void)
5116
{
5117
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5118
    /* XXX: not implemented */
5119
    raise_exception(EXCP06_ILLOP);
5120
}
5121

    
5122
void helper_invlpga(int aflag)
5123
{
5124
    target_ulong addr;
5125
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5126
    
5127
    if (aflag == 2)
5128
        addr = EAX;
5129
    else
5130
        addr = (uint32_t)EAX;
5131

    
5132
    /* XXX: could use the ASID to see if it is needed to do the
5133
       flush */
5134
    tlb_flush_page(env, addr);
5135
}
5136

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

    
5205
void helper_svm_check_io(uint32_t port, uint32_t param, 
5206
                         uint32_t next_eip_addend)
5207
{
5208
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5209
        /* FIXME: this should be read in at vmrun (faster this way?) */
5210
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5211
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5212
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5213
            /* next EIP */
5214
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5215
                     env->eip + next_eip_addend);
5216
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5217
        }
5218
    }
5219
}
5220

    
5221
/* Note: currently only 32 bits of exit_code are used */
5222
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5223
{
5224
    uint32_t int_ctl;
5225

    
5226
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5227
                exit_code, exit_info_1,
5228
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5229
                EIP);
5230

    
5231
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5232
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5233
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5234
    } else {
5235
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5236
    }
5237

    
5238
    /* Save the VM state in the vmcb */
5239
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5240
                 &env->segs[R_ES]);
5241
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5242
                 &env->segs[R_CS]);
5243
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5244
                 &env->segs[R_SS]);
5245
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5246
                 &env->segs[R_DS]);
5247

    
5248
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5249
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5250

    
5251
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5252
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5253

    
5254
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5255
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5256
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5257
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5258
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5259

    
5260
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5261
    int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
5262
    int_ctl |= env->v_tpr & V_TPR_MASK;
5263
    if (env->interrupt_request & CPU_INTERRUPT_VIRQ)
5264
        int_ctl |= V_IRQ_MASK;
5265
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5266

    
5267
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5268
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5269
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5270
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5271
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5272
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5273
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5274

    
5275
    /* Reload the host state from vm_hsave */
5276
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5277
    env->hflags &= ~HF_SVMI_MASK;
5278
    env->intercept = 0;
5279
    env->intercept_exceptions = 0;
5280
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5281
    env->tsc_offset = 0;
5282

    
5283
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5284
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5285

    
5286
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5287
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5288

    
5289
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5290
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5291
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5292
    /* we need to set the efer after the crs so the hidden flags get
5293
       set properly */
5294
    cpu_load_efer(env, 
5295
                  ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
5296
    env->eflags = 0;
5297
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5298
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5299
    CC_OP = CC_OP_EFLAGS;
5300

    
5301
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5302
                       env, R_ES);
5303
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5304
                       env, R_CS);
5305
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5306
                       env, R_SS);
5307
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5308
                       env, R_DS);
5309

    
5310
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5311
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5312
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5313

    
5314
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5315
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5316

    
5317
    /* other setups */
5318
    cpu_x86_set_cpl(env, 0);
5319
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5320
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5321

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

    
5325
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5326

    
5327
    /* Clears the TSC_OFFSET inside the processor. */
5328

    
5329
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5330
       from the page table indicated the host's CR3. If the PDPEs contain
5331
       illegal state, the processor causes a shutdown. */
5332

    
5333
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5334
    env->cr[0] |= CR0_PE_MASK;
5335
    env->eflags &= ~VM_MASK;
5336

    
5337
    /* Disables all breakpoints in the host DR7 register. */
5338

    
5339
    /* Checks the reloaded host state for consistency. */
5340

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

    
5345
    /* remove any pending exception */
5346
    env->exception_index = -1;
5347
    env->error_code = 0;
5348
    env->old_exception = -1;
5349

    
5350
    cpu_loop_exit();
5351
}
5352

    
5353
#endif
5354

    
5355
/* MMX/SSE */
5356
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5357
void helper_enter_mmx(void)
5358
{
5359
    env->fpstt = 0;
5360
    *(uint32_t *)(env->fptags) = 0;
5361
    *(uint32_t *)(env->fptags + 4) = 0;
5362
}
5363

    
5364
void helper_emms(void)
5365
{
5366
    /* set to empty state */
5367
    *(uint32_t *)(env->fptags) = 0x01010101;
5368
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5369
}
5370

    
5371
/* XXX: suppress */
5372
void helper_movq(void *d, void *s)
5373
{
5374
    *(uint64_t *)d = *(uint64_t *)s;
5375
}
5376

    
5377
#define SHIFT 0
5378
#include "ops_sse.h"
5379

    
5380
#define SHIFT 1
5381
#include "ops_sse.h"
5382

    
5383
#define SHIFT 0
5384
#include "helper_template.h"
5385
#undef SHIFT
5386

    
5387
#define SHIFT 1
5388
#include "helper_template.h"
5389
#undef SHIFT
5390

    
5391
#define SHIFT 2
5392
#include "helper_template.h"
5393
#undef SHIFT
5394

    
5395
#ifdef TARGET_X86_64
5396

    
5397
#define SHIFT 3
5398
#include "helper_template.h"
5399
#undef SHIFT
5400

    
5401
#endif
5402

    
5403
/* bit operations */
5404
target_ulong helper_bsf(target_ulong t0)
5405
{
5406
    int count;
5407
    target_ulong res;
5408

    
5409
    res = t0;
5410
    count = 0;
5411
    while ((res & 1) == 0) {
5412
        count++;
5413
        res >>= 1;
5414
    }
5415
    return count;
5416
}
5417

    
5418
target_ulong helper_bsr(target_ulong t0)
5419
{
5420
    int count;
5421
    target_ulong res, mask;
5422
    
5423
    res = t0;
5424
    count = TARGET_LONG_BITS - 1;
5425
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5426
    while ((res & mask) == 0) {
5427
        count--;
5428
        res <<= 1;
5429
    }
5430
    return count;
5431
}
5432

    
5433

    
5434
static int compute_all_eflags(void)
5435
{
5436
    return CC_SRC;
5437
}
5438

    
5439
static int compute_c_eflags(void)
5440
{
5441
    return CC_SRC & CC_C;
5442
}
5443

    
5444
uint32_t helper_cc_compute_all(int op)
5445
{
5446
    switch (op) {
5447
    default: /* should never happen */ return 0;
5448

    
5449
    case CC_OP_EFLAGS: return compute_all_eflags();
5450

    
5451
    case CC_OP_MULB: return compute_all_mulb();
5452
    case CC_OP_MULW: return compute_all_mulw();
5453
    case CC_OP_MULL: return compute_all_mull();
5454

    
5455
    case CC_OP_ADDB: return compute_all_addb();
5456
    case CC_OP_ADDW: return compute_all_addw();
5457
    case CC_OP_ADDL: return compute_all_addl();
5458

    
5459
    case CC_OP_ADCB: return compute_all_adcb();
5460
    case CC_OP_ADCW: return compute_all_adcw();
5461
    case CC_OP_ADCL: return compute_all_adcl();
5462

    
5463
    case CC_OP_SUBB: return compute_all_subb();
5464
    case CC_OP_SUBW: return compute_all_subw();
5465
    case CC_OP_SUBL: return compute_all_subl();
5466

    
5467
    case CC_OP_SBBB: return compute_all_sbbb();
5468
    case CC_OP_SBBW: return compute_all_sbbw();
5469
    case CC_OP_SBBL: return compute_all_sbbl();
5470

    
5471
    case CC_OP_LOGICB: return compute_all_logicb();
5472
    case CC_OP_LOGICW: return compute_all_logicw();
5473
    case CC_OP_LOGICL: return compute_all_logicl();
5474

    
5475
    case CC_OP_INCB: return compute_all_incb();
5476
    case CC_OP_INCW: return compute_all_incw();
5477
    case CC_OP_INCL: return compute_all_incl();
5478

    
5479
    case CC_OP_DECB: return compute_all_decb();
5480
    case CC_OP_DECW: return compute_all_decw();
5481
    case CC_OP_DECL: return compute_all_decl();
5482

    
5483
    case CC_OP_SHLB: return compute_all_shlb();
5484
    case CC_OP_SHLW: return compute_all_shlw();
5485
    case CC_OP_SHLL: return compute_all_shll();
5486

    
5487
    case CC_OP_SARB: return compute_all_sarb();
5488
    case CC_OP_SARW: return compute_all_sarw();
5489
    case CC_OP_SARL: return compute_all_sarl();
5490

    
5491
#ifdef TARGET_X86_64
5492
    case CC_OP_MULQ: return compute_all_mulq();
5493

    
5494
    case CC_OP_ADDQ: return compute_all_addq();
5495

    
5496
    case CC_OP_ADCQ: return compute_all_adcq();
5497

    
5498
    case CC_OP_SUBQ: return compute_all_subq();
5499

    
5500
    case CC_OP_SBBQ: return compute_all_sbbq();
5501

    
5502
    case CC_OP_LOGICQ: return compute_all_logicq();
5503

    
5504
    case CC_OP_INCQ: return compute_all_incq();
5505

    
5506
    case CC_OP_DECQ: return compute_all_decq();
5507

    
5508
    case CC_OP_SHLQ: return compute_all_shlq();
5509

    
5510
    case CC_OP_SARQ: return compute_all_sarq();
5511
#endif
5512
    }
5513
}
5514

    
5515
uint32_t helper_cc_compute_c(int op)
5516
{
5517
    switch (op) {
5518
    default: /* should never happen */ return 0;
5519

    
5520
    case CC_OP_EFLAGS: return compute_c_eflags();
5521

    
5522
    case CC_OP_MULB: return compute_c_mull();
5523
    case CC_OP_MULW: return compute_c_mull();
5524
    case CC_OP_MULL: return compute_c_mull();
5525

    
5526
    case CC_OP_ADDB: return compute_c_addb();
5527
    case CC_OP_ADDW: return compute_c_addw();
5528
    case CC_OP_ADDL: return compute_c_addl();
5529

    
5530
    case CC_OP_ADCB: return compute_c_adcb();
5531
    case CC_OP_ADCW: return compute_c_adcw();
5532
    case CC_OP_ADCL: return compute_c_adcl();
5533

    
5534
    case CC_OP_SUBB: return compute_c_subb();
5535
    case CC_OP_SUBW: return compute_c_subw();
5536
    case CC_OP_SUBL: return compute_c_subl();
5537

    
5538
    case CC_OP_SBBB: return compute_c_sbbb();
5539
    case CC_OP_SBBW: return compute_c_sbbw();
5540
    case CC_OP_SBBL: return compute_c_sbbl();
5541

    
5542
    case CC_OP_LOGICB: return compute_c_logicb();
5543
    case CC_OP_LOGICW: return compute_c_logicw();
5544
    case CC_OP_LOGICL: return compute_c_logicl();
5545

    
5546
    case CC_OP_INCB: return compute_c_incl();
5547
    case CC_OP_INCW: return compute_c_incl();
5548
    case CC_OP_INCL: return compute_c_incl();
5549

    
5550
    case CC_OP_DECB: return compute_c_incl();
5551
    case CC_OP_DECW: return compute_c_incl();
5552
    case CC_OP_DECL: return compute_c_incl();
5553

    
5554
    case CC_OP_SHLB: return compute_c_shlb();
5555
    case CC_OP_SHLW: return compute_c_shlw();
5556
    case CC_OP_SHLL: return compute_c_shll();
5557

    
5558
    case CC_OP_SARB: return compute_c_sarl();
5559
    case CC_OP_SARW: return compute_c_sarl();
5560
    case CC_OP_SARL: return compute_c_sarl();
5561

    
5562
#ifdef TARGET_X86_64
5563
    case CC_OP_MULQ: return compute_c_mull();
5564

    
5565
    case CC_OP_ADDQ: return compute_c_addq();
5566

    
5567
    case CC_OP_ADCQ: return compute_c_adcq();
5568

    
5569
    case CC_OP_SUBQ: return compute_c_subq();
5570

    
5571
    case CC_OP_SBBQ: return compute_c_sbbq();
5572

    
5573
    case CC_OP_LOGICQ: return compute_c_logicq();
5574

    
5575
    case CC_OP_INCQ: return compute_c_incl();
5576

    
5577
    case CC_OP_DECQ: return compute_c_incl();
5578

    
5579
    case CC_OP_SHLQ: return compute_c_shlq();
5580

    
5581
    case CC_OP_SARQ: return compute_c_sarl();
5582
#endif
5583
    }
5584
}