Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 09d85fb8

History | View | Annotate | Download (158.6 kB)

1
/*
2
 *  i386 helpers
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#define CPU_NO_GLOBAL_REGS
20
#include "exec.h"
21
#include "exec-all.h"
22
#include "host-utils.h"
23

    
24
//#define DEBUG_PCALL
25

    
26

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

    
36

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

    
45
static const uint8_t parity_table[256] = {
46
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
47
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
49
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
50
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
52
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
53
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
54
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
55
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
56
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
57
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
58
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
59
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
60
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
61
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
62
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
63
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
64
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
65
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
66
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
67
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
68
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
69
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
70
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
71
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
72
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
73
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
74
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
75
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
76
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
77
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
78
};
79

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

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

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

    
107
/* broken thread support */
108

    
109
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
110

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
564
target_ulong helper_inb(uint32_t port)
565
{
566
    return cpu_inb(port);
567
}
568

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

    
574
target_ulong helper_inw(uint32_t port)
575
{
576
    return cpu_inw(port);
577
}
578

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

    
584
target_ulong helper_inl(uint32_t port)
585
{
586
    return cpu_inl(port);
587
}
588

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

    
597
static int exeption_has_error_code(int intno)
598
{
599
        switch(intno) {
600
        case 8:
601
        case 10:
602
        case 11:
603
        case 12:
604
        case 13:
605
        case 14:
606
        case 17:
607
            return 1;
608
        }
609
        return 0;
610
}
611

    
612
#ifdef TARGET_X86_64
613
#define SET_ESP(val, sp_mask)\
614
do {\
615
    if ((sp_mask) == 0xffff)\
616
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
617
    else if ((sp_mask) == 0xffffffffLL)\
618
        ESP = (uint32_t)(val);\
619
    else\
620
        ESP = (val);\
621
} while (0)
622
#else
623
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
624
#endif
625

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

    
630
/* XXX: add a is_user flag to have proper security support */
631
#define PUSHW(ssp, sp, sp_mask, val)\
632
{\
633
    sp -= 2;\
634
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
635
}
636

    
637
#define PUSHL(ssp, sp, sp_mask, val)\
638
{\
639
    sp -= 4;\
640
    stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
641
}
642

    
643
#define POPW(ssp, sp, sp_mask, val)\
644
{\
645
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
646
    sp += 2;\
647
}
648

    
649
#define POPL(ssp, sp, sp_mask, val)\
650
{\
651
    val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
652
    sp += 4;\
653
}
654

    
655
/* protected mode interrupt */
656
static void do_interrupt_protected(int intno, int is_int, int error_code,
657
                                   unsigned int next_eip, int is_hw)
658
{
659
    SegmentCache *dt;
660
    target_ulong ptr, ssp;
661
    int type, dpl, selector, ss_dpl, cpl;
662
    int has_error_code, new_stack, shift;
663
    uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
664
    uint32_t old_eip, sp_mask;
665

    
666
    has_error_code = 0;
667
    if (!is_int && !is_hw)
668
        has_error_code = exeption_has_error_code(intno);
669
    if (is_int)
670
        old_eip = next_eip;
671
    else
672
        old_eip = env->eip;
673

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

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

    
776
    shift = type >> 3;
777

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

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

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

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

    
849
#ifdef TARGET_X86_64
850

    
851
#define PUSHQ(sp, val)\
852
{\
853
    sp -= 8;\
854
    stq_kernel(sp, (val));\
855
}
856

    
857
#define POPQ(sp, val)\
858
{\
859
    val = ldq_kernel(sp);\
860
    sp += 8;\
861
}
862

    
863
static inline target_ulong get_rsp_from_tss(int level)
864
{
865
    int index;
866

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

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

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

    
891
    has_error_code = 0;
892
    if (!is_int && !is_hw)
893
        has_error_code = exeption_has_error_code(intno);
894
    if (is_int)
895
        old_eip = next_eip;
896
    else
897
        old_eip = env->eip;
898

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

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

    
967
    PUSHQ(esp, env->segs[R_SS].selector);
968
    PUSHQ(esp, ESP);
969
    PUSHQ(esp, compute_eflags());
970
    PUSHQ(esp, env->segs[R_CS].selector);
971
    PUSHQ(esp, old_eip);
972
    if (has_error_code) {
973
        PUSHQ(esp, error_code);
974
    }
975

    
976
    if (new_stack) {
977
        ss = 0 | dpl;
978
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
979
    }
980
    ESP = esp;
981

    
982
    selector = (selector & ~3) | dpl;
983
    cpu_x86_load_seg_cache(env, R_CS, selector,
984
                   get_seg_base(e1, e2),
985
                   get_seg_limit(e1, e2),
986
                   e2);
987
    cpu_x86_set_cpl(env, dpl);
988
    env->eip = offset;
989

    
990
    /* interrupt gate clear IF mask */
991
    if ((type & 1) == 0) {
992
        env->eflags &= ~IF_MASK;
993
    }
994
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
995
}
996
#endif
997

    
998
#ifdef TARGET_X86_64
999
#if defined(CONFIG_USER_ONLY)
1000
void helper_syscall(int next_eip_addend)
1001
{
1002
    env->exception_index = EXCP_SYSCALL;
1003
    env->exception_next_eip = env->eip + next_eip_addend;
1004
    cpu_loop_exit();
1005
}
1006
#else
1007
void helper_syscall(int next_eip_addend)
1008
{
1009
    int selector;
1010

    
1011
    if (!(env->efer & MSR_EFER_SCE)) {
1012
        raise_exception_err(EXCP06_ILLOP, 0);
1013
    }
1014
    selector = (env->star >> 32) & 0xffff;
1015
    if (env->hflags & HF_LMA_MASK) {
1016
        int code64;
1017

    
1018
        ECX = env->eip + next_eip_addend;
1019
        env->regs[11] = compute_eflags();
1020

    
1021
        code64 = env->hflags & HF_CS64_MASK;
1022

    
1023
        cpu_x86_set_cpl(env, 0);
1024
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1025
                           0, 0xffffffff,
1026
                               DESC_G_MASK | DESC_P_MASK |
1027
                               DESC_S_MASK |
1028
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1029
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1030
                               0, 0xffffffff,
1031
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1032
                               DESC_S_MASK |
1033
                               DESC_W_MASK | DESC_A_MASK);
1034
        env->eflags &= ~env->fmask;
1035
        load_eflags(env->eflags, 0);
1036
        if (code64)
1037
            env->eip = env->lstar;
1038
        else
1039
            env->eip = env->cstar;
1040
    } else {
1041
        ECX = (uint32_t)(env->eip + next_eip_addend);
1042

    
1043
        cpu_x86_set_cpl(env, 0);
1044
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1045
                           0, 0xffffffff,
1046
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1047
                               DESC_S_MASK |
1048
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1049
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1050
                               0, 0xffffffff,
1051
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1052
                               DESC_S_MASK |
1053
                               DESC_W_MASK | DESC_A_MASK);
1054
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1055
        env->eip = (uint32_t)env->star;
1056
    }
1057
}
1058
#endif
1059
#endif
1060

    
1061
#ifdef TARGET_X86_64
1062
void helper_sysret(int dflag)
1063
{
1064
    int cpl, selector;
1065

    
1066
    if (!(env->efer & MSR_EFER_SCE)) {
1067
        raise_exception_err(EXCP06_ILLOP, 0);
1068
    }
1069
    cpl = env->hflags & HF_CPL_MASK;
1070
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1071
        raise_exception_err(EXCP0D_GPF, 0);
1072
    }
1073
    selector = (env->star >> 48) & 0xffff;
1074
    if (env->hflags & HF_LMA_MASK) {
1075
        if (dflag == 2) {
1076
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1077
                                   0, 0xffffffff,
1078
                                   DESC_G_MASK | DESC_P_MASK |
1079
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1080
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1081
                                   DESC_L_MASK);
1082
            env->eip = ECX;
1083
        } else {
1084
            cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1085
                                   0, 0xffffffff,
1086
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1087
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1088
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1089
            env->eip = (uint32_t)ECX;
1090
        }
1091
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1092
                               0, 0xffffffff,
1093
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1094
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1095
                               DESC_W_MASK | DESC_A_MASK);
1096
        load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1097
                    IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1098
        cpu_x86_set_cpl(env, 3);
1099
    } else {
1100
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1101
                               0, 0xffffffff,
1102
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1103
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1104
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1105
        env->eip = (uint32_t)ECX;
1106
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1107
                               0, 0xffffffff,
1108
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1109
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1110
                               DESC_W_MASK | DESC_A_MASK);
1111
        env->eflags |= IF_MASK;
1112
        cpu_x86_set_cpl(env, 3);
1113
    }
1114
}
1115
#endif
1116

    
1117
/* real mode interrupt */
1118
static void do_interrupt_real(int intno, int is_int, int error_code,
1119
                              unsigned int next_eip)
1120
{
1121
    SegmentCache *dt;
1122
    target_ulong ptr, ssp;
1123
    int selector;
1124
    uint32_t offset, esp;
1125
    uint32_t old_cs, old_eip;
1126

    
1127
    /* real mode (simpler !) */
1128
    dt = &env->idt;
1129
    if (intno * 4 + 3 > dt->limit)
1130
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1131
    ptr = dt->base + intno * 4;
1132
    offset = lduw_kernel(ptr);
1133
    selector = lduw_kernel(ptr + 2);
1134
    esp = ESP;
1135
    ssp = env->segs[R_SS].base;
1136
    if (is_int)
1137
        old_eip = next_eip;
1138
    else
1139
        old_eip = env->eip;
1140
    old_cs = env->segs[R_CS].selector;
1141
    /* XXX: use SS segment size ? */
1142
    PUSHW(ssp, esp, 0xffff, compute_eflags());
1143
    PUSHW(ssp, esp, 0xffff, old_cs);
1144
    PUSHW(ssp, esp, 0xffff, old_eip);
1145

    
1146
    /* update processor state */
1147
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1148
    env->eip = offset;
1149
    env->segs[R_CS].selector = selector;
1150
    env->segs[R_CS].base = (selector << 4);
1151
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1152
}
1153

    
1154
/* fake user mode interrupt */
1155
void do_interrupt_user(int intno, int is_int, int error_code,
1156
                       target_ulong next_eip)
1157
{
1158
    SegmentCache *dt;
1159
    target_ulong ptr;
1160
    int dpl, cpl, shift;
1161
    uint32_t e2;
1162

    
1163
    dt = &env->idt;
1164
    if (env->hflags & HF_LMA_MASK) {
1165
        shift = 4;
1166
    } else {
1167
        shift = 3;
1168
    }
1169
    ptr = dt->base + (intno << shift);
1170
    e2 = ldl_kernel(ptr + 4);
1171

    
1172
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1173
    cpl = env->hflags & HF_CPL_MASK;
1174
    /* check privilege if software int */
1175
    if (is_int && dpl < cpl)
1176
        raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1177

    
1178
    /* Since we emulate only user space, we cannot do more than
1179
       exiting the emulation with the suitable exception and error
1180
       code */
1181
    if (is_int)
1182
        EIP = next_eip;
1183
}
1184

    
1185
#if !defined(CONFIG_USER_ONLY)
1186
static void handle_even_inj(int intno, int is_int, int error_code,
1187
                int is_hw, int rm)
1188
{
1189
    uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1190
    if (!(event_inj & SVM_EVTINJ_VALID)) {
1191
            int type;
1192
            if (is_int)
1193
                    type = SVM_EVTINJ_TYPE_SOFT;
1194
            else
1195
                    type = SVM_EVTINJ_TYPE_EXEPT;
1196
            event_inj = intno | type | SVM_EVTINJ_VALID;
1197
            if (!rm && exeption_has_error_code(intno)) {
1198
                    event_inj |= SVM_EVTINJ_VALID_ERR;
1199
                    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err), error_code);
1200
            }
1201
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj);
1202
    }
1203
}
1204
#endif
1205

    
1206
/*
1207
 * Begin execution of an interruption. is_int is TRUE if coming from
1208
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1209
 * instruction. It is only relevant if is_int is TRUE.
1210
 */
1211
void do_interrupt(int intno, int is_int, int error_code,
1212
                  target_ulong next_eip, int is_hw)
1213
{
1214
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
1215
        if ((env->cr[0] & CR0_PE_MASK)) {
1216
            static int count;
1217
            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,
1218
                    count, intno, error_code, is_int,
1219
                    env->hflags & HF_CPL_MASK,
1220
                    env->segs[R_CS].selector, EIP,
1221
                    (int)env->segs[R_CS].base + EIP,
1222
                    env->segs[R_SS].selector, ESP);
1223
            if (intno == 0x0e) {
1224
                qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
1225
            } else {
1226
                qemu_log(" EAX=" TARGET_FMT_lx, EAX);
1227
            }
1228
            qemu_log("\n");
1229
            log_cpu_state(env, X86_DUMP_CCOP);
1230
#if 0
1231
            {
1232
                int i;
1233
                uint8_t *ptr;
1234
                qemu_log("       code=");
1235
                ptr = env->segs[R_CS].base + env->eip;
1236
                for(i = 0; i < 16; i++) {
1237
                    qemu_log(" %02x", ldub(ptr + i));
1238
                }
1239
                qemu_log("\n");
1240
            }
1241
#endif
1242
            count++;
1243
        }
1244
    }
1245
    if (env->cr[0] & CR0_PE_MASK) {
1246
#if !defined(CONFIG_USER_ONLY)
1247
        if (env->hflags & HF_SVMI_MASK)
1248
            handle_even_inj(intno, is_int, error_code, is_hw, 0);
1249
#endif
1250
#ifdef TARGET_X86_64
1251
        if (env->hflags & HF_LMA_MASK) {
1252
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1253
        } else
1254
#endif
1255
        {
1256
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1257
        }
1258
    } else {
1259
#if !defined(CONFIG_USER_ONLY)
1260
        if (env->hflags & HF_SVMI_MASK)
1261
            handle_even_inj(intno, is_int, error_code, is_hw, 1);
1262
#endif
1263
        do_interrupt_real(intno, is_int, error_code, next_eip);
1264
    }
1265

    
1266
#if !defined(CONFIG_USER_ONLY)
1267
    if (env->hflags & HF_SVMI_MASK) {
1268
            uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1269
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
1270
    }
1271
#endif
1272
}
1273

    
1274
/* This should come from sysemu.h - if we could include it here... */
1275
void qemu_system_reset_request(void);
1276

    
1277
/*
1278
 * Check nested exceptions and change to double or triple fault if
1279
 * needed. It should only be called, if this is not an interrupt.
1280
 * Returns the new exception number.
1281
 */
1282
static int check_exception(int intno, int *error_code)
1283
{
1284
    int first_contributory = env->old_exception == 0 ||
1285
                              (env->old_exception >= 10 &&
1286
                               env->old_exception <= 13);
1287
    int second_contributory = intno == 0 ||
1288
                               (intno >= 10 && intno <= 13);
1289

    
1290
    qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
1291
                env->old_exception, intno);
1292

    
1293
#if !defined(CONFIG_USER_ONLY)
1294
    if (env->old_exception == EXCP08_DBLE) {
1295
        if (env->hflags & HF_SVMI_MASK)
1296
            helper_vmexit(SVM_EXIT_SHUTDOWN, 0); /* does not return */
1297

    
1298
        qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1299

    
1300
        qemu_system_reset_request();
1301
        return EXCP_HLT;
1302
    }
1303
#endif
1304

    
1305
    if ((first_contributory && second_contributory)
1306
        || (env->old_exception == EXCP0E_PAGE &&
1307
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1308
        intno = EXCP08_DBLE;
1309
        *error_code = 0;
1310
    }
1311

    
1312
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1313
        (intno == EXCP08_DBLE))
1314
        env->old_exception = intno;
1315

    
1316
    return intno;
1317
}
1318

    
1319
/*
1320
 * Signal an interruption. It is executed in the main CPU loop.
1321
 * is_int is TRUE if coming from the int instruction. next_eip is the
1322
 * EIP value AFTER the interrupt instruction. It is only relevant if
1323
 * is_int is TRUE.
1324
 */
1325
static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
1326
                                          int next_eip_addend)
1327
{
1328
    if (!is_int) {
1329
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1330
        intno = check_exception(intno, &error_code);
1331
    } else {
1332
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1333
    }
1334

    
1335
    env->exception_index = intno;
1336
    env->error_code = error_code;
1337
    env->exception_is_int = is_int;
1338
    env->exception_next_eip = env->eip + next_eip_addend;
1339
    cpu_loop_exit();
1340
}
1341

    
1342
/* shortcuts to generate exceptions */
1343

    
1344
void raise_exception_err(int exception_index, int error_code)
1345
{
1346
    raise_interrupt(exception_index, 0, error_code, 0);
1347
}
1348

    
1349
void raise_exception(int exception_index)
1350
{
1351
    raise_interrupt(exception_index, 0, 0, 0);
1352
}
1353

    
1354
/* SMM support */
1355

    
1356
#if defined(CONFIG_USER_ONLY)
1357

    
1358
void do_smm_enter(void)
1359
{
1360
}
1361

    
1362
void helper_rsm(void)
1363
{
1364
}
1365

    
1366
#else
1367

    
1368
#ifdef TARGET_X86_64
1369
#define SMM_REVISION_ID 0x00020064
1370
#else
1371
#define SMM_REVISION_ID 0x00020000
1372
#endif
1373

    
1374
void do_smm_enter(void)
1375
{
1376
    target_ulong sm_state;
1377
    SegmentCache *dt;
1378
    int i, offset;
1379

    
1380
    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
1381
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1382

    
1383
    env->hflags |= HF_SMM_MASK;
1384
    cpu_smm_update(env);
1385

    
1386
    sm_state = env->smbase + 0x8000;
1387

    
1388
#ifdef TARGET_X86_64
1389
    for(i = 0; i < 6; i++) {
1390
        dt = &env->segs[i];
1391
        offset = 0x7e00 + i * 16;
1392
        stw_phys(sm_state + offset, dt->selector);
1393
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1394
        stl_phys(sm_state + offset + 4, dt->limit);
1395
        stq_phys(sm_state + offset + 8, dt->base);
1396
    }
1397

    
1398
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1399
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1400

    
1401
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1402
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1403
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1404
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1405

    
1406
    stq_phys(sm_state + 0x7e88, env->idt.base);
1407
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1408

    
1409
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1410
    stq_phys(sm_state + 0x7e98, env->tr.base);
1411
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1412
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1413

    
1414
    stq_phys(sm_state + 0x7ed0, env->efer);
1415

    
1416
    stq_phys(sm_state + 0x7ff8, EAX);
1417
    stq_phys(sm_state + 0x7ff0, ECX);
1418
    stq_phys(sm_state + 0x7fe8, EDX);
1419
    stq_phys(sm_state + 0x7fe0, EBX);
1420
    stq_phys(sm_state + 0x7fd8, ESP);
1421
    stq_phys(sm_state + 0x7fd0, EBP);
1422
    stq_phys(sm_state + 0x7fc8, ESI);
1423
    stq_phys(sm_state + 0x7fc0, EDI);
1424
    for(i = 8; i < 16; i++)
1425
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1426
    stq_phys(sm_state + 0x7f78, env->eip);
1427
    stl_phys(sm_state + 0x7f70, compute_eflags());
1428
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1429
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1430

    
1431
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1432
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1433
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1434

    
1435
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1436
    stl_phys(sm_state + 0x7f00, env->smbase);
1437
#else
1438
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1439
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1440
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1441
    stl_phys(sm_state + 0x7ff0, env->eip);
1442
    stl_phys(sm_state + 0x7fec, EDI);
1443
    stl_phys(sm_state + 0x7fe8, ESI);
1444
    stl_phys(sm_state + 0x7fe4, EBP);
1445
    stl_phys(sm_state + 0x7fe0, ESP);
1446
    stl_phys(sm_state + 0x7fdc, EBX);
1447
    stl_phys(sm_state + 0x7fd8, EDX);
1448
    stl_phys(sm_state + 0x7fd4, ECX);
1449
    stl_phys(sm_state + 0x7fd0, EAX);
1450
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1451
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1452

    
1453
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1454
    stl_phys(sm_state + 0x7f64, env->tr.base);
1455
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1456
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1457

    
1458
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1459
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1460
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1461
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1462

    
1463
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1464
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1465

    
1466
    stl_phys(sm_state + 0x7f58, env->idt.base);
1467
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1468

    
1469
    for(i = 0; i < 6; i++) {
1470
        dt = &env->segs[i];
1471
        if (i < 3)
1472
            offset = 0x7f84 + i * 12;
1473
        else
1474
            offset = 0x7f2c + (i - 3) * 12;
1475
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1476
        stl_phys(sm_state + offset + 8, dt->base);
1477
        stl_phys(sm_state + offset + 4, dt->limit);
1478
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1479
    }
1480
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1481

    
1482
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1483
    stl_phys(sm_state + 0x7ef8, env->smbase);
1484
#endif
1485
    /* init SMM cpu state */
1486

    
1487
#ifdef TARGET_X86_64
1488
    cpu_load_efer(env, 0);
1489
#endif
1490
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1491
    env->eip = 0x00008000;
1492
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1493
                           0xffffffff, 0);
1494
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1495
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1496
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1497
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1498
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1499

    
1500
    cpu_x86_update_cr0(env,
1501
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1502
    cpu_x86_update_cr4(env, 0);
1503
    env->dr[7] = 0x00000400;
1504
    CC_OP = CC_OP_EFLAGS;
1505
}
1506

    
1507
void helper_rsm(void)
1508
{
1509
    target_ulong sm_state;
1510
    int i, offset;
1511
    uint32_t val;
1512

    
1513
    sm_state = env->smbase + 0x8000;
1514
#ifdef TARGET_X86_64
1515
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1516

    
1517
    for(i = 0; i < 6; i++) {
1518
        offset = 0x7e00 + i * 16;
1519
        cpu_x86_load_seg_cache(env, i,
1520
                               lduw_phys(sm_state + offset),
1521
                               ldq_phys(sm_state + offset + 8),
1522
                               ldl_phys(sm_state + offset + 4),
1523
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1524
    }
1525

    
1526
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1527
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1528

    
1529
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1530
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1531
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1532
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1533

    
1534
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1535
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1536

    
1537
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1538
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1539
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1540
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1541

    
1542
    EAX = ldq_phys(sm_state + 0x7ff8);
1543
    ECX = ldq_phys(sm_state + 0x7ff0);
1544
    EDX = ldq_phys(sm_state + 0x7fe8);
1545
    EBX = ldq_phys(sm_state + 0x7fe0);
1546
    ESP = ldq_phys(sm_state + 0x7fd8);
1547
    EBP = ldq_phys(sm_state + 0x7fd0);
1548
    ESI = ldq_phys(sm_state + 0x7fc8);
1549
    EDI = ldq_phys(sm_state + 0x7fc0);
1550
    for(i = 8; i < 16; i++)
1551
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1552
    env->eip = ldq_phys(sm_state + 0x7f78);
1553
    load_eflags(ldl_phys(sm_state + 0x7f70),
1554
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1555
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1556
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1557

    
1558
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1559
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1560
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1561

    
1562
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1563
    if (val & 0x20000) {
1564
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1565
    }
1566
#else
1567
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1568
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1569
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1570
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1571
    env->eip = ldl_phys(sm_state + 0x7ff0);
1572
    EDI = ldl_phys(sm_state + 0x7fec);
1573
    ESI = ldl_phys(sm_state + 0x7fe8);
1574
    EBP = ldl_phys(sm_state + 0x7fe4);
1575
    ESP = ldl_phys(sm_state + 0x7fe0);
1576
    EBX = ldl_phys(sm_state + 0x7fdc);
1577
    EDX = ldl_phys(sm_state + 0x7fd8);
1578
    ECX = ldl_phys(sm_state + 0x7fd4);
1579
    EAX = ldl_phys(sm_state + 0x7fd0);
1580
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1581
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1582

    
1583
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1584
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1585
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1586
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1587

    
1588
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1589
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1590
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1591
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1592

    
1593
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1594
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1595

    
1596
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1597
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1598

    
1599
    for(i = 0; i < 6; i++) {
1600
        if (i < 3)
1601
            offset = 0x7f84 + i * 12;
1602
        else
1603
            offset = 0x7f2c + (i - 3) * 12;
1604
        cpu_x86_load_seg_cache(env, i,
1605
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1606
                               ldl_phys(sm_state + offset + 8),
1607
                               ldl_phys(sm_state + offset + 4),
1608
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1609
    }
1610
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1611

    
1612
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1613
    if (val & 0x20000) {
1614
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1615
    }
1616
#endif
1617
    CC_OP = CC_OP_EFLAGS;
1618
    env->hflags &= ~HF_SMM_MASK;
1619
    cpu_smm_update(env);
1620

    
1621
    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
1622
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1623
}
1624

    
1625
#endif /* !CONFIG_USER_ONLY */
1626

    
1627

    
1628
/* division, flags are undefined */
1629

    
1630
void helper_divb_AL(target_ulong t0)
1631
{
1632
    unsigned int num, den, q, r;
1633

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

    
1647
void helper_idivb_AL(target_ulong t0)
1648
{
1649
    int num, den, q, r;
1650

    
1651
    num = (int16_t)EAX;
1652
    den = (int8_t)t0;
1653
    if (den == 0) {
1654
        raise_exception(EXCP00_DIVZ);
1655
    }
1656
    q = (num / den);
1657
    if (q != (int8_t)q)
1658
        raise_exception(EXCP00_DIVZ);
1659
    q &= 0xff;
1660
    r = (num % den) & 0xff;
1661
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1662
}
1663

    
1664
void helper_divw_AX(target_ulong t0)
1665
{
1666
    unsigned int num, den, q, r;
1667

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

    
1682
void helper_idivw_AX(target_ulong t0)
1683
{
1684
    int num, den, q, r;
1685

    
1686
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1687
    den = (int16_t)t0;
1688
    if (den == 0) {
1689
        raise_exception(EXCP00_DIVZ);
1690
    }
1691
    q = (num / den);
1692
    if (q != (int16_t)q)
1693
        raise_exception(EXCP00_DIVZ);
1694
    q &= 0xffff;
1695
    r = (num % den) & 0xffff;
1696
    EAX = (EAX & ~0xffff) | q;
1697
    EDX = (EDX & ~0xffff) | r;
1698
}
1699

    
1700
void helper_divl_EAX(target_ulong t0)
1701
{
1702
    unsigned int den, r;
1703
    uint64_t num, q;
1704

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

    
1718
void helper_idivl_EAX(target_ulong t0)
1719
{
1720
    int den, r;
1721
    int64_t num, q;
1722

    
1723
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1724
    den = t0;
1725
    if (den == 0) {
1726
        raise_exception(EXCP00_DIVZ);
1727
    }
1728
    q = (num / den);
1729
    r = (num % den);
1730
    if (q != (int32_t)q)
1731
        raise_exception(EXCP00_DIVZ);
1732
    EAX = (uint32_t)q;
1733
    EDX = (uint32_t)r;
1734
}
1735

    
1736
/* bcd */
1737

    
1738
/* XXX: exception */
1739
void helper_aam(int base)
1740
{
1741
    int al, ah;
1742
    al = EAX & 0xff;
1743
    ah = al / base;
1744
    al = al % base;
1745
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1746
    CC_DST = al;
1747
}
1748

    
1749
void helper_aad(int base)
1750
{
1751
    int al, ah;
1752
    al = EAX & 0xff;
1753
    ah = (EAX >> 8) & 0xff;
1754
    al = ((ah * base) + al) & 0xff;
1755
    EAX = (EAX & ~0xffff) | al;
1756
    CC_DST = al;
1757
}
1758

    
1759
void helper_aaa(void)
1760
{
1761
    int icarry;
1762
    int al, ah, af;
1763
    int eflags;
1764

    
1765
    eflags = helper_cc_compute_all(CC_OP);
1766
    af = eflags & CC_A;
1767
    al = EAX & 0xff;
1768
    ah = (EAX >> 8) & 0xff;
1769

    
1770
    icarry = (al > 0xf9);
1771
    if (((al & 0x0f) > 9 ) || af) {
1772
        al = (al + 6) & 0x0f;
1773
        ah = (ah + 1 + icarry) & 0xff;
1774
        eflags |= CC_C | CC_A;
1775
    } else {
1776
        eflags &= ~(CC_C | CC_A);
1777
        al &= 0x0f;
1778
    }
1779
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1780
    CC_SRC = eflags;
1781
}
1782

    
1783
void helper_aas(void)
1784
{
1785
    int icarry;
1786
    int al, ah, af;
1787
    int eflags;
1788

    
1789
    eflags = helper_cc_compute_all(CC_OP);
1790
    af = eflags & CC_A;
1791
    al = EAX & 0xff;
1792
    ah = (EAX >> 8) & 0xff;
1793

    
1794
    icarry = (al < 6);
1795
    if (((al & 0x0f) > 9 ) || af) {
1796
        al = (al - 6) & 0x0f;
1797
        ah = (ah - 1 - icarry) & 0xff;
1798
        eflags |= CC_C | CC_A;
1799
    } else {
1800
        eflags &= ~(CC_C | CC_A);
1801
        al &= 0x0f;
1802
    }
1803
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1804
    CC_SRC = eflags;
1805
}
1806

    
1807
void helper_daa(void)
1808
{
1809
    int al, af, cf;
1810
    int eflags;
1811

    
1812
    eflags = helper_cc_compute_all(CC_OP);
1813
    cf = eflags & CC_C;
1814
    af = eflags & CC_A;
1815
    al = EAX & 0xff;
1816

    
1817
    eflags = 0;
1818
    if (((al & 0x0f) > 9 ) || af) {
1819
        al = (al + 6) & 0xff;
1820
        eflags |= CC_A;
1821
    }
1822
    if ((al > 0x9f) || cf) {
1823
        al = (al + 0x60) & 0xff;
1824
        eflags |= CC_C;
1825
    }
1826
    EAX = (EAX & ~0xff) | al;
1827
    /* well, speed is not an issue here, so we compute the flags by hand */
1828
    eflags |= (al == 0) << 6; /* zf */
1829
    eflags |= parity_table[al]; /* pf */
1830
    eflags |= (al & 0x80); /* sf */
1831
    CC_SRC = eflags;
1832
}
1833

    
1834
void helper_das(void)
1835
{
1836
    int al, al1, af, cf;
1837
    int eflags;
1838

    
1839
    eflags = helper_cc_compute_all(CC_OP);
1840
    cf = eflags & CC_C;
1841
    af = eflags & CC_A;
1842
    al = EAX & 0xff;
1843

    
1844
    eflags = 0;
1845
    al1 = al;
1846
    if (((al & 0x0f) > 9 ) || af) {
1847
        eflags |= CC_A;
1848
        if (al < 6 || cf)
1849
            eflags |= CC_C;
1850
        al = (al - 6) & 0xff;
1851
    }
1852
    if ((al1 > 0x99) || cf) {
1853
        al = (al - 0x60) & 0xff;
1854
        eflags |= CC_C;
1855
    }
1856
    EAX = (EAX & ~0xff) | al;
1857
    /* well, speed is not an issue here, so we compute the flags by hand */
1858
    eflags |= (al == 0) << 6; /* zf */
1859
    eflags |= parity_table[al]; /* pf */
1860
    eflags |= (al & 0x80); /* sf */
1861
    CC_SRC = eflags;
1862
}
1863

    
1864
void helper_into(int next_eip_addend)
1865
{
1866
    int eflags;
1867
    eflags = helper_cc_compute_all(CC_OP);
1868
    if (eflags & CC_O) {
1869
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1870
    }
1871
}
1872

    
1873
void helper_cmpxchg8b(target_ulong a0)
1874
{
1875
    uint64_t d;
1876
    int eflags;
1877

    
1878
    eflags = helper_cc_compute_all(CC_OP);
1879
    d = ldq(a0);
1880
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1881
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1882
        eflags |= CC_Z;
1883
    } else {
1884
        /* always do the store */
1885
        stq(a0, d); 
1886
        EDX = (uint32_t)(d >> 32);
1887
        EAX = (uint32_t)d;
1888
        eflags &= ~CC_Z;
1889
    }
1890
    CC_SRC = eflags;
1891
}
1892

    
1893
#ifdef TARGET_X86_64
1894
void helper_cmpxchg16b(target_ulong a0)
1895
{
1896
    uint64_t d0, d1;
1897
    int eflags;
1898

    
1899
    if ((a0 & 0xf) != 0)
1900
        raise_exception(EXCP0D_GPF);
1901
    eflags = helper_cc_compute_all(CC_OP);
1902
    d0 = ldq(a0);
1903
    d1 = ldq(a0 + 8);
1904
    if (d0 == EAX && d1 == EDX) {
1905
        stq(a0, EBX);
1906
        stq(a0 + 8, ECX);
1907
        eflags |= CC_Z;
1908
    } else {
1909
        /* always do the store */
1910
        stq(a0, d0); 
1911
        stq(a0 + 8, d1); 
1912
        EDX = d1;
1913
        EAX = d0;
1914
        eflags &= ~CC_Z;
1915
    }
1916
    CC_SRC = eflags;
1917
}
1918
#endif
1919

    
1920
void helper_single_step(void)
1921
{
1922
#ifndef CONFIG_USER_ONLY
1923
    check_hw_breakpoints(env, 1);
1924
    env->dr[6] |= DR6_BS;
1925
#endif
1926
    raise_exception(EXCP01_DB);
1927
}
1928

    
1929
void helper_cpuid(void)
1930
{
1931
    uint32_t eax, ebx, ecx, edx;
1932

    
1933
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1934

    
1935
    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
1936
    EAX = eax;
1937
    EBX = ebx;
1938
    ECX = ecx;
1939
    EDX = edx;
1940
}
1941

    
1942
void helper_enter_level(int level, int data32, target_ulong t1)
1943
{
1944
    target_ulong ssp;
1945
    uint32_t esp_mask, esp, ebp;
1946

    
1947
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1948
    ssp = env->segs[R_SS].base;
1949
    ebp = EBP;
1950
    esp = ESP;
1951
    if (data32) {
1952
        /* 32 bit */
1953
        esp -= 4;
1954
        while (--level) {
1955
            esp -= 4;
1956
            ebp -= 4;
1957
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1958
        }
1959
        esp -= 4;
1960
        stl(ssp + (esp & esp_mask), t1);
1961
    } else {
1962
        /* 16 bit */
1963
        esp -= 2;
1964
        while (--level) {
1965
            esp -= 2;
1966
            ebp -= 2;
1967
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1968
        }
1969
        esp -= 2;
1970
        stw(ssp + (esp & esp_mask), t1);
1971
    }
1972
}
1973

    
1974
#ifdef TARGET_X86_64
1975
void helper_enter64_level(int level, int data64, target_ulong t1)
1976
{
1977
    target_ulong esp, ebp;
1978
    ebp = EBP;
1979
    esp = ESP;
1980

    
1981
    if (data64) {
1982
        /* 64 bit */
1983
        esp -= 8;
1984
        while (--level) {
1985
            esp -= 8;
1986
            ebp -= 8;
1987
            stq(esp, ldq(ebp));
1988
        }
1989
        esp -= 8;
1990
        stq(esp, t1);
1991
    } else {
1992
        /* 16 bit */
1993
        esp -= 2;
1994
        while (--level) {
1995
            esp -= 2;
1996
            ebp -= 2;
1997
            stw(esp, lduw(ebp));
1998
        }
1999
        esp -= 2;
2000
        stw(esp, t1);
2001
    }
2002
}
2003
#endif
2004

    
2005
void helper_lldt(int selector)
2006
{
2007
    SegmentCache *dt;
2008
    uint32_t e1, e2;
2009
    int index, entry_limit;
2010
    target_ulong ptr;
2011

    
2012
    selector &= 0xffff;
2013
    if ((selector & 0xfffc) == 0) {
2014
        /* XXX: NULL selector case: invalid LDT */
2015
        env->ldt.base = 0;
2016
        env->ldt.limit = 0;
2017
    } else {
2018
        if (selector & 0x4)
2019
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2020
        dt = &env->gdt;
2021
        index = selector & ~7;
2022
#ifdef TARGET_X86_64
2023
        if (env->hflags & HF_LMA_MASK)
2024
            entry_limit = 15;
2025
        else
2026
#endif
2027
            entry_limit = 7;
2028
        if ((index + entry_limit) > dt->limit)
2029
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2030
        ptr = dt->base + index;
2031
        e1 = ldl_kernel(ptr);
2032
        e2 = ldl_kernel(ptr + 4);
2033
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2034
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2035
        if (!(e2 & DESC_P_MASK))
2036
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2037
#ifdef TARGET_X86_64
2038
        if (env->hflags & HF_LMA_MASK) {
2039
            uint32_t e3;
2040
            e3 = ldl_kernel(ptr + 8);
2041
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2042
            env->ldt.base |= (target_ulong)e3 << 32;
2043
        } else
2044
#endif
2045
        {
2046
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2047
        }
2048
    }
2049
    env->ldt.selector = selector;
2050
}
2051

    
2052
void helper_ltr(int selector)
2053
{
2054
    SegmentCache *dt;
2055
    uint32_t e1, e2;
2056
    int index, type, entry_limit;
2057
    target_ulong ptr;
2058

    
2059
    selector &= 0xffff;
2060
    if ((selector & 0xfffc) == 0) {
2061
        /* NULL selector case: invalid TR */
2062
        env->tr.base = 0;
2063
        env->tr.limit = 0;
2064
        env->tr.flags = 0;
2065
    } else {
2066
        if (selector & 0x4)
2067
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2068
        dt = &env->gdt;
2069
        index = selector & ~7;
2070
#ifdef TARGET_X86_64
2071
        if (env->hflags & HF_LMA_MASK)
2072
            entry_limit = 15;
2073
        else
2074
#endif
2075
            entry_limit = 7;
2076
        if ((index + entry_limit) > dt->limit)
2077
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2078
        ptr = dt->base + index;
2079
        e1 = ldl_kernel(ptr);
2080
        e2 = ldl_kernel(ptr + 4);
2081
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2082
        if ((e2 & DESC_S_MASK) ||
2083
            (type != 1 && type != 9))
2084
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2085
        if (!(e2 & DESC_P_MASK))
2086
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2087
#ifdef TARGET_X86_64
2088
        if (env->hflags & HF_LMA_MASK) {
2089
            uint32_t e3, e4;
2090
            e3 = ldl_kernel(ptr + 8);
2091
            e4 = ldl_kernel(ptr + 12);
2092
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2093
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2094
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2095
            env->tr.base |= (target_ulong)e3 << 32;
2096
        } else
2097
#endif
2098
        {
2099
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2100
        }
2101
        e2 |= DESC_TSS_BUSY_MASK;
2102
        stl_kernel(ptr + 4, e2);
2103
    }
2104
    env->tr.selector = selector;
2105
}
2106

    
2107
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2108
void helper_load_seg(int seg_reg, int selector)
2109
{
2110
    uint32_t e1, e2;
2111
    int cpl, dpl, rpl;
2112
    SegmentCache *dt;
2113
    int index;
2114
    target_ulong ptr;
2115

    
2116
    selector &= 0xffff;
2117
    cpl = env->hflags & HF_CPL_MASK;
2118
    if ((selector & 0xfffc) == 0) {
2119
        /* null selector case */
2120
        if (seg_reg == R_SS
2121
#ifdef TARGET_X86_64
2122
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2123
#endif
2124
            )
2125
            raise_exception_err(EXCP0D_GPF, 0);
2126
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2127
    } else {
2128

    
2129
        if (selector & 0x4)
2130
            dt = &env->ldt;
2131
        else
2132
            dt = &env->gdt;
2133
        index = selector & ~7;
2134
        if ((index + 7) > dt->limit)
2135
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2136
        ptr = dt->base + index;
2137
        e1 = ldl_kernel(ptr);
2138
        e2 = ldl_kernel(ptr + 4);
2139

    
2140
        if (!(e2 & DESC_S_MASK))
2141
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2142
        rpl = selector & 3;
2143
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2144
        if (seg_reg == R_SS) {
2145
            /* must be writable segment */
2146
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2147
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2148
            if (rpl != cpl || dpl != cpl)
2149
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2150
        } else {
2151
            /* must be readable segment */
2152
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2153
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2154

    
2155
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2156
                /* if not conforming code, test rights */
2157
                if (dpl < cpl || dpl < rpl)
2158
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2159
            }
2160
        }
2161

    
2162
        if (!(e2 & DESC_P_MASK)) {
2163
            if (seg_reg == R_SS)
2164
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2165
            else
2166
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2167
        }
2168

    
2169
        /* set the access bit if not already set */
2170
        if (!(e2 & DESC_A_MASK)) {
2171
            e2 |= DESC_A_MASK;
2172
            stl_kernel(ptr + 4, e2);
2173
        }
2174

    
2175
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2176
                       get_seg_base(e1, e2),
2177
                       get_seg_limit(e1, e2),
2178
                       e2);
2179
#if 0
2180
        qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2181
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2182
#endif
2183
    }
2184
}
2185

    
2186
/* protected mode jump */
2187
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2188
                           int next_eip_addend)
2189
{
2190
    int gate_cs, type;
2191
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2192
    target_ulong next_eip;
2193

    
2194
    if ((new_cs & 0xfffc) == 0)
2195
        raise_exception_err(EXCP0D_GPF, 0);
2196
    if (load_segment(&e1, &e2, new_cs) != 0)
2197
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2198
    cpl = env->hflags & HF_CPL_MASK;
2199
    if (e2 & DESC_S_MASK) {
2200
        if (!(e2 & DESC_CS_MASK))
2201
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2202
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2203
        if (e2 & DESC_C_MASK) {
2204
            /* conforming code segment */
2205
            if (dpl > cpl)
2206
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2207
        } else {
2208
            /* non conforming code segment */
2209
            rpl = new_cs & 3;
2210
            if (rpl > cpl)
2211
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2212
            if (dpl != cpl)
2213
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2214
        }
2215
        if (!(e2 & DESC_P_MASK))
2216
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2217
        limit = get_seg_limit(e1, e2);
2218
        if (new_eip > limit &&
2219
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2220
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2221
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2222
                       get_seg_base(e1, e2), limit, e2);
2223
        EIP = new_eip;
2224
    } else {
2225
        /* jump to call or task gate */
2226
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2227
        rpl = new_cs & 3;
2228
        cpl = env->hflags & HF_CPL_MASK;
2229
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2230
        switch(type) {
2231
        case 1: /* 286 TSS */
2232
        case 9: /* 386 TSS */
2233
        case 5: /* task gate */
2234
            if (dpl < cpl || dpl < rpl)
2235
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2236
            next_eip = env->eip + next_eip_addend;
2237
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2238
            CC_OP = CC_OP_EFLAGS;
2239
            break;
2240
        case 4: /* 286 call gate */
2241
        case 12: /* 386 call gate */
2242
            if ((dpl < cpl) || (dpl < rpl))
2243
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2244
            if (!(e2 & DESC_P_MASK))
2245
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2246
            gate_cs = e1 >> 16;
2247
            new_eip = (e1 & 0xffff);
2248
            if (type == 12)
2249
                new_eip |= (e2 & 0xffff0000);
2250
            if (load_segment(&e1, &e2, gate_cs) != 0)
2251
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2252
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2253
            /* must be code segment */
2254
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2255
                 (DESC_S_MASK | DESC_CS_MASK)))
2256
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2257
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2258
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2259
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2260
            if (!(e2 & DESC_P_MASK))
2261
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2262
            limit = get_seg_limit(e1, e2);
2263
            if (new_eip > limit)
2264
                raise_exception_err(EXCP0D_GPF, 0);
2265
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2266
                                   get_seg_base(e1, e2), limit, e2);
2267
            EIP = new_eip;
2268
            break;
2269
        default:
2270
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2271
            break;
2272
        }
2273
    }
2274
}
2275

    
2276
/* real mode call */
2277
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2278
                       int shift, int next_eip)
2279
{
2280
    int new_eip;
2281
    uint32_t esp, esp_mask;
2282
    target_ulong ssp;
2283

    
2284
    new_eip = new_eip1;
2285
    esp = ESP;
2286
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2287
    ssp = env->segs[R_SS].base;
2288
    if (shift) {
2289
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2290
        PUSHL(ssp, esp, esp_mask, next_eip);
2291
    } else {
2292
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2293
        PUSHW(ssp, esp, esp_mask, next_eip);
2294
    }
2295

    
2296
    SET_ESP(esp, esp_mask);
2297
    env->eip = new_eip;
2298
    env->segs[R_CS].selector = new_cs;
2299
    env->segs[R_CS].base = (new_cs << 4);
2300
}
2301

    
2302
/* protected mode call */
2303
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2304
                            int shift, int next_eip_addend)
2305
{
2306
    int new_stack, i;
2307
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2308
    uint32_t ss = 0, ss_e1 = 0, ss_e2 = 0, sp, type, ss_dpl, sp_mask;
2309
    uint32_t val, limit, old_sp_mask;
2310
    target_ulong ssp, old_ssp, next_eip;
2311

    
2312
    next_eip = env->eip + next_eip_addend;
2313
    LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
2314
    LOG_PCALL_STATE(env);
2315
    if ((new_cs & 0xfffc) == 0)
2316
        raise_exception_err(EXCP0D_GPF, 0);
2317
    if (load_segment(&e1, &e2, new_cs) != 0)
2318
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2319
    cpl = env->hflags & HF_CPL_MASK;
2320
    LOG_PCALL("desc=%08x:%08x\n", e1, e2);
2321
    if (e2 & DESC_S_MASK) {
2322
        if (!(e2 & DESC_CS_MASK))
2323
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2324
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2325
        if (e2 & DESC_C_MASK) {
2326
            /* conforming code segment */
2327
            if (dpl > cpl)
2328
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2329
        } else {
2330
            /* non conforming code segment */
2331
            rpl = new_cs & 3;
2332
            if (rpl > cpl)
2333
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2334
            if (dpl != cpl)
2335
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2336
        }
2337
        if (!(e2 & DESC_P_MASK))
2338
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2339

    
2340
#ifdef TARGET_X86_64
2341
        /* XXX: check 16/32 bit cases in long mode */
2342
        if (shift == 2) {
2343
            target_ulong rsp;
2344
            /* 64 bit case */
2345
            rsp = ESP;
2346
            PUSHQ(rsp, env->segs[R_CS].selector);
2347
            PUSHQ(rsp, next_eip);
2348
            /* from this point, not restartable */
2349
            ESP = rsp;
2350
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2351
                                   get_seg_base(e1, e2),
2352
                                   get_seg_limit(e1, e2), e2);
2353
            EIP = new_eip;
2354
        } else
2355
#endif
2356
        {
2357
            sp = ESP;
2358
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2359
            ssp = env->segs[R_SS].base;
2360
            if (shift) {
2361
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2362
                PUSHL(ssp, sp, sp_mask, next_eip);
2363
            } else {
2364
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2365
                PUSHW(ssp, sp, sp_mask, next_eip);
2366
            }
2367

    
2368
            limit = get_seg_limit(e1, e2);
2369
            if (new_eip > limit)
2370
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2371
            /* from this point, not restartable */
2372
            SET_ESP(sp, sp_mask);
2373
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2374
                                   get_seg_base(e1, e2), limit, e2);
2375
            EIP = new_eip;
2376
        }
2377
    } else {
2378
        /* check gate type */
2379
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2380
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2381
        rpl = new_cs & 3;
2382
        switch(type) {
2383
        case 1: /* available 286 TSS */
2384
        case 9: /* available 386 TSS */
2385
        case 5: /* task gate */
2386
            if (dpl < cpl || dpl < rpl)
2387
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2388
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2389
            CC_OP = CC_OP_EFLAGS;
2390
            return;
2391
        case 4: /* 286 call gate */
2392
        case 12: /* 386 call gate */
2393
            break;
2394
        default:
2395
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2396
            break;
2397
        }
2398
        shift = type >> 3;
2399

    
2400
        if (dpl < cpl || dpl < rpl)
2401
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2402
        /* check valid bit */
2403
        if (!(e2 & DESC_P_MASK))
2404
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2405
        selector = e1 >> 16;
2406
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2407
        param_count = e2 & 0x1f;
2408
        if ((selector & 0xfffc) == 0)
2409
            raise_exception_err(EXCP0D_GPF, 0);
2410

    
2411
        if (load_segment(&e1, &e2, selector) != 0)
2412
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2413
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2414
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2415
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2416
        if (dpl > cpl)
2417
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2418
        if (!(e2 & DESC_P_MASK))
2419
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2420

    
2421
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2422
            /* to inner privilege */
2423
            get_ss_esp_from_tss(&ss, &sp, dpl);
2424
            LOG_PCALL("new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2425
                        ss, sp, param_count, ESP);
2426
            if ((ss & 0xfffc) == 0)
2427
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2428
            if ((ss & 3) != dpl)
2429
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2430
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2431
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2432
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2433
            if (ss_dpl != dpl)
2434
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2435
            if (!(ss_e2 & DESC_S_MASK) ||
2436
                (ss_e2 & DESC_CS_MASK) ||
2437
                !(ss_e2 & DESC_W_MASK))
2438
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2439
            if (!(ss_e2 & DESC_P_MASK))
2440
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2441

    
2442
            //            push_size = ((param_count * 2) + 8) << shift;
2443

    
2444
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2445
            old_ssp = env->segs[R_SS].base;
2446

    
2447
            sp_mask = get_sp_mask(ss_e2);
2448
            ssp = get_seg_base(ss_e1, ss_e2);
2449
            if (shift) {
2450
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2451
                PUSHL(ssp, sp, sp_mask, ESP);
2452
                for(i = param_count - 1; i >= 0; i--) {
2453
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2454
                    PUSHL(ssp, sp, sp_mask, val);
2455
                }
2456
            } else {
2457
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2458
                PUSHW(ssp, sp, sp_mask, ESP);
2459
                for(i = param_count - 1; i >= 0; i--) {
2460
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2461
                    PUSHW(ssp, sp, sp_mask, val);
2462
                }
2463
            }
2464
            new_stack = 1;
2465
        } else {
2466
            /* to same privilege */
2467
            sp = ESP;
2468
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2469
            ssp = env->segs[R_SS].base;
2470
            //            push_size = (4 << shift);
2471
            new_stack = 0;
2472
        }
2473

    
2474
        if (shift) {
2475
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2476
            PUSHL(ssp, sp, sp_mask, next_eip);
2477
        } else {
2478
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2479
            PUSHW(ssp, sp, sp_mask, next_eip);
2480
        }
2481

    
2482
        /* from this point, not restartable */
2483

    
2484
        if (new_stack) {
2485
            ss = (ss & ~3) | dpl;
2486
            cpu_x86_load_seg_cache(env, R_SS, ss,
2487
                                   ssp,
2488
                                   get_seg_limit(ss_e1, ss_e2),
2489
                                   ss_e2);
2490
        }
2491

    
2492
        selector = (selector & ~3) | dpl;
2493
        cpu_x86_load_seg_cache(env, R_CS, selector,
2494
                       get_seg_base(e1, e2),
2495
                       get_seg_limit(e1, e2),
2496
                       e2);
2497
        cpu_x86_set_cpl(env, dpl);
2498
        SET_ESP(sp, sp_mask);
2499
        EIP = offset;
2500
    }
2501
}
2502

    
2503
/* real and vm86 mode iret */
2504
void helper_iret_real(int shift)
2505
{
2506
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2507
    target_ulong ssp;
2508
    int eflags_mask;
2509

    
2510
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2511
    sp = ESP;
2512
    ssp = env->segs[R_SS].base;
2513
    if (shift == 1) {
2514
        /* 32 bits */
2515
        POPL(ssp, sp, sp_mask, new_eip);
2516
        POPL(ssp, sp, sp_mask, new_cs);
2517
        new_cs &= 0xffff;
2518
        POPL(ssp, sp, sp_mask, new_eflags);
2519
    } else {
2520
        /* 16 bits */
2521
        POPW(ssp, sp, sp_mask, new_eip);
2522
        POPW(ssp, sp, sp_mask, new_cs);
2523
        POPW(ssp, sp, sp_mask, new_eflags);
2524
    }
2525
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2526
    env->segs[R_CS].selector = new_cs;
2527
    env->segs[R_CS].base = (new_cs << 4);
2528
    env->eip = new_eip;
2529
    if (env->eflags & VM_MASK)
2530
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2531
    else
2532
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2533
    if (shift == 0)
2534
        eflags_mask &= 0xffff;
2535
    load_eflags(new_eflags, eflags_mask);
2536
    env->hflags2 &= ~HF2_NMI_MASK;
2537
}
2538

    
2539
static inline void validate_seg(int seg_reg, int cpl)
2540
{
2541
    int dpl;
2542
    uint32_t e2;
2543

    
2544
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2545
       they may still contain a valid base. I would be interested to
2546
       know how a real x86_64 CPU behaves */
2547
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2548
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2549
        return;
2550

    
2551
    e2 = env->segs[seg_reg].flags;
2552
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2553
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2554
        /* data or non conforming code segment */
2555
        if (dpl < cpl) {
2556
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2557
        }
2558
    }
2559
}
2560

    
2561
/* protected mode iret */
2562
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2563
{
2564
    uint32_t new_cs, new_eflags, new_ss;
2565
    uint32_t new_es, new_ds, new_fs, new_gs;
2566
    uint32_t e1, e2, ss_e1, ss_e2;
2567
    int cpl, dpl, rpl, eflags_mask, iopl;
2568
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2569

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

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

    
2696
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2697
                       get_seg_base(e1, e2),
2698
                       get_seg_limit(e1, e2),
2699
                       e2);
2700
        cpu_x86_set_cpl(env, rpl);
2701
        sp = new_esp;
2702
#ifdef TARGET_X86_64
2703
        if (env->hflags & HF_CS64_MASK)
2704
            sp_mask = -1;
2705
        else
2706
#endif
2707
            sp_mask = get_sp_mask(ss_e2);
2708

    
2709
        /* validate data segments */
2710
        validate_seg(R_ES, rpl);
2711
        validate_seg(R_DS, rpl);
2712
        validate_seg(R_FS, rpl);
2713
        validate_seg(R_GS, rpl);
2714

    
2715
        sp += addend;
2716
    }
2717
    SET_ESP(sp, sp_mask);
2718
    env->eip = new_eip;
2719
    if (is_iret) {
2720
        /* NOTE: 'cpl' is the _old_ CPL */
2721
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2722
        if (cpl == 0)
2723
            eflags_mask |= IOPL_MASK;
2724
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2725
        if (cpl <= iopl)
2726
            eflags_mask |= IF_MASK;
2727
        if (shift == 0)
2728
            eflags_mask &= 0xffff;
2729
        load_eflags(new_eflags, eflags_mask);
2730
    }
2731
    return;
2732

    
2733
 return_to_vm86:
2734
    POPL(ssp, sp, sp_mask, new_esp);
2735
    POPL(ssp, sp, sp_mask, new_ss);
2736
    POPL(ssp, sp, sp_mask, new_es);
2737
    POPL(ssp, sp, sp_mask, new_ds);
2738
    POPL(ssp, sp, sp_mask, new_fs);
2739
    POPL(ssp, sp, sp_mask, new_gs);
2740

    
2741
    /* modify processor state */
2742
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2743
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2744
    load_seg_vm(R_CS, new_cs & 0xffff);
2745
    cpu_x86_set_cpl(env, 3);
2746
    load_seg_vm(R_SS, new_ss & 0xffff);
2747
    load_seg_vm(R_ES, new_es & 0xffff);
2748
    load_seg_vm(R_DS, new_ds & 0xffff);
2749
    load_seg_vm(R_FS, new_fs & 0xffff);
2750
    load_seg_vm(R_GS, new_gs & 0xffff);
2751

    
2752
    env->eip = new_eip & 0xffff;
2753
    ESP = new_esp;
2754
}
2755

    
2756
void helper_iret_protected(int shift, int next_eip)
2757
{
2758
    int tss_selector, type;
2759
    uint32_t e1, e2;
2760

    
2761
    /* specific case for TSS */
2762
    if (env->eflags & NT_MASK) {
2763
#ifdef TARGET_X86_64
2764
        if (env->hflags & HF_LMA_MASK)
2765
            raise_exception_err(EXCP0D_GPF, 0);
2766
#endif
2767
        tss_selector = lduw_kernel(env->tr.base + 0);
2768
        if (tss_selector & 4)
2769
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2770
        if (load_segment(&e1, &e2, tss_selector) != 0)
2771
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2772
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2773
        /* NOTE: we check both segment and busy TSS */
2774
        if (type != 3)
2775
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2776
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2777
    } else {
2778
        helper_ret_protected(shift, 1, 0);
2779
    }
2780
    env->hflags2 &= ~HF2_NMI_MASK;
2781
}
2782

    
2783
void helper_lret_protected(int shift, int addend)
2784
{
2785
    helper_ret_protected(shift, 0, addend);
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
}
2859

    
2860
#if defined(CONFIG_USER_ONLY)
2861
target_ulong helper_read_crN(int reg)
2862
{
2863
    return 0;
2864
}
2865

    
2866
void helper_write_crN(int reg, target_ulong t0)
2867
{
2868
}
2869

    
2870
void helper_movl_drN_T0(int reg, target_ulong t0)
2871
{
2872
}
2873
#else
2874
target_ulong helper_read_crN(int reg)
2875
{
2876
    target_ulong val;
2877

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

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

    
2919
void helper_movl_drN_T0(int reg, target_ulong t0)
2920
{
2921
    int i;
2922

    
2923
    if (reg < 4) {
2924
        hw_breakpoint_remove(env, reg);
2925
        env->dr[reg] = t0;
2926
        hw_breakpoint_insert(env, reg);
2927
    } else if (reg == 7) {
2928
        for (i = 0; i < 4; i++)
2929
            hw_breakpoint_remove(env, i);
2930
        env->dr[7] = t0;
2931
        for (i = 0; i < 4; i++)
2932
            hw_breakpoint_insert(env, i);
2933
    } else
2934
        env->dr[reg] = t0;
2935
}
2936
#endif
2937

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

    
2946
void helper_clts(void)
2947
{
2948
    env->cr[0] &= ~CR0_TS_MASK;
2949
    env->hflags &= ~HF_TS_MASK;
2950
}
2951

    
2952
void helper_invlpg(target_ulong addr)
2953
{
2954
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
2955
    tlb_flush_page(env, addr);
2956
}
2957

    
2958
void helper_rdtsc(void)
2959
{
2960
    uint64_t val;
2961

    
2962
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2963
        raise_exception(EXCP0D_GPF);
2964
    }
2965
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
2966

    
2967
    val = cpu_get_tsc(env) + env->tsc_offset;
2968
    EAX = (uint32_t)(val);
2969
    EDX = (uint32_t)(val >> 32);
2970
}
2971

    
2972
void helper_rdtscp(void)
2973
{
2974
    helper_rdtsc();
2975
    ECX = (uint32_t)(env->tsc_aux);
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
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3034
                update_mask |= MSR_EFER_FFXSR;
3035
            cpu_load_efer(env, (env->efer & ~update_mask) |
3036
                          (val & update_mask));
3037
        }
3038
        break;
3039
    case MSR_STAR:
3040
        env->star = val;
3041
        break;
3042
    case MSR_PAT:
3043
        env->pat = val;
3044
        break;
3045
    case MSR_VM_HSAVE_PA:
3046
        env->vm_hsave = val;
3047
        break;
3048
#ifdef TARGET_X86_64
3049
    case MSR_LSTAR:
3050
        env->lstar = val;
3051
        break;
3052
    case MSR_CSTAR:
3053
        env->cstar = val;
3054
        break;
3055
    case MSR_FMASK:
3056
        env->fmask = val;
3057
        break;
3058
    case MSR_FSBASE:
3059
        env->segs[R_FS].base = val;
3060
        break;
3061
    case MSR_GSBASE:
3062
        env->segs[R_GS].base = val;
3063
        break;
3064
    case MSR_KERNELGSBASE:
3065
        env->kernelgsbase = val;
3066
        break;
3067
#endif
3068
    case MSR_MTRRphysBase(0):
3069
    case MSR_MTRRphysBase(1):
3070
    case MSR_MTRRphysBase(2):
3071
    case MSR_MTRRphysBase(3):
3072
    case MSR_MTRRphysBase(4):
3073
    case MSR_MTRRphysBase(5):
3074
    case MSR_MTRRphysBase(6):
3075
    case MSR_MTRRphysBase(7):
3076
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
3077
        break;
3078
    case MSR_MTRRphysMask(0):
3079
    case MSR_MTRRphysMask(1):
3080
    case MSR_MTRRphysMask(2):
3081
    case MSR_MTRRphysMask(3):
3082
    case MSR_MTRRphysMask(4):
3083
    case MSR_MTRRphysMask(5):
3084
    case MSR_MTRRphysMask(6):
3085
    case MSR_MTRRphysMask(7):
3086
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
3087
        break;
3088
    case MSR_MTRRfix64K_00000:
3089
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
3090
        break;
3091
    case MSR_MTRRfix16K_80000:
3092
    case MSR_MTRRfix16K_A0000:
3093
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
3094
        break;
3095
    case MSR_MTRRfix4K_C0000:
3096
    case MSR_MTRRfix4K_C8000:
3097
    case MSR_MTRRfix4K_D0000:
3098
    case MSR_MTRRfix4K_D8000:
3099
    case MSR_MTRRfix4K_E0000:
3100
    case MSR_MTRRfix4K_E8000:
3101
    case MSR_MTRRfix4K_F0000:
3102
    case MSR_MTRRfix4K_F8000:
3103
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
3104
        break;
3105
    case MSR_MTRRdefType:
3106
        env->mtrr_deftype = val;
3107
        break;
3108
    case MSR_MCG_STATUS:
3109
        env->mcg_status = val;
3110
        break;
3111
    case MSR_MCG_CTL:
3112
        if ((env->mcg_cap & MCG_CTL_P)
3113
            && (val == 0 || val == ~(uint64_t)0))
3114
            env->mcg_ctl = val;
3115
        break;
3116
    case MSR_TSC_AUX:
3117
        env->tsc_aux = val;
3118
        break;
3119
    default:
3120
        if ((uint32_t)ECX >= MSR_MC0_CTL
3121
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3122
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3123
            if ((offset & 0x3) != 0
3124
                || (val == 0 || val == ~(uint64_t)0))
3125
                env->mce_banks[offset] = val;
3126
            break;
3127
        }
3128
        /* XXX: exception ? */
3129
        break;
3130
    }
3131
}
3132

    
3133
void helper_rdmsr(void)
3134
{
3135
    uint64_t val;
3136

    
3137
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3138

    
3139
    switch((uint32_t)ECX) {
3140
    case MSR_IA32_SYSENTER_CS:
3141
        val = env->sysenter_cs;
3142
        break;
3143
    case MSR_IA32_SYSENTER_ESP:
3144
        val = env->sysenter_esp;
3145
        break;
3146
    case MSR_IA32_SYSENTER_EIP:
3147
        val = env->sysenter_eip;
3148
        break;
3149
    case MSR_IA32_APICBASE:
3150
        val = cpu_get_apic_base(env);
3151
        break;
3152
    case MSR_EFER:
3153
        val = env->efer;
3154
        break;
3155
    case MSR_STAR:
3156
        val = env->star;
3157
        break;
3158
    case MSR_PAT:
3159
        val = env->pat;
3160
        break;
3161
    case MSR_VM_HSAVE_PA:
3162
        val = env->vm_hsave;
3163
        break;
3164
    case MSR_IA32_PERF_STATUS:
3165
        /* tsc_increment_by_tick */
3166
        val = 1000ULL;
3167
        /* CPU multiplier */
3168
        val |= (((uint64_t)4ULL) << 40);
3169
        break;
3170
#ifdef TARGET_X86_64
3171
    case MSR_LSTAR:
3172
        val = env->lstar;
3173
        break;
3174
    case MSR_CSTAR:
3175
        val = env->cstar;
3176
        break;
3177
    case MSR_FMASK:
3178
        val = env->fmask;
3179
        break;
3180
    case MSR_FSBASE:
3181
        val = env->segs[R_FS].base;
3182
        break;
3183
    case MSR_GSBASE:
3184
        val = env->segs[R_GS].base;
3185
        break;
3186
    case MSR_KERNELGSBASE:
3187
        val = env->kernelgsbase;
3188
        break;
3189
    case MSR_TSC_AUX:
3190
        val = env->tsc_aux;
3191
        break;
3192
#endif
3193
    case MSR_MTRRphysBase(0):
3194
    case MSR_MTRRphysBase(1):
3195
    case MSR_MTRRphysBase(2):
3196
    case MSR_MTRRphysBase(3):
3197
    case MSR_MTRRphysBase(4):
3198
    case MSR_MTRRphysBase(5):
3199
    case MSR_MTRRphysBase(6):
3200
    case MSR_MTRRphysBase(7):
3201
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;
3202
        break;
3203
    case MSR_MTRRphysMask(0):
3204
    case MSR_MTRRphysMask(1):
3205
    case MSR_MTRRphysMask(2):
3206
    case MSR_MTRRphysMask(3):
3207
    case MSR_MTRRphysMask(4):
3208
    case MSR_MTRRphysMask(5):
3209
    case MSR_MTRRphysMask(6):
3210
    case MSR_MTRRphysMask(7):
3211
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;
3212
        break;
3213
    case MSR_MTRRfix64K_00000:
3214
        val = env->mtrr_fixed[0];
3215
        break;
3216
    case MSR_MTRRfix16K_80000:
3217
    case MSR_MTRRfix16K_A0000:
3218
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];
3219
        break;
3220
    case MSR_MTRRfix4K_C0000:
3221
    case MSR_MTRRfix4K_C8000:
3222
    case MSR_MTRRfix4K_D0000:
3223
    case MSR_MTRRfix4K_D8000:
3224
    case MSR_MTRRfix4K_E0000:
3225
    case MSR_MTRRfix4K_E8000:
3226
    case MSR_MTRRfix4K_F0000:
3227
    case MSR_MTRRfix4K_F8000:
3228
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];
3229
        break;
3230
    case MSR_MTRRdefType:
3231
        val = env->mtrr_deftype;
3232
        break;
3233
    case MSR_MTRRcap:
3234
        if (env->cpuid_features & CPUID_MTRR)
3235
            val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED;
3236
        else
3237
            /* XXX: exception ? */
3238
            val = 0;
3239
        break;
3240
    case MSR_MCG_CAP:
3241
        val = env->mcg_cap;
3242
        break;
3243
    case MSR_MCG_CTL:
3244
        if (env->mcg_cap & MCG_CTL_P)
3245
            val = env->mcg_ctl;
3246
        else
3247
            val = 0;
3248
        break;
3249
    case MSR_MCG_STATUS:
3250
        val = env->mcg_status;
3251
        break;
3252
    default:
3253
        if ((uint32_t)ECX >= MSR_MC0_CTL
3254
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3255
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3256
            val = env->mce_banks[offset];
3257
            break;
3258
        }
3259
        /* XXX: exception ? */
3260
        val = 0;
3261
        break;
3262
    }
3263
    EAX = (uint32_t)(val);
3264
    EDX = (uint32_t)(val >> 32);
3265
}
3266
#endif
3267

    
3268
target_ulong helper_lsl(target_ulong selector1)
3269
{
3270
    unsigned int limit;
3271
    uint32_t e1, e2, eflags, selector;
3272
    int rpl, dpl, cpl, type;
3273

    
3274
    selector = selector1 & 0xffff;
3275
    eflags = helper_cc_compute_all(CC_OP);
3276
    if ((selector & 0xfffc) == 0)
3277
        goto fail;
3278
    if (load_segment(&e1, &e2, selector) != 0)
3279
        goto fail;
3280
    rpl = selector & 3;
3281
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3282
    cpl = env->hflags & HF_CPL_MASK;
3283
    if (e2 & DESC_S_MASK) {
3284
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3285
            /* conforming */
3286
        } else {
3287
            if (dpl < cpl || dpl < rpl)
3288
                goto fail;
3289
        }
3290
    } else {
3291
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3292
        switch(type) {
3293
        case 1:
3294
        case 2:
3295
        case 3:
3296
        case 9:
3297
        case 11:
3298
            break;
3299
        default:
3300
            goto fail;
3301
        }
3302
        if (dpl < cpl || dpl < rpl) {
3303
        fail:
3304
            CC_SRC = eflags & ~CC_Z;
3305
            return 0;
3306
        }
3307
    }
3308
    limit = get_seg_limit(e1, e2);
3309
    CC_SRC = eflags | CC_Z;
3310
    return limit;
3311
}
3312

    
3313
target_ulong helper_lar(target_ulong selector1)
3314
{
3315
    uint32_t e1, e2, eflags, selector;
3316
    int rpl, dpl, cpl, type;
3317

    
3318
    selector = selector1 & 0xffff;
3319
    eflags = helper_cc_compute_all(CC_OP);
3320
    if ((selector & 0xfffc) == 0)
3321
        goto fail;
3322
    if (load_segment(&e1, &e2, selector) != 0)
3323
        goto fail;
3324
    rpl = selector & 3;
3325
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3326
    cpl = env->hflags & HF_CPL_MASK;
3327
    if (e2 & DESC_S_MASK) {
3328
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3329
            /* conforming */
3330
        } else {
3331
            if (dpl < cpl || dpl < rpl)
3332
                goto fail;
3333
        }
3334
    } else {
3335
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3336
        switch(type) {
3337
        case 1:
3338
        case 2:
3339
        case 3:
3340
        case 4:
3341
        case 5:
3342
        case 9:
3343
        case 11:
3344
        case 12:
3345
            break;
3346
        default:
3347
            goto fail;
3348
        }
3349
        if (dpl < cpl || dpl < rpl) {
3350
        fail:
3351
            CC_SRC = eflags & ~CC_Z;
3352
            return 0;
3353
        }
3354
    }
3355
    CC_SRC = eflags | CC_Z;
3356
    return e2 & 0x00f0ff00;
3357
}
3358

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

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

    
3392
void helper_verw(target_ulong selector1)
3393
{
3394
    uint32_t e1, e2, eflags, selector;
3395
    int rpl, dpl, cpl;
3396

    
3397
    selector = selector1 & 0xffff;
3398
    eflags = helper_cc_compute_all(CC_OP);
3399
    if ((selector & 0xfffc) == 0)
3400
        goto fail;
3401
    if (load_segment(&e1, &e2, selector) != 0)
3402
        goto fail;
3403
    if (!(e2 & DESC_S_MASK))
3404
        goto fail;
3405
    rpl = selector & 3;
3406
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3407
    cpl = env->hflags & HF_CPL_MASK;
3408
    if (e2 & DESC_CS_MASK) {
3409
        goto fail;
3410
    } else {
3411
        if (dpl < cpl || dpl < rpl)
3412
            goto fail;
3413
        if (!(e2 & DESC_W_MASK)) {
3414
        fail:
3415
            CC_SRC = eflags & ~CC_Z;
3416
            return;
3417
        }
3418
    }
3419
    CC_SRC = eflags | CC_Z;
3420
}
3421

    
3422
/* x87 FPU helpers */
3423

    
3424
static void fpu_set_exception(int mask)
3425
{
3426
    env->fpus |= mask;
3427
    if (env->fpus & (~env->fpuc & FPUC_EM))
3428
        env->fpus |= FPUS_SE | FPUS_B;
3429
}
3430

    
3431
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3432
{
3433
    if (b == 0.0)
3434
        fpu_set_exception(FPUS_ZE);
3435
    return a / b;
3436
}
3437

    
3438
static void fpu_raise_exception(void)
3439
{
3440
    if (env->cr[0] & CR0_NE_MASK) {
3441
        raise_exception(EXCP10_COPR);
3442
    }
3443
#if !defined(CONFIG_USER_ONLY)
3444
    else {
3445
        cpu_set_ferr(env);
3446
    }
3447
#endif
3448
}
3449

    
3450
void helper_flds_FT0(uint32_t val)
3451
{
3452
    union {
3453
        float32 f;
3454
        uint32_t i;
3455
    } u;
3456
    u.i = val;
3457
    FT0 = float32_to_floatx(u.f, &env->fp_status);
3458
}
3459

    
3460
void helper_fldl_FT0(uint64_t val)
3461
{
3462
    union {
3463
        float64 f;
3464
        uint64_t i;
3465
    } u;
3466
    u.i = val;
3467
    FT0 = float64_to_floatx(u.f, &env->fp_status);
3468
}
3469

    
3470
void helper_fildl_FT0(int32_t val)
3471
{
3472
    FT0 = int32_to_floatx(val, &env->fp_status);
3473
}
3474

    
3475
void helper_flds_ST0(uint32_t val)
3476
{
3477
    int new_fpstt;
3478
    union {
3479
        float32 f;
3480
        uint32_t i;
3481
    } u;
3482
    new_fpstt = (env->fpstt - 1) & 7;
3483
    u.i = val;
3484
    env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3485
    env->fpstt = new_fpstt;
3486
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3487
}
3488

    
3489
void helper_fldl_ST0(uint64_t val)
3490
{
3491
    int new_fpstt;
3492
    union {
3493
        float64 f;
3494
        uint64_t i;
3495
    } u;
3496
    new_fpstt = (env->fpstt - 1) & 7;
3497
    u.i = val;
3498
    env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3499
    env->fpstt = new_fpstt;
3500
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3501
}
3502

    
3503
void helper_fildl_ST0(int32_t val)
3504
{
3505
    int new_fpstt;
3506
    new_fpstt = (env->fpstt - 1) & 7;
3507
    env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3508
    env->fpstt = new_fpstt;
3509
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3510
}
3511

    
3512
void helper_fildll_ST0(int64_t val)
3513
{
3514
    int new_fpstt;
3515
    new_fpstt = (env->fpstt - 1) & 7;
3516
    env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3517
    env->fpstt = new_fpstt;
3518
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3519
}
3520

    
3521
uint32_t helper_fsts_ST0(void)
3522
{
3523
    union {
3524
        float32 f;
3525
        uint32_t i;
3526
    } u;
3527
    u.f = floatx_to_float32(ST0, &env->fp_status);
3528
    return u.i;
3529
}
3530

    
3531
uint64_t helper_fstl_ST0(void)
3532
{
3533
    union {
3534
        float64 f;
3535
        uint64_t i;
3536
    } u;
3537
    u.f = floatx_to_float64(ST0, &env->fp_status);
3538
    return u.i;
3539
}
3540

    
3541
int32_t helper_fist_ST0(void)
3542
{
3543
    int32_t val;
3544
    val = floatx_to_int32(ST0, &env->fp_status);
3545
    if (val != (int16_t)val)
3546
        val = -32768;
3547
    return val;
3548
}
3549

    
3550
int32_t helper_fistl_ST0(void)
3551
{
3552
    int32_t val;
3553
    val = floatx_to_int32(ST0, &env->fp_status);
3554
    return val;
3555
}
3556

    
3557
int64_t helper_fistll_ST0(void)
3558
{
3559
    int64_t val;
3560
    val = floatx_to_int64(ST0, &env->fp_status);
3561
    return val;
3562
}
3563

    
3564
int32_t helper_fistt_ST0(void)
3565
{
3566
    int32_t val;
3567
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3568
    if (val != (int16_t)val)
3569
        val = -32768;
3570
    return val;
3571
}
3572

    
3573
int32_t helper_fisttl_ST0(void)
3574
{
3575
    int32_t val;
3576
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3577
    return val;
3578
}
3579

    
3580
int64_t helper_fisttll_ST0(void)
3581
{
3582
    int64_t val;
3583
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3584
    return val;
3585
}
3586

    
3587
void helper_fldt_ST0(target_ulong ptr)
3588
{
3589
    int new_fpstt;
3590
    new_fpstt = (env->fpstt - 1) & 7;
3591
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3592
    env->fpstt = new_fpstt;
3593
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3594
}
3595

    
3596
void helper_fstt_ST0(target_ulong ptr)
3597
{
3598
    helper_fstt(ST0, ptr);
3599
}
3600

    
3601
void helper_fpush(void)
3602
{
3603
    fpush();
3604
}
3605

    
3606
void helper_fpop(void)
3607
{
3608
    fpop();
3609
}
3610

    
3611
void helper_fdecstp(void)
3612
{
3613
    env->fpstt = (env->fpstt - 1) & 7;
3614
    env->fpus &= (~0x4700);
3615
}
3616

    
3617
void helper_fincstp(void)
3618
{
3619
    env->fpstt = (env->fpstt + 1) & 7;
3620
    env->fpus &= (~0x4700);
3621
}
3622

    
3623
/* FPU move */
3624

    
3625
void helper_ffree_STN(int st_index)
3626
{
3627
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3628
}
3629

    
3630
void helper_fmov_ST0_FT0(void)
3631
{
3632
    ST0 = FT0;
3633
}
3634

    
3635
void helper_fmov_FT0_STN(int st_index)
3636
{
3637
    FT0 = ST(st_index);
3638
}
3639

    
3640
void helper_fmov_ST0_STN(int st_index)
3641
{
3642
    ST0 = ST(st_index);
3643
}
3644

    
3645
void helper_fmov_STN_ST0(int st_index)
3646
{
3647
    ST(st_index) = ST0;
3648
}
3649

    
3650
void helper_fxchg_ST0_STN(int st_index)
3651
{
3652
    CPU86_LDouble tmp;
3653
    tmp = ST(st_index);
3654
    ST(st_index) = ST0;
3655
    ST0 = tmp;
3656
}
3657

    
3658
/* FPU operations */
3659

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

    
3662
void helper_fcom_ST0_FT0(void)
3663
{
3664
    int ret;
3665

    
3666
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3667
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3668
}
3669

    
3670
void helper_fucom_ST0_FT0(void)
3671
{
3672
    int ret;
3673

    
3674
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3675
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3676
}
3677

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

    
3680
void helper_fcomi_ST0_FT0(void)
3681
{
3682
    int eflags;
3683
    int ret;
3684

    
3685
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3686
    eflags = helper_cc_compute_all(CC_OP);
3687
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3688
    CC_SRC = eflags;
3689
}
3690

    
3691
void helper_fucomi_ST0_FT0(void)
3692
{
3693
    int eflags;
3694
    int ret;
3695

    
3696
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3697
    eflags = helper_cc_compute_all(CC_OP);
3698
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3699
    CC_SRC = eflags;
3700
}
3701

    
3702
void helper_fadd_ST0_FT0(void)
3703
{
3704
    ST0 += FT0;
3705
}
3706

    
3707
void helper_fmul_ST0_FT0(void)
3708
{
3709
    ST0 *= FT0;
3710
}
3711

    
3712
void helper_fsub_ST0_FT0(void)
3713
{
3714
    ST0 -= FT0;
3715
}
3716

    
3717
void helper_fsubr_ST0_FT0(void)
3718
{
3719
    ST0 = FT0 - ST0;
3720
}
3721

    
3722
void helper_fdiv_ST0_FT0(void)
3723
{
3724
    ST0 = helper_fdiv(ST0, FT0);
3725
}
3726

    
3727
void helper_fdivr_ST0_FT0(void)
3728
{
3729
    ST0 = helper_fdiv(FT0, ST0);
3730
}
3731

    
3732
/* fp operations between STN and ST0 */
3733

    
3734
void helper_fadd_STN_ST0(int st_index)
3735
{
3736
    ST(st_index) += ST0;
3737
}
3738

    
3739
void helper_fmul_STN_ST0(int st_index)
3740
{
3741
    ST(st_index) *= ST0;
3742
}
3743

    
3744
void helper_fsub_STN_ST0(int st_index)
3745
{
3746
    ST(st_index) -= ST0;
3747
}
3748

    
3749
void helper_fsubr_STN_ST0(int st_index)
3750
{
3751
    CPU86_LDouble *p;
3752
    p = &ST(st_index);
3753
    *p = ST0 - *p;
3754
}
3755

    
3756
void helper_fdiv_STN_ST0(int st_index)
3757
{
3758
    CPU86_LDouble *p;
3759
    p = &ST(st_index);
3760
    *p = helper_fdiv(*p, ST0);
3761
}
3762

    
3763
void helper_fdivr_STN_ST0(int st_index)
3764
{
3765
    CPU86_LDouble *p;
3766
    p = &ST(st_index);
3767
    *p = helper_fdiv(ST0, *p);
3768
}
3769

    
3770
/* misc FPU operations */
3771
void helper_fchs_ST0(void)
3772
{
3773
    ST0 = floatx_chs(ST0);
3774
}
3775

    
3776
void helper_fabs_ST0(void)
3777
{
3778
    ST0 = floatx_abs(ST0);
3779
}
3780

    
3781
void helper_fld1_ST0(void)
3782
{
3783
    ST0 = f15rk[1];
3784
}
3785

    
3786
void helper_fldl2t_ST0(void)
3787
{
3788
    ST0 = f15rk[6];
3789
}
3790

    
3791
void helper_fldl2e_ST0(void)
3792
{
3793
    ST0 = f15rk[5];
3794
}
3795

    
3796
void helper_fldpi_ST0(void)
3797
{
3798
    ST0 = f15rk[2];
3799
}
3800

    
3801
void helper_fldlg2_ST0(void)
3802
{
3803
    ST0 = f15rk[3];
3804
}
3805

    
3806
void helper_fldln2_ST0(void)
3807
{
3808
    ST0 = f15rk[4];
3809
}
3810

    
3811
void helper_fldz_ST0(void)
3812
{
3813
    ST0 = f15rk[0];
3814
}
3815

    
3816
void helper_fldz_FT0(void)
3817
{
3818
    FT0 = f15rk[0];
3819
}
3820

    
3821
uint32_t helper_fnstsw(void)
3822
{
3823
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3824
}
3825

    
3826
uint32_t helper_fnstcw(void)
3827
{
3828
    return env->fpuc;
3829
}
3830

    
3831
static void update_fp_status(void)
3832
{
3833
    int rnd_type;
3834

    
3835
    /* set rounding mode */
3836
    switch(env->fpuc & RC_MASK) {
3837
    default:
3838
    case RC_NEAR:
3839
        rnd_type = float_round_nearest_even;
3840
        break;
3841
    case RC_DOWN:
3842
        rnd_type = float_round_down;
3843
        break;
3844
    case RC_UP:
3845
        rnd_type = float_round_up;
3846
        break;
3847
    case RC_CHOP:
3848
        rnd_type = float_round_to_zero;
3849
        break;
3850
    }
3851
    set_float_rounding_mode(rnd_type, &env->fp_status);
3852
#ifdef FLOATX80
3853
    switch((env->fpuc >> 8) & 3) {
3854
    case 0:
3855
        rnd_type = 32;
3856
        break;
3857
    case 2:
3858
        rnd_type = 64;
3859
        break;
3860
    case 3:
3861
    default:
3862
        rnd_type = 80;
3863
        break;
3864
    }
3865
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3866
#endif
3867
}
3868

    
3869
void helper_fldcw(uint32_t val)
3870
{
3871
    env->fpuc = val;
3872
    update_fp_status();
3873
}
3874

    
3875
void helper_fclex(void)
3876
{
3877
    env->fpus &= 0x7f00;
3878
}
3879

    
3880
void helper_fwait(void)
3881
{
3882
    if (env->fpus & FPUS_SE)
3883
        fpu_raise_exception();
3884
}
3885

    
3886
void helper_fninit(void)
3887
{
3888
    env->fpus = 0;
3889
    env->fpstt = 0;
3890
    env->fpuc = 0x37f;
3891
    env->fptags[0] = 1;
3892
    env->fptags[1] = 1;
3893
    env->fptags[2] = 1;
3894
    env->fptags[3] = 1;
3895
    env->fptags[4] = 1;
3896
    env->fptags[5] = 1;
3897
    env->fptags[6] = 1;
3898
    env->fptags[7] = 1;
3899
}
3900

    
3901
/* BCD ops */
3902

    
3903
void helper_fbld_ST0(target_ulong ptr)
3904
{
3905
    CPU86_LDouble tmp;
3906
    uint64_t val;
3907
    unsigned int v;
3908
    int i;
3909

    
3910
    val = 0;
3911
    for(i = 8; i >= 0; i--) {
3912
        v = ldub(ptr + i);
3913
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3914
    }
3915
    tmp = val;
3916
    if (ldub(ptr + 9) & 0x80)
3917
        tmp = -tmp;
3918
    fpush();
3919
    ST0 = tmp;
3920
}
3921

    
3922
void helper_fbst_ST0(target_ulong ptr)
3923
{
3924
    int v;
3925
    target_ulong mem_ref, mem_end;
3926
    int64_t val;
3927

    
3928
    val = floatx_to_int64(ST0, &env->fp_status);
3929
    mem_ref = ptr;
3930
    mem_end = mem_ref + 9;
3931
    if (val < 0) {
3932
        stb(mem_end, 0x80);
3933
        val = -val;
3934
    } else {
3935
        stb(mem_end, 0x00);
3936
    }
3937
    while (mem_ref < mem_end) {
3938
        if (val == 0)
3939
            break;
3940
        v = val % 100;
3941
        val = val / 100;
3942
        v = ((v / 10) << 4) | (v % 10);
3943
        stb(mem_ref++, v);
3944
    }
3945
    while (mem_ref < mem_end) {
3946
        stb(mem_ref++, 0);
3947
    }
3948
}
3949

    
3950
void helper_f2xm1(void)
3951
{
3952
    ST0 = pow(2.0,ST0) - 1.0;
3953
}
3954

    
3955
void helper_fyl2x(void)
3956
{
3957
    CPU86_LDouble fptemp;
3958

    
3959
    fptemp = ST0;
3960
    if (fptemp>0.0){
3961
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
3962
        ST1 *= fptemp;
3963
        fpop();
3964
    } else {
3965
        env->fpus &= (~0x4700);
3966
        env->fpus |= 0x400;
3967
    }
3968
}
3969

    
3970
void helper_fptan(void)
3971
{
3972
    CPU86_LDouble fptemp;
3973

    
3974
    fptemp = ST0;
3975
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3976
        env->fpus |= 0x400;
3977
    } else {
3978
        ST0 = tan(fptemp);
3979
        fpush();
3980
        ST0 = 1.0;
3981
        env->fpus &= (~0x400);  /* C2 <-- 0 */
3982
        /* the above code is for  |arg| < 2**52 only */
3983
    }
3984
}
3985

    
3986
void helper_fpatan(void)
3987
{
3988
    CPU86_LDouble fptemp, fpsrcop;
3989

    
3990
    fpsrcop = ST1;
3991
    fptemp = ST0;
3992
    ST1 = atan2(fpsrcop,fptemp);
3993
    fpop();
3994
}
3995

    
3996
void helper_fxtract(void)
3997
{
3998
    CPU86_LDoubleU temp;
3999
    unsigned int expdif;
4000

    
4001
    temp.d = ST0;
4002
    expdif = EXPD(temp) - EXPBIAS;
4003
    /*DP exponent bias*/
4004
    ST0 = expdif;
4005
    fpush();
4006
    BIASEXPONENT(temp);
4007
    ST0 = temp.d;
4008
}
4009

    
4010
void helper_fprem1(void)
4011
{
4012
    CPU86_LDouble dblq, fpsrcop, fptemp;
4013
    CPU86_LDoubleU fpsrcop1, fptemp1;
4014
    int expdif;
4015
    signed long long int q;
4016

    
4017
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
4018
        ST0 = 0.0 / 0.0; /* NaN */
4019
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4020
        return;
4021
    }
4022

    
4023
    fpsrcop = ST0;
4024
    fptemp = ST1;
4025
    fpsrcop1.d = fpsrcop;
4026
    fptemp1.d = fptemp;
4027
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4028

    
4029
    if (expdif < 0) {
4030
        /* optimisation? taken from the AMD docs */
4031
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4032
        /* ST0 is unchanged */
4033
        return;
4034
    }
4035

    
4036
    if (expdif < 53) {
4037
        dblq = fpsrcop / fptemp;
4038
        /* round dblq towards nearest integer */
4039
        dblq = rint(dblq);
4040
        ST0 = fpsrcop - fptemp * dblq;
4041

    
4042
        /* convert dblq to q by truncating towards zero */
4043
        if (dblq < 0.0)
4044
           q = (signed long long int)(-dblq);
4045
        else
4046
           q = (signed long long int)dblq;
4047

    
4048
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4049
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4050
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4051
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4052
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4053
    } else {
4054
        env->fpus |= 0x400;  /* C2 <-- 1 */
4055
        fptemp = pow(2.0, expdif - 50);
4056
        fpsrcop = (ST0 / ST1) / fptemp;
4057
        /* fpsrcop = integer obtained by chopping */
4058
        fpsrcop = (fpsrcop < 0.0) ?
4059
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4060
        ST0 -= (ST1 * fpsrcop * fptemp);
4061
    }
4062
}
4063

    
4064
void helper_fprem(void)
4065
{
4066
    CPU86_LDouble dblq, fpsrcop, fptemp;
4067
    CPU86_LDoubleU fpsrcop1, fptemp1;
4068
    int expdif;
4069
    signed long long int q;
4070

    
4071
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
4072
       ST0 = 0.0 / 0.0; /* NaN */
4073
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4074
       return;
4075
    }
4076

    
4077
    fpsrcop = (CPU86_LDouble)ST0;
4078
    fptemp = (CPU86_LDouble)ST1;
4079
    fpsrcop1.d = fpsrcop;
4080
    fptemp1.d = fptemp;
4081
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4082

    
4083
    if (expdif < 0) {
4084
        /* optimisation? taken from the AMD docs */
4085
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4086
        /* ST0 is unchanged */
4087
        return;
4088
    }
4089

    
4090
    if ( expdif < 53 ) {
4091
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4092
        /* round dblq towards zero */
4093
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4094
        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
4095

    
4096
        /* convert dblq to q by truncating towards zero */
4097
        if (dblq < 0.0)
4098
           q = (signed long long int)(-dblq);
4099
        else
4100
           q = (signed long long int)dblq;
4101

    
4102
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4103
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4104
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4105
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4106
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4107
    } else {
4108
        int N = 32 + (expdif % 32); /* as per AMD docs */
4109
        env->fpus |= 0x400;  /* C2 <-- 1 */
4110
        fptemp = pow(2.0, (double)(expdif - N));
4111
        fpsrcop = (ST0 / ST1) / fptemp;
4112
        /* fpsrcop = integer obtained by chopping */
4113
        fpsrcop = (fpsrcop < 0.0) ?
4114
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4115
        ST0 -= (ST1 * fpsrcop * fptemp);
4116
    }
4117
}
4118

    
4119
void helper_fyl2xp1(void)
4120
{
4121
    CPU86_LDouble fptemp;
4122

    
4123
    fptemp = ST0;
4124
    if ((fptemp+1.0)>0.0) {
4125
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4126
        ST1 *= fptemp;
4127
        fpop();
4128
    } else {
4129
        env->fpus &= (~0x4700);
4130
        env->fpus |= 0x400;
4131
    }
4132
}
4133

    
4134
void helper_fsqrt(void)
4135
{
4136
    CPU86_LDouble fptemp;
4137

    
4138
    fptemp = ST0;
4139
    if (fptemp<0.0) {
4140
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4141
        env->fpus |= 0x400;
4142
    }
4143
    ST0 = sqrt(fptemp);
4144
}
4145

    
4146
void helper_fsincos(void)
4147
{
4148
    CPU86_LDouble fptemp;
4149

    
4150
    fptemp = ST0;
4151
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4152
        env->fpus |= 0x400;
4153
    } else {
4154
        ST0 = sin(fptemp);
4155
        fpush();
4156
        ST0 = cos(fptemp);
4157
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4158
        /* the above code is for  |arg| < 2**63 only */
4159
    }
4160
}
4161

    
4162
void helper_frndint(void)
4163
{
4164
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4165
}
4166

    
4167
void helper_fscale(void)
4168
{
4169
    ST0 = ldexp (ST0, (int)(ST1));
4170
}
4171

    
4172
void helper_fsin(void)
4173
{
4174
    CPU86_LDouble fptemp;
4175

    
4176
    fptemp = ST0;
4177
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4178
        env->fpus |= 0x400;
4179
    } else {
4180
        ST0 = sin(fptemp);
4181
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4182
        /* the above code is for  |arg| < 2**53 only */
4183
    }
4184
}
4185

    
4186
void helper_fcos(void)
4187
{
4188
    CPU86_LDouble fptemp;
4189

    
4190
    fptemp = ST0;
4191
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4192
        env->fpus |= 0x400;
4193
    } else {
4194
        ST0 = cos(fptemp);
4195
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4196
        /* the above code is for  |arg5 < 2**63 only */
4197
    }
4198
}
4199

    
4200
void helper_fxam_ST0(void)
4201
{
4202
    CPU86_LDoubleU temp;
4203
    int expdif;
4204

    
4205
    temp.d = ST0;
4206

    
4207
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4208
    if (SIGND(temp))
4209
        env->fpus |= 0x200; /* C1 <-- 1 */
4210

    
4211
    /* XXX: test fptags too */
4212
    expdif = EXPD(temp);
4213
    if (expdif == MAXEXPD) {
4214
#ifdef USE_X86LDOUBLE
4215
        if (MANTD(temp) == 0x8000000000000000ULL)
4216
#else
4217
        if (MANTD(temp) == 0)
4218
#endif
4219
            env->fpus |=  0x500 /*Infinity*/;
4220
        else
4221
            env->fpus |=  0x100 /*NaN*/;
4222
    } else if (expdif == 0) {
4223
        if (MANTD(temp) == 0)
4224
            env->fpus |=  0x4000 /*Zero*/;
4225
        else
4226
            env->fpus |= 0x4400 /*Denormal*/;
4227
    } else {
4228
        env->fpus |= 0x400;
4229
    }
4230
}
4231

    
4232
void helper_fstenv(target_ulong ptr, int data32)
4233
{
4234
    int fpus, fptag, exp, i;
4235
    uint64_t mant;
4236
    CPU86_LDoubleU tmp;
4237

    
4238
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4239
    fptag = 0;
4240
    for (i=7; i>=0; i--) {
4241
        fptag <<= 2;
4242
        if (env->fptags[i]) {
4243
            fptag |= 3;
4244
        } else {
4245
            tmp.d = env->fpregs[i].d;
4246
            exp = EXPD(tmp);
4247
            mant = MANTD(tmp);
4248
            if (exp == 0 && mant == 0) {
4249
                /* zero */
4250
                fptag |= 1;
4251
            } else if (exp == 0 || exp == MAXEXPD
4252
#ifdef USE_X86LDOUBLE
4253
                       || (mant & (1LL << 63)) == 0
4254
#endif
4255
                       ) {
4256
                /* NaNs, infinity, denormal */
4257
                fptag |= 2;
4258
            }
4259
        }
4260
    }
4261
    if (data32) {
4262
        /* 32 bit */
4263
        stl(ptr, env->fpuc);
4264
        stl(ptr + 4, fpus);
4265
        stl(ptr + 8, fptag);
4266
        stl(ptr + 12, 0); /* fpip */
4267
        stl(ptr + 16, 0); /* fpcs */
4268
        stl(ptr + 20, 0); /* fpoo */
4269
        stl(ptr + 24, 0); /* fpos */
4270
    } else {
4271
        /* 16 bit */
4272
        stw(ptr, env->fpuc);
4273
        stw(ptr + 2, fpus);
4274
        stw(ptr + 4, fptag);
4275
        stw(ptr + 6, 0);
4276
        stw(ptr + 8, 0);
4277
        stw(ptr + 10, 0);
4278
        stw(ptr + 12, 0);
4279
    }
4280
}
4281

    
4282
void helper_fldenv(target_ulong ptr, int data32)
4283
{
4284
    int i, fpus, fptag;
4285

    
4286
    if (data32) {
4287
        env->fpuc = lduw(ptr);
4288
        fpus = lduw(ptr + 4);
4289
        fptag = lduw(ptr + 8);
4290
    }
4291
    else {
4292
        env->fpuc = lduw(ptr);
4293
        fpus = lduw(ptr + 2);
4294
        fptag = lduw(ptr + 4);
4295
    }
4296
    env->fpstt = (fpus >> 11) & 7;
4297
    env->fpus = fpus & ~0x3800;
4298
    for(i = 0;i < 8; i++) {
4299
        env->fptags[i] = ((fptag & 3) == 3);
4300
        fptag >>= 2;
4301
    }
4302
}
4303

    
4304
void helper_fsave(target_ulong ptr, int data32)
4305
{
4306
    CPU86_LDouble tmp;
4307
    int i;
4308

    
4309
    helper_fstenv(ptr, data32);
4310

    
4311
    ptr += (14 << data32);
4312
    for(i = 0;i < 8; i++) {
4313
        tmp = ST(i);
4314
        helper_fstt(tmp, ptr);
4315
        ptr += 10;
4316
    }
4317

    
4318
    /* fninit */
4319
    env->fpus = 0;
4320
    env->fpstt = 0;
4321
    env->fpuc = 0x37f;
4322
    env->fptags[0] = 1;
4323
    env->fptags[1] = 1;
4324
    env->fptags[2] = 1;
4325
    env->fptags[3] = 1;
4326
    env->fptags[4] = 1;
4327
    env->fptags[5] = 1;
4328
    env->fptags[6] = 1;
4329
    env->fptags[7] = 1;
4330
}
4331

    
4332
void helper_frstor(target_ulong ptr, int data32)
4333
{
4334
    CPU86_LDouble tmp;
4335
    int i;
4336

    
4337
    helper_fldenv(ptr, data32);
4338
    ptr += (14 << data32);
4339

    
4340
    for(i = 0;i < 8; i++) {
4341
        tmp = helper_fldt(ptr);
4342
        ST(i) = tmp;
4343
        ptr += 10;
4344
    }
4345
}
4346

    
4347
void helper_fxsave(target_ulong ptr, int data64)
4348
{
4349
    int fpus, fptag, i, nb_xmm_regs;
4350
    CPU86_LDouble tmp;
4351
    target_ulong addr;
4352

    
4353
    /* The operand must be 16 byte aligned */
4354
    if (ptr & 0xf) {
4355
        raise_exception(EXCP0D_GPF);
4356
    }
4357

    
4358
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4359
    fptag = 0;
4360
    for(i = 0; i < 8; i++) {
4361
        fptag |= (env->fptags[i] << i);
4362
    }
4363
    stw(ptr, env->fpuc);
4364
    stw(ptr + 2, fpus);
4365
    stw(ptr + 4, fptag ^ 0xff);
4366
#ifdef TARGET_X86_64
4367
    if (data64) {
4368
        stq(ptr + 0x08, 0); /* rip */
4369
        stq(ptr + 0x10, 0); /* rdp */
4370
    } else 
4371
#endif
4372
    {
4373
        stl(ptr + 0x08, 0); /* eip */
4374
        stl(ptr + 0x0c, 0); /* sel  */
4375
        stl(ptr + 0x10, 0); /* dp */
4376
        stl(ptr + 0x14, 0); /* sel  */
4377
    }
4378

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

    
4386
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4387
        /* XXX: finish it */
4388
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4389
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4390
        if (env->hflags & HF_CS64_MASK)
4391
            nb_xmm_regs = 16;
4392
        else
4393
            nb_xmm_regs = 8;
4394
        addr = ptr + 0xa0;
4395
        /* Fast FXSAVE leaves out the XMM registers */
4396
        if (!(env->efer & MSR_EFER_FFXSR)
4397
          || (env->hflags & HF_CPL_MASK)
4398
          || !(env->hflags & HF_LMA_MASK)) {
4399
            for(i = 0; i < nb_xmm_regs; i++) {
4400
                stq(addr, env->xmm_regs[i].XMM_Q(0));
4401
                stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4402
                addr += 16;
4403
            }
4404
        }
4405
    }
4406
}
4407

    
4408
void helper_fxrstor(target_ulong ptr, int data64)
4409
{
4410
    int i, fpus, fptag, nb_xmm_regs;
4411
    CPU86_LDouble tmp;
4412
    target_ulong addr;
4413

    
4414
    /* The operand must be 16 byte aligned */
4415
    if (ptr & 0xf) {
4416
        raise_exception(EXCP0D_GPF);
4417
    }
4418

    
4419
    env->fpuc = lduw(ptr);
4420
    fpus = lduw(ptr + 2);
4421
    fptag = lduw(ptr + 4);
4422
    env->fpstt = (fpus >> 11) & 7;
4423
    env->fpus = fpus & ~0x3800;
4424
    fptag ^= 0xff;
4425
    for(i = 0;i < 8; i++) {
4426
        env->fptags[i] = ((fptag >> i) & 1);
4427
    }
4428

    
4429
    addr = ptr + 0x20;
4430
    for(i = 0;i < 8; i++) {
4431
        tmp = helper_fldt(addr);
4432
        ST(i) = tmp;
4433
        addr += 16;
4434
    }
4435

    
4436
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4437
        /* XXX: finish it */
4438
        env->mxcsr = ldl(ptr + 0x18);
4439
        //ldl(ptr + 0x1c);
4440
        if (env->hflags & HF_CS64_MASK)
4441
            nb_xmm_regs = 16;
4442
        else
4443
            nb_xmm_regs = 8;
4444
        addr = ptr + 0xa0;
4445
        /* Fast FXRESTORE leaves out the XMM registers */
4446
        if (!(env->efer & MSR_EFER_FFXSR)
4447
          || (env->hflags & HF_CPL_MASK)
4448
          || !(env->hflags & HF_LMA_MASK)) {
4449
            for(i = 0; i < nb_xmm_regs; i++) {
4450
                env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4451
                env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4452
                addr += 16;
4453
            }
4454
        }
4455
    }
4456
}
4457

    
4458
#ifndef USE_X86LDOUBLE
4459

    
4460
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4461
{
4462
    CPU86_LDoubleU temp;
4463
    int e;
4464

    
4465
    temp.d = f;
4466
    /* mantissa */
4467
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4468
    /* exponent + sign */
4469
    e = EXPD(temp) - EXPBIAS + 16383;
4470
    e |= SIGND(temp) >> 16;
4471
    *pexp = e;
4472
}
4473

    
4474
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4475
{
4476
    CPU86_LDoubleU temp;
4477
    int e;
4478
    uint64_t ll;
4479

    
4480
    /* XXX: handle overflow ? */
4481
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4482
    e |= (upper >> 4) & 0x800; /* sign */
4483
    ll = (mant >> 11) & ((1LL << 52) - 1);
4484
#ifdef __arm__
4485
    temp.l.upper = (e << 20) | (ll >> 32);
4486
    temp.l.lower = ll;
4487
#else
4488
    temp.ll = ll | ((uint64_t)e << 52);
4489
#endif
4490
    return temp.d;
4491
}
4492

    
4493
#else
4494

    
4495
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4496
{
4497
    CPU86_LDoubleU temp;
4498

    
4499
    temp.d = f;
4500
    *pmant = temp.l.lower;
4501
    *pexp = temp.l.upper;
4502
}
4503

    
4504
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4505
{
4506
    CPU86_LDoubleU temp;
4507

    
4508
    temp.l.upper = upper;
4509
    temp.l.lower = mant;
4510
    return temp.d;
4511
}
4512
#endif
4513

    
4514
#ifdef TARGET_X86_64
4515

    
4516
//#define DEBUG_MULDIV
4517

    
4518
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4519
{
4520
    *plow += a;
4521
    /* carry test */
4522
    if (*plow < a)
4523
        (*phigh)++;
4524
    *phigh += b;
4525
}
4526

    
4527
static void neg128(uint64_t *plow, uint64_t *phigh)
4528
{
4529
    *plow = ~ *plow;
4530
    *phigh = ~ *phigh;
4531
    add128(plow, phigh, 1, 0);
4532
}
4533

    
4534
/* return TRUE if overflow */
4535
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4536
{
4537
    uint64_t q, r, a1, a0;
4538
    int i, qb, ab;
4539

    
4540
    a0 = *plow;
4541
    a1 = *phigh;
4542
    if (a1 == 0) {
4543
        q = a0 / b;
4544
        r = a0 % b;
4545
        *plow = q;
4546
        *phigh = r;
4547
    } else {
4548
        if (a1 >= b)
4549
            return 1;
4550
        /* XXX: use a better algorithm */
4551
        for(i = 0; i < 64; i++) {
4552
            ab = a1 >> 63;
4553
            a1 = (a1 << 1) | (a0 >> 63);
4554
            if (ab || a1 >= b) {
4555
                a1 -= b;
4556
                qb = 1;
4557
            } else {
4558
                qb = 0;
4559
            }
4560
            a0 = (a0 << 1) | qb;
4561
        }
4562
#if defined(DEBUG_MULDIV)
4563
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4564
               *phigh, *plow, b, a0, a1);
4565
#endif
4566
        *plow = a0;
4567
        *phigh = a1;
4568
    }
4569
    return 0;
4570
}
4571

    
4572
/* return TRUE if overflow */
4573
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4574
{
4575
    int sa, sb;
4576
    sa = ((int64_t)*phigh < 0);
4577
    if (sa)
4578
        neg128(plow, phigh);
4579
    sb = (b < 0);
4580
    if (sb)
4581
        b = -b;
4582
    if (div64(plow, phigh, b) != 0)
4583
        return 1;
4584
    if (sa ^ sb) {
4585
        if (*plow > (1ULL << 63))
4586
            return 1;
4587
        *plow = - *plow;
4588
    } else {
4589
        if (*plow >= (1ULL << 63))
4590
            return 1;
4591
    }
4592
    if (sa)
4593
        *phigh = - *phigh;
4594
    return 0;
4595
}
4596

    
4597
void helper_mulq_EAX_T0(target_ulong t0)
4598
{
4599
    uint64_t r0, r1;
4600

    
4601
    mulu64(&r0, &r1, EAX, t0);
4602
    EAX = r0;
4603
    EDX = r1;
4604
    CC_DST = r0;
4605
    CC_SRC = r1;
4606
}
4607

    
4608
void helper_imulq_EAX_T0(target_ulong t0)
4609
{
4610
    uint64_t r0, r1;
4611

    
4612
    muls64(&r0, &r1, EAX, t0);
4613
    EAX = r0;
4614
    EDX = r1;
4615
    CC_DST = r0;
4616
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4617
}
4618

    
4619
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4620
{
4621
    uint64_t r0, r1;
4622

    
4623
    muls64(&r0, &r1, t0, t1);
4624
    CC_DST = r0;
4625
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4626
    return r0;
4627
}
4628

    
4629
void helper_divq_EAX(target_ulong t0)
4630
{
4631
    uint64_t r0, r1;
4632
    if (t0 == 0) {
4633
        raise_exception(EXCP00_DIVZ);
4634
    }
4635
    r0 = EAX;
4636
    r1 = EDX;
4637
    if (div64(&r0, &r1, t0))
4638
        raise_exception(EXCP00_DIVZ);
4639
    EAX = r0;
4640
    EDX = r1;
4641
}
4642

    
4643
void helper_idivq_EAX(target_ulong t0)
4644
{
4645
    uint64_t r0, r1;
4646
    if (t0 == 0) {
4647
        raise_exception(EXCP00_DIVZ);
4648
    }
4649
    r0 = EAX;
4650
    r1 = EDX;
4651
    if (idiv64(&r0, &r1, t0))
4652
        raise_exception(EXCP00_DIVZ);
4653
    EAX = r0;
4654
    EDX = r1;
4655
}
4656
#endif
4657

    
4658
static void do_hlt(void)
4659
{
4660
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4661
    env->halted = 1;
4662
    env->exception_index = EXCP_HLT;
4663
    cpu_loop_exit();
4664
}
4665

    
4666
void helper_hlt(int next_eip_addend)
4667
{
4668
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4669
    EIP += next_eip_addend;
4670
    
4671
    do_hlt();
4672
}
4673

    
4674
void helper_monitor(target_ulong ptr)
4675
{
4676
    if ((uint32_t)ECX != 0)
4677
        raise_exception(EXCP0D_GPF);
4678
    /* XXX: store address ? */
4679
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4680
}
4681

    
4682
void helper_mwait(int next_eip_addend)
4683
{
4684
    if ((uint32_t)ECX != 0)
4685
        raise_exception(EXCP0D_GPF);
4686
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4687
    EIP += next_eip_addend;
4688

    
4689
    /* XXX: not complete but not completely erroneous */
4690
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4691
        /* more than one CPU: do not sleep because another CPU may
4692
           wake this one */
4693
    } else {
4694
        do_hlt();
4695
    }
4696
}
4697

    
4698
void helper_debug(void)
4699
{
4700
    env->exception_index = EXCP_DEBUG;
4701
    cpu_loop_exit();
4702
}
4703

    
4704
void helper_reset_rf(void)
4705
{
4706
    env->eflags &= ~RF_MASK;
4707
}
4708

    
4709
void helper_raise_interrupt(int intno, int next_eip_addend)
4710
{
4711
    raise_interrupt(intno, 1, 0, next_eip_addend);
4712
}
4713

    
4714
void helper_raise_exception(int exception_index)
4715
{
4716
    raise_exception(exception_index);
4717
}
4718

    
4719
void helper_cli(void)
4720
{
4721
    env->eflags &= ~IF_MASK;
4722
}
4723

    
4724
void helper_sti(void)
4725
{
4726
    env->eflags |= IF_MASK;
4727
}
4728

    
4729
#if 0
4730
/* vm86plus instructions */
4731
void helper_cli_vm(void)
4732
{
4733
    env->eflags &= ~VIF_MASK;
4734
}
4735

4736
void helper_sti_vm(void)
4737
{
4738
    env->eflags |= VIF_MASK;
4739
    if (env->eflags & VIP_MASK) {
4740
        raise_exception(EXCP0D_GPF);
4741
    }
4742
}
4743
#endif
4744

    
4745
void helper_set_inhibit_irq(void)
4746
{
4747
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4748
}
4749

    
4750
void helper_reset_inhibit_irq(void)
4751
{
4752
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4753
}
4754

    
4755
void helper_boundw(target_ulong a0, int v)
4756
{
4757
    int low, high;
4758
    low = ldsw(a0);
4759
    high = ldsw(a0 + 2);
4760
    v = (int16_t)v;
4761
    if (v < low || v > high) {
4762
        raise_exception(EXCP05_BOUND);
4763
    }
4764
}
4765

    
4766
void helper_boundl(target_ulong a0, int v)
4767
{
4768
    int low, high;
4769
    low = ldl(a0);
4770
    high = ldl(a0 + 4);
4771
    if (v < low || v > high) {
4772
        raise_exception(EXCP05_BOUND);
4773
    }
4774
}
4775

    
4776
static float approx_rsqrt(float a)
4777
{
4778
    return 1.0 / sqrt(a);
4779
}
4780

    
4781
static float approx_rcp(float a)
4782
{
4783
    return 1.0 / a;
4784
}
4785

    
4786
#if !defined(CONFIG_USER_ONLY)
4787

    
4788
#define MMUSUFFIX _mmu
4789

    
4790
#define SHIFT 0
4791
#include "softmmu_template.h"
4792

    
4793
#define SHIFT 1
4794
#include "softmmu_template.h"
4795

    
4796
#define SHIFT 2
4797
#include "softmmu_template.h"
4798

    
4799
#define SHIFT 3
4800
#include "softmmu_template.h"
4801

    
4802
#endif
4803

    
4804
#if !defined(CONFIG_USER_ONLY)
4805
/* try to fill the TLB and return an exception if error. If retaddr is
4806
   NULL, it means that the function was called in C code (i.e. not
4807
   from generated code or from helper.c) */
4808
/* XXX: fix it to restore all registers */
4809
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4810
{
4811
    TranslationBlock *tb;
4812
    int ret;
4813
    unsigned long pc;
4814
    CPUX86State *saved_env;
4815

    
4816
    /* XXX: hack to restore env in all cases, even if not called from
4817
       generated code */
4818
    saved_env = env;
4819
    env = cpu_single_env;
4820

    
4821
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4822
    if (ret) {
4823
        if (retaddr) {
4824
            /* now we have a real cpu fault */
4825
            pc = (unsigned long)retaddr;
4826
            tb = tb_find_pc(pc);
4827
            if (tb) {
4828
                /* the PC is inside the translated code. It means that we have
4829
                   a virtual CPU fault */
4830
                cpu_restore_state(tb, env, pc, NULL);
4831
            }
4832
        }
4833
        raise_exception_err(env->exception_index, env->error_code);
4834
    }
4835
    env = saved_env;
4836
}
4837
#endif
4838

    
4839
/* Secure Virtual Machine helpers */
4840

    
4841
#if defined(CONFIG_USER_ONLY)
4842

    
4843
void helper_vmrun(int aflag, int next_eip_addend)
4844
{ 
4845
}
4846
void helper_vmmcall(void) 
4847
{ 
4848
}
4849
void helper_vmload(int aflag)
4850
{ 
4851
}
4852
void helper_vmsave(int aflag)
4853
{ 
4854
}
4855
void helper_stgi(void)
4856
{
4857
}
4858
void helper_clgi(void)
4859
{
4860
}
4861
void helper_skinit(void) 
4862
{ 
4863
}
4864
void helper_invlpga(int aflag)
4865
{ 
4866
}
4867
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4868
{ 
4869
}
4870
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4871
{
4872
}
4873

    
4874
void helper_svm_check_io(uint32_t port, uint32_t param, 
4875
                         uint32_t next_eip_addend)
4876
{
4877
}
4878
#else
4879

    
4880
static inline void svm_save_seg(target_phys_addr_t addr,
4881
                                const SegmentCache *sc)
4882
{
4883
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4884
             sc->selector);
4885
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4886
             sc->base);
4887
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4888
             sc->limit);
4889
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4890
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4891
}
4892
                                
4893
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4894
{
4895
    unsigned int flags;
4896

    
4897
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4898
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4899
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4900
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4901
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4902
}
4903

    
4904
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4905
                                      CPUState *env, int seg_reg)
4906
{
4907
    SegmentCache sc1, *sc = &sc1;
4908
    svm_load_seg(addr, sc);
4909
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4910
                           sc->base, sc->limit, sc->flags);
4911
}
4912

    
4913
void helper_vmrun(int aflag, int next_eip_addend)
4914
{
4915
    target_ulong addr;
4916
    uint32_t event_inj;
4917
    uint32_t int_ctl;
4918

    
4919
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4920

    
4921
    if (aflag == 2)
4922
        addr = EAX;
4923
    else
4924
        addr = (uint32_t)EAX;
4925

    
4926
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
4927

    
4928
    env->vm_vmcb = addr;
4929

    
4930
    /* save the current CPU state in the hsave page */
4931
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4932
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4933

    
4934
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4935
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4936

    
4937
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4938
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4939
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4940
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4941
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4942
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4943

    
4944
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4945
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4946

    
4947
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4948
                  &env->segs[R_ES]);
4949
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4950
                 &env->segs[R_CS]);
4951
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4952
                 &env->segs[R_SS]);
4953
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4954
                 &env->segs[R_DS]);
4955

    
4956
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
4957
             EIP + next_eip_addend);
4958
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4959
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4960

    
4961
    /* load the interception bitmaps so we do not need to access the
4962
       vmcb in svm mode */
4963
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4964
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4965
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4966
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4967
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4968
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4969

    
4970
    /* enable intercepts */
4971
    env->hflags |= HF_SVMI_MASK;
4972

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

    
4975
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4976
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4977

    
4978
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4979
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4980

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

    
4984
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4985
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4986
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4987
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4988
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4989
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4990
    if (int_ctl & V_INTR_MASKING_MASK) {
4991
        env->v_tpr = int_ctl & V_TPR_MASK;
4992
        env->hflags2 |= HF2_VINTR_MASK;
4993
        if (env->eflags & IF_MASK)
4994
            env->hflags2 |= HF2_HIF_MASK;
4995
    }
4996

    
4997
    cpu_load_efer(env, 
4998
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4999
    env->eflags = 0;
5000
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
5001
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5002
    CC_OP = CC_OP_EFLAGS;
5003

    
5004
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
5005
                       env, R_ES);
5006
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
5007
                       env, R_CS);
5008
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
5009
                       env, R_SS);
5010
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
5011
                       env, R_DS);
5012

    
5013
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
5014
    env->eip = EIP;
5015
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
5016
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
5017
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
5018
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
5019
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
5020

    
5021
    /* FIXME: guest state consistency checks */
5022

    
5023
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
5024
        case TLB_CONTROL_DO_NOTHING:
5025
            break;
5026
        case TLB_CONTROL_FLUSH_ALL_ASID:
5027
            /* FIXME: this is not 100% correct but should work for now */
5028
            tlb_flush(env, 1);
5029
        break;
5030
    }
5031

    
5032
    env->hflags2 |= HF2_GIF_MASK;
5033

    
5034
    if (int_ctl & V_IRQ_MASK) {
5035
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
5036
    }
5037

    
5038
    /* maybe we need to inject an event */
5039
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
5040
    if (event_inj & SVM_EVTINJ_VALID) {
5041
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
5042
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
5043
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
5044

    
5045
        qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
5046
        /* FIXME: need to implement valid_err */
5047
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
5048
        case SVM_EVTINJ_TYPE_INTR:
5049
                env->exception_index = vector;
5050
                env->error_code = event_inj_err;
5051
                env->exception_is_int = 0;
5052
                env->exception_next_eip = -1;