Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ a1d8db07

History | View | Annotate | Download (161.3 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

    
20
#include <math.h>
21
#include "exec.h"
22
#include "exec-all.h"
23
#include "host-utils.h"
24
#include "ioport.h"
25

    
26
//#define DEBUG_PCALL
27

    
28

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

    
38

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

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

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

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

    
98
#if defined(CONFIG_SOFTFLOAT)
99
# define floatx_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL )
100
# define floatx_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL )
101
# define floatx_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL )
102
#else
103
# define floatx_lg2 (0.30102999566398119523L)
104
# define floatx_l2e (1.44269504088896340739L)
105
# define floatx_l2t (3.32192809488736234781L)
106
#endif
107

    
108
static const CPU86_LDouble f15rk[7] =
109
{
110
    floatx_zero,
111
    floatx_one,
112
    floatx_pi,
113
    floatx_lg2,
114
    floatx_ln2,
115
    floatx_l2e,
116
    floatx_l2t,
117
};
118

    
119
/* broken thread support */
120

    
121
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
122

    
123
void helper_lock(void)
124
{
125
    spin_lock(&global_cpu_lock);
126
}
127

    
128
void helper_unlock(void)
129
{
130
    spin_unlock(&global_cpu_lock);
131
}
132

    
133
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
134
{
135
    load_eflags(t0, update_mask);
136
}
137

    
138
target_ulong helper_read_eflags(void)
139
{
140
    uint32_t eflags;
141
    eflags = helper_cc_compute_all(CC_OP);
142
    eflags |= (DF & DF_MASK);
143
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
144
    return eflags;
145
}
146

    
147
/* return non zero if error */
148
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
149
                               int selector)
150
{
151
    SegmentCache *dt;
152
    int index;
153
    target_ulong ptr;
154

    
155
    if (selector & 0x4)
156
        dt = &env->ldt;
157
    else
158
        dt = &env->gdt;
159
    index = selector & ~7;
160
    if ((index + 7) > dt->limit)
161
        return -1;
162
    ptr = dt->base + index;
163
    *e1_ptr = ldl_kernel(ptr);
164
    *e2_ptr = ldl_kernel(ptr + 4);
165
    return 0;
166
}
167

    
168
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
169
{
170
    unsigned int limit;
171
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
172
    if (e2 & DESC_G_MASK)
173
        limit = (limit << 12) | 0xfff;
174
    return limit;
175
}
176

    
177
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
178
{
179
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
180
}
181

    
182
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
183
{
184
    sc->base = get_seg_base(e1, e2);
185
    sc->limit = get_seg_limit(e1, e2);
186
    sc->flags = e2;
187
}
188

    
189
/* init the segment cache in vm86 mode. */
190
static inline void load_seg_vm(int seg, int selector)
191
{
192
    selector &= 0xffff;
193
    cpu_x86_load_seg_cache(env, seg, selector,
194
                           (selector << 4), 0xffff, 0);
195
}
196

    
197
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
198
                                       uint32_t *esp_ptr, int dpl)
199
{
200
    int type, index, shift;
201

    
202
#if 0
203
    {
204
        int i;
205
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
206
        for(i=0;i<env->tr.limit;i++) {
207
            printf("%02x ", env->tr.base[i]);
208
            if ((i & 7) == 7) printf("\n");
209
        }
210
        printf("\n");
211
    }
212
#endif
213

    
214
    if (!(env->tr.flags & DESC_P_MASK))
215
        cpu_abort(env, "invalid tss");
216
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
217
    if ((type & 7) != 1)
218
        cpu_abort(env, "invalid tss type");
219
    shift = type >> 3;
220
    index = (dpl * 4 + 2) << shift;
221
    if (index + (4 << shift) - 1 > env->tr.limit)
222
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
223
    if (shift == 0) {
224
        *esp_ptr = lduw_kernel(env->tr.base + index);
225
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
226
    } else {
227
        *esp_ptr = ldl_kernel(env->tr.base + index);
228
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
229
    }
230
}
231

    
232
/* XXX: merge with load_seg() */
233
static void tss_load_seg(int seg_reg, int selector)
234
{
235
    uint32_t e1, e2;
236
    int rpl, dpl, cpl;
237

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

    
282
#define SWITCH_TSS_JMP  0
283
#define SWITCH_TSS_IRET 1
284
#define SWITCH_TSS_CALL 2
285

    
286
/* XXX: restore CPU state in registers (PowerPC case) */
287
static void switch_tss(int tss_selector,
288
                       uint32_t e1, uint32_t e2, int source,
289
                       uint32_t next_eip)
290
{
291
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
292
    target_ulong tss_base;
293
    uint32_t new_regs[8], new_segs[6];
294
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
295
    uint32_t old_eflags, eflags_mask;
296
    SegmentCache *dt;
297
    int index;
298
    target_ulong ptr;
299

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

    
303
    /* if task gate, we read the TSS segment and we load it */
304
    if (type == 5) {
305
        if (!(e2 & DESC_P_MASK))
306
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
307
        tss_selector = e1 >> 16;
308
        if (tss_selector & 4)
309
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
310
        if (load_segment(&e1, &e2, tss_selector) != 0)
311
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
312
        if (e2 & DESC_S_MASK)
313
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
314
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
315
        if ((type & 7) != 1)
316
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
317
    }
318

    
319
    if (!(e2 & DESC_P_MASK))
320
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
321

    
322
    if (type & 8)
323
        tss_limit_max = 103;
324
    else
325
        tss_limit_max = 43;
326
    tss_limit = get_seg_limit(e1, e2);
327
    tss_base = get_seg_base(e1, e2);
328
    if ((tss_selector & 4) != 0 ||
329
        tss_limit < tss_limit_max)
330
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
331
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
332
    if (old_type & 8)
333
        old_tss_limit_max = 103;
334
    else
335
        old_tss_limit_max = 43;
336

    
337
    /* read all the registers from the new TSS */
338
    if (type & 8) {
339
        /* 32 bit */
340
        new_cr3 = ldl_kernel(tss_base + 0x1c);
341
        new_eip = ldl_kernel(tss_base + 0x20);
342
        new_eflags = ldl_kernel(tss_base + 0x24);
343
        for(i = 0; i < 8; i++)
344
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
345
        for(i = 0; i < 6; i++)
346
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
347
        new_ldt = lduw_kernel(tss_base + 0x60);
348
        new_trap = ldl_kernel(tss_base + 0x64);
349
    } else {
350
        /* 16 bit */
351
        new_cr3 = 0;
352
        new_eip = lduw_kernel(tss_base + 0x0e);
353
        new_eflags = lduw_kernel(tss_base + 0x10);
354
        for(i = 0; i < 8; i++)
355
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
356
        for(i = 0; i < 4; i++)
357
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
358
        new_ldt = lduw_kernel(tss_base + 0x2a);
359
        new_segs[R_FS] = 0;
360
        new_segs[R_GS] = 0;
361
        new_trap = 0;
362
    }
363
    /* XXX: avoid a compiler warning, see
364
     http://support.amd.com/us/Processor_TechDocs/24593.pdf
365
     chapters 12.2.5 and 13.2.4 on how to implement TSS Trap bit */
366
    (void)new_trap;
367

    
368
    /* NOTE: we must avoid memory exceptions during the task switch,
369
       so we make dummy accesses before */
370
    /* XXX: it can still fail in some cases, so a bigger hack is
371
       necessary to valid the TLB after having done the accesses */
372

    
373
    v1 = ldub_kernel(env->tr.base);
374
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
375
    stb_kernel(env->tr.base, v1);
376
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
377

    
378
    /* clear busy bit (it is restartable) */
379
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
380
        target_ulong ptr;
381
        uint32_t e2;
382
        ptr = env->gdt.base + (env->tr.selector & ~7);
383
        e2 = ldl_kernel(ptr + 4);
384
        e2 &= ~DESC_TSS_BUSY_MASK;
385
        stl_kernel(ptr + 4, e2);
386
    }
387
    old_eflags = compute_eflags();
388
    if (source == SWITCH_TSS_IRET)
389
        old_eflags &= ~NT_MASK;
390

    
391
    /* save the current state in the old TSS */
392
    if (type & 8) {
393
        /* 32 bit */
394
        stl_kernel(env->tr.base + 0x20, next_eip);
395
        stl_kernel(env->tr.base + 0x24, old_eflags);
396
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
397
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
398
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
399
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
400
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
401
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
402
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
403
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
404
        for(i = 0; i < 6; i++)
405
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
406
    } else {
407
        /* 16 bit */
408
        stw_kernel(env->tr.base + 0x0e, next_eip);
409
        stw_kernel(env->tr.base + 0x10, old_eflags);
410
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
411
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
412
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
413
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
414
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
415
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
416
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
417
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
418
        for(i = 0; i < 4; i++)
419
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
420
    }
421

    
422
    /* now if an exception occurs, it will occurs in the next task
423
       context */
424

    
425
    if (source == SWITCH_TSS_CALL) {
426
        stw_kernel(tss_base, env->tr.selector);
427
        new_eflags |= NT_MASK;
428
    }
429

    
430
    /* set busy bit */
431
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
432
        target_ulong ptr;
433
        uint32_t e2;
434
        ptr = env->gdt.base + (tss_selector & ~7);
435
        e2 = ldl_kernel(ptr + 4);
436
        e2 |= DESC_TSS_BUSY_MASK;
437
        stl_kernel(ptr + 4, e2);
438
    }
439

    
440
    /* set the new CPU state */
441
    /* from this point, any exception which occurs can give problems */
442
    env->cr[0] |= CR0_TS_MASK;
443
    env->hflags |= HF_TS_MASK;
444
    env->tr.selector = tss_selector;
445
    env->tr.base = tss_base;
446
    env->tr.limit = tss_limit;
447
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
448

    
449
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
450
        cpu_x86_update_cr3(env, new_cr3);
451
    }
452

    
453
    /* load all registers without an exception, then reload them with
454
       possible exception */
455
    env->eip = new_eip;
456
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
457
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
458
    if (!(type & 8))
459
        eflags_mask &= 0xffff;
460
    load_eflags(new_eflags, eflags_mask);
461
    /* XXX: what to do in 16 bit case ? */
462
    EAX = new_regs[0];
463
    ECX = new_regs[1];
464
    EDX = new_regs[2];
465
    EBX = new_regs[3];
466
    ESP = new_regs[4];
467
    EBP = new_regs[5];
468
    ESI = new_regs[6];
469
    EDI = new_regs[7];
470
    if (new_eflags & VM_MASK) {
471
        for(i = 0; i < 6; i++)
472
            load_seg_vm(i, new_segs[i]);
473
        /* in vm86, CPL is always 3 */
474
        cpu_x86_set_cpl(env, 3);
475
    } else {
476
        /* CPL is set the RPL of CS */
477
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
478
        /* first just selectors as the rest may trigger exceptions */
479
        for(i = 0; i < 6; i++)
480
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
481
    }
482

    
483
    env->ldt.selector = new_ldt & ~4;
484
    env->ldt.base = 0;
485
    env->ldt.limit = 0;
486
    env->ldt.flags = 0;
487

    
488
    /* load the LDT */
489
    if (new_ldt & 4)
490
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
491

    
492
    if ((new_ldt & 0xfffc) != 0) {
493
        dt = &env->gdt;
494
        index = new_ldt & ~7;
495
        if ((index + 7) > dt->limit)
496
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
497
        ptr = dt->base + index;
498
        e1 = ldl_kernel(ptr);
499
        e2 = ldl_kernel(ptr + 4);
500
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
501
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
502
        if (!(e2 & DESC_P_MASK))
503
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
504
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
505
    }
506

    
507
    /* load the segments */
508
    if (!(new_eflags & VM_MASK)) {
509
        tss_load_seg(R_CS, new_segs[R_CS]);
510
        tss_load_seg(R_SS, new_segs[R_SS]);
511
        tss_load_seg(R_ES, new_segs[R_ES]);
512
        tss_load_seg(R_DS, new_segs[R_DS]);
513
        tss_load_seg(R_FS, new_segs[R_FS]);
514
        tss_load_seg(R_GS, new_segs[R_GS]);
515
    }
516

    
517
    /* check that EIP is in the CS segment limits */
518
    if (new_eip > env->segs[R_CS].limit) {
519
        /* XXX: different exception if CALL ? */
520
        raise_exception_err(EXCP0D_GPF, 0);
521
    }
522

    
523
#ifndef CONFIG_USER_ONLY
524
    /* reset local breakpoints */
525
    if (env->dr[7] & 0x55) {
526
        for (i = 0; i < 4; i++) {
527
            if (hw_breakpoint_enabled(env->dr[7], i) == 0x1)
528
                hw_breakpoint_remove(env, i);
529
        }
530
        env->dr[7] &= ~0x55;
531
    }
532
#endif
533
}
534

    
535
/* check if Port I/O is allowed in TSS */
536
static inline void check_io(int addr, int size)
537
{
538
    int io_offset, val, mask;
539

    
540
    /* TSS must be a valid 32 bit one */
541
    if (!(env->tr.flags & DESC_P_MASK) ||
542
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
543
        env->tr.limit < 103)
544
        goto fail;
545
    io_offset = lduw_kernel(env->tr.base + 0x66);
546
    io_offset += (addr >> 3);
547
    /* Note: the check needs two bytes */
548
    if ((io_offset + 1) > env->tr.limit)
549
        goto fail;
550
    val = lduw_kernel(env->tr.base + io_offset);
551
    val >>= (addr & 7);
552
    mask = (1 << size) - 1;
553
    /* all bits must be zero to allow the I/O */
554
    if ((val & mask) != 0) {
555
    fail:
556
        raise_exception_err(EXCP0D_GPF, 0);
557
    }
558
}
559

    
560
void helper_check_iob(uint32_t t0)
561
{
562
    check_io(t0, 1);
563
}
564

    
565
void helper_check_iow(uint32_t t0)
566
{
567
    check_io(t0, 2);
568
}
569

    
570
void helper_check_iol(uint32_t t0)
571
{
572
    check_io(t0, 4);
573
}
574

    
575
void helper_outb(uint32_t port, uint32_t data)
576
{
577
    cpu_outb(port, data & 0xff);
578
}
579

    
580
target_ulong helper_inb(uint32_t port)
581
{
582
    return cpu_inb(port);
583
}
584

    
585
void helper_outw(uint32_t port, uint32_t data)
586
{
587
    cpu_outw(port, data & 0xffff);
588
}
589

    
590
target_ulong helper_inw(uint32_t port)
591
{
592
    return cpu_inw(port);
593
}
594

    
595
void helper_outl(uint32_t port, uint32_t data)
596
{
597
    cpu_outl(port, data);
598
}
599

    
600
target_ulong helper_inl(uint32_t port)
601
{
602
    return cpu_inl(port);
603
}
604

    
605
static inline unsigned int get_sp_mask(unsigned int e2)
606
{
607
    if (e2 & DESC_B_MASK)
608
        return 0xffffffff;
609
    else
610
        return 0xffff;
611
}
612

    
613
static int exeption_has_error_code(int intno)
614
{
615
        switch(intno) {
616
        case 8:
617
        case 10:
618
        case 11:
619
        case 12:
620
        case 13:
621
        case 14:
622
        case 17:
623
            return 1;
624
        }
625
        return 0;
626
}
627

    
628
#ifdef TARGET_X86_64
629
#define SET_ESP(val, sp_mask)\
630
do {\
631
    if ((sp_mask) == 0xffff)\
632
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
633
    else if ((sp_mask) == 0xffffffffLL)\
634
        ESP = (uint32_t)(val);\
635
    else\
636
        ESP = (val);\
637
} while (0)
638
#else
639
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
640
#endif
641

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

    
646
/* XXX: add a is_user flag to have proper security support */
647
#define PUSHW(ssp, sp, sp_mask, val)\
648
{\
649
    sp -= 2;\
650
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
651
}
652

    
653
#define PUSHL(ssp, sp, sp_mask, val)\
654
{\
655
    sp -= 4;\
656
    stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
657
}
658

    
659
#define POPW(ssp, sp, sp_mask, val)\
660
{\
661
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
662
    sp += 2;\
663
}
664

    
665
#define POPL(ssp, sp, sp_mask, val)\
666
{\
667
    val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
668
    sp += 4;\
669
}
670

    
671
/* protected mode interrupt */
672
static void do_interrupt_protected(int intno, int is_int, int error_code,
673
                                   unsigned int next_eip, int is_hw)
674
{
675
    SegmentCache *dt;
676
    target_ulong ptr, ssp;
677
    int type, dpl, selector, ss_dpl, cpl;
678
    int has_error_code, new_stack, shift;
679
    uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
680
    uint32_t old_eip, sp_mask;
681

    
682
    has_error_code = 0;
683
    if (!is_int && !is_hw)
684
        has_error_code = exeption_has_error_code(intno);
685
    if (is_int)
686
        old_eip = next_eip;
687
    else
688
        old_eip = env->eip;
689

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

    
745
    if (load_segment(&e1, &e2, selector) != 0)
746
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
747
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
748
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
749
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
750
    if (dpl > cpl)
751
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
752
    if (!(e2 & DESC_P_MASK))
753
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
754
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
755
        /* to inner privilege */
756
        get_ss_esp_from_tss(&ss, &esp, dpl);
757
        if ((ss & 0xfffc) == 0)
758
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
759
        if ((ss & 3) != dpl)
760
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
761
        if (load_segment(&ss_e1, &ss_e2, ss) != 0)
762
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
763
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
764
        if (ss_dpl != dpl)
765
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
766
        if (!(ss_e2 & DESC_S_MASK) ||
767
            (ss_e2 & DESC_CS_MASK) ||
768
            !(ss_e2 & DESC_W_MASK))
769
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
770
        if (!(ss_e2 & DESC_P_MASK))
771
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
772
        new_stack = 1;
773
        sp_mask = get_sp_mask(ss_e2);
774
        ssp = get_seg_base(ss_e1, ss_e2);
775
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
776
        /* to same privilege */
777
        if (env->eflags & VM_MASK)
778
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
779
        new_stack = 0;
780
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
781
        ssp = env->segs[R_SS].base;
782
        esp = ESP;
783
        dpl = cpl;
784
    } else {
785
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
786
        new_stack = 0; /* avoid warning */
787
        sp_mask = 0; /* avoid warning */
788
        ssp = 0; /* avoid warning */
789
        esp = 0; /* avoid warning */
790
    }
791

    
792
    shift = type >> 3;
793

    
794
#if 0
795
    /* XXX: check that enough room is available */
796
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
797
    if (env->eflags & VM_MASK)
798
        push_size += 8;
799
    push_size <<= shift;
800
#endif
801
    if (shift == 1) {
802
        if (new_stack) {
803
            if (env->eflags & VM_MASK) {
804
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
805
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
806
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
807
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
808
            }
809
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
810
            PUSHL(ssp, esp, sp_mask, ESP);
811
        }
812
        PUSHL(ssp, esp, sp_mask, compute_eflags());
813
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
814
        PUSHL(ssp, esp, sp_mask, old_eip);
815
        if (has_error_code) {
816
            PUSHL(ssp, esp, sp_mask, error_code);
817
        }
818
    } else {
819
        if (new_stack) {
820
            if (env->eflags & VM_MASK) {
821
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
822
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
823
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
824
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
825
            }
826
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
827
            PUSHW(ssp, esp, sp_mask, ESP);
828
        }
829
        PUSHW(ssp, esp, sp_mask, compute_eflags());
830
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
831
        PUSHW(ssp, esp, sp_mask, old_eip);
832
        if (has_error_code) {
833
            PUSHW(ssp, esp, sp_mask, error_code);
834
        }
835
    }
836

    
837
    if (new_stack) {
838
        if (env->eflags & VM_MASK) {
839
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
840
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
841
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
842
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
843
        }
844
        ss = (ss & ~3) | dpl;
845
        cpu_x86_load_seg_cache(env, R_SS, ss,
846
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
847
    }
848
    SET_ESP(esp, sp_mask);
849

    
850
    selector = (selector & ~3) | dpl;
851
    cpu_x86_load_seg_cache(env, R_CS, selector,
852
                   get_seg_base(e1, e2),
853
                   get_seg_limit(e1, e2),
854
                   e2);
855
    cpu_x86_set_cpl(env, dpl);
856
    env->eip = offset;
857

    
858
    /* interrupt gate clear IF mask */
859
    if ((type & 1) == 0) {
860
        env->eflags &= ~IF_MASK;
861
    }
862
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
863
}
864

    
865
#ifdef TARGET_X86_64
866

    
867
#define PUSHQ(sp, val)\
868
{\
869
    sp -= 8;\
870
    stq_kernel(sp, (val));\
871
}
872

    
873
#define POPQ(sp, val)\
874
{\
875
    val = ldq_kernel(sp);\
876
    sp += 8;\
877
}
878

    
879
static inline target_ulong get_rsp_from_tss(int level)
880
{
881
    int index;
882

    
883
#if 0
884
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
885
           env->tr.base, env->tr.limit);
886
#endif
887

    
888
    if (!(env->tr.flags & DESC_P_MASK))
889
        cpu_abort(env, "invalid tss");
890
    index = 8 * level + 4;
891
    if ((index + 7) > env->tr.limit)
892
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
893
    return ldq_kernel(env->tr.base + index);
894
}
895

    
896
/* 64 bit interrupt */
897
static void do_interrupt64(int intno, int is_int, int error_code,
898
                           target_ulong next_eip, int is_hw)
899
{
900
    SegmentCache *dt;
901
    target_ulong ptr;
902
    int type, dpl, selector, cpl, ist;
903
    int has_error_code, new_stack;
904
    uint32_t e1, e2, e3, ss;
905
    target_ulong old_eip, esp, offset;
906

    
907
    has_error_code = 0;
908
    if (!is_int && !is_hw)
909
        has_error_code = exeption_has_error_code(intno);
910
    if (is_int)
911
        old_eip = next_eip;
912
    else
913
        old_eip = env->eip;
914

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

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

    
983
    PUSHQ(esp, env->segs[R_SS].selector);
984
    PUSHQ(esp, ESP);
985
    PUSHQ(esp, compute_eflags());
986
    PUSHQ(esp, env->segs[R_CS].selector);
987
    PUSHQ(esp, old_eip);
988
    if (has_error_code) {
989
        PUSHQ(esp, error_code);
990
    }
991

    
992
    if (new_stack) {
993
        ss = 0 | dpl;
994
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
995
    }
996
    ESP = esp;
997

    
998
    selector = (selector & ~3) | dpl;
999
    cpu_x86_load_seg_cache(env, R_CS, selector,
1000
                   get_seg_base(e1, e2),
1001
                   get_seg_limit(e1, e2),
1002
                   e2);
1003
    cpu_x86_set_cpl(env, dpl);
1004
    env->eip = offset;
1005

    
1006
    /* interrupt gate clear IF mask */
1007
    if ((type & 1) == 0) {
1008
        env->eflags &= ~IF_MASK;
1009
    }
1010
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
1011
}
1012
#endif
1013

    
1014
#ifdef TARGET_X86_64
1015
#if defined(CONFIG_USER_ONLY)
1016
void helper_syscall(int next_eip_addend)
1017
{
1018
    env->exception_index = EXCP_SYSCALL;
1019
    env->exception_next_eip = env->eip + next_eip_addend;
1020
    cpu_loop_exit();
1021
}
1022
#else
1023
void helper_syscall(int next_eip_addend)
1024
{
1025
    int selector;
1026

    
1027
    if (!(env->efer & MSR_EFER_SCE)) {
1028
        raise_exception_err(EXCP06_ILLOP, 0);
1029
    }
1030
    selector = (env->star >> 32) & 0xffff;
1031
    if (env->hflags & HF_LMA_MASK) {
1032
        int code64;
1033

    
1034
        ECX = env->eip + next_eip_addend;
1035
        env->regs[11] = compute_eflags();
1036

    
1037
        code64 = env->hflags & HF_CS64_MASK;
1038

    
1039
        cpu_x86_set_cpl(env, 0);
1040
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1041
                           0, 0xffffffff,
1042
                               DESC_G_MASK | DESC_P_MASK |
1043
                               DESC_S_MASK |
1044
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1045
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1046
                               0, 0xffffffff,
1047
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1048
                               DESC_S_MASK |
1049
                               DESC_W_MASK | DESC_A_MASK);
1050
        env->eflags &= ~env->fmask;
1051
        load_eflags(env->eflags, 0);
1052
        if (code64)
1053
            env->eip = env->lstar;
1054
        else
1055
            env->eip = env->cstar;
1056
    } else {
1057
        ECX = (uint32_t)(env->eip + next_eip_addend);
1058

    
1059
        cpu_x86_set_cpl(env, 0);
1060
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1061
                           0, 0xffffffff,
1062
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1063
                               DESC_S_MASK |
1064
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1065
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1066
                               0, 0xffffffff,
1067
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1068
                               DESC_S_MASK |
1069
                               DESC_W_MASK | DESC_A_MASK);
1070
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1071
        env->eip = (uint32_t)env->star;
1072
    }
1073
}
1074
#endif
1075
#endif
1076

    
1077
#ifdef TARGET_X86_64
1078
void helper_sysret(int dflag)
1079
{
1080
    int cpl, selector;
1081

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

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

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

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

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

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

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

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

    
1201
#if !defined(CONFIG_USER_ONLY)
1202
static void handle_even_inj(int intno, int is_int, int error_code,
1203
                int is_hw, int rm)
1204
{
1205
    uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1206
    if (!(event_inj & SVM_EVTINJ_VALID)) {
1207
            int type;
1208
            if (is_int)
1209
                    type = SVM_EVTINJ_TYPE_SOFT;
1210
            else
1211
                    type = SVM_EVTINJ_TYPE_EXEPT;
1212
            event_inj = intno | type | SVM_EVTINJ_VALID;
1213
            if (!rm && exeption_has_error_code(intno)) {
1214
                    event_inj |= SVM_EVTINJ_VALID_ERR;
1215
                    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err), error_code);
1216
            }
1217
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj);
1218
    }
1219
}
1220
#endif
1221

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

    
1282
#if !defined(CONFIG_USER_ONLY)
1283
    if (env->hflags & HF_SVMI_MASK) {
1284
            uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1285
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
1286
    }
1287
#endif
1288
}
1289

    
1290
/* This should come from sysemu.h - if we could include it here... */
1291
void qemu_system_reset_request(void);
1292

    
1293
/*
1294
 * Check nested exceptions and change to double or triple fault if
1295
 * needed. It should only be called, if this is not an interrupt.
1296
 * Returns the new exception number.
1297
 */
1298
static int check_exception(int intno, int *error_code)
1299
{
1300
    int first_contributory = env->old_exception == 0 ||
1301
                              (env->old_exception >= 10 &&
1302
                               env->old_exception <= 13);
1303
    int second_contributory = intno == 0 ||
1304
                               (intno >= 10 && intno <= 13);
1305

    
1306
    qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
1307
                env->old_exception, intno);
1308

    
1309
#if !defined(CONFIG_USER_ONLY)
1310
    if (env->old_exception == EXCP08_DBLE) {
1311
        if (env->hflags & HF_SVMI_MASK)
1312
            helper_vmexit(SVM_EXIT_SHUTDOWN, 0); /* does not return */
1313

    
1314
        qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1315

    
1316
        qemu_system_reset_request();
1317
        return EXCP_HLT;
1318
    }
1319
#endif
1320

    
1321
    if ((first_contributory && second_contributory)
1322
        || (env->old_exception == EXCP0E_PAGE &&
1323
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1324
        intno = EXCP08_DBLE;
1325
        *error_code = 0;
1326
    }
1327

    
1328
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1329
        (intno == EXCP08_DBLE))
1330
        env->old_exception = intno;
1331

    
1332
    return intno;
1333
}
1334

    
1335
/*
1336
 * Signal an interruption. It is executed in the main CPU loop.
1337
 * is_int is TRUE if coming from the int instruction. next_eip is the
1338
 * EIP value AFTER the interrupt instruction. It is only relevant if
1339
 * is_int is TRUE.
1340
 */
1341
static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
1342
                                          int next_eip_addend)
1343
{
1344
    if (!is_int) {
1345
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1346
        intno = check_exception(intno, &error_code);
1347
    } else {
1348
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1349
    }
1350

    
1351
    env->exception_index = intno;
1352
    env->error_code = error_code;
1353
    env->exception_is_int = is_int;
1354
    env->exception_next_eip = env->eip + next_eip_addend;
1355
    cpu_loop_exit();
1356
}
1357

    
1358
/* shortcuts to generate exceptions */
1359

    
1360
void raise_exception_err(int exception_index, int error_code)
1361
{
1362
    raise_interrupt(exception_index, 0, error_code, 0);
1363
}
1364

    
1365
void raise_exception(int exception_index)
1366
{
1367
    raise_interrupt(exception_index, 0, 0, 0);
1368
}
1369

    
1370
void raise_exception_env(int exception_index, CPUState *nenv)
1371
{
1372
    env = nenv;
1373
    raise_exception(exception_index);
1374
}
1375
/* SMM support */
1376

    
1377
#if defined(CONFIG_USER_ONLY)
1378

    
1379
void do_smm_enter(void)
1380
{
1381
}
1382

    
1383
void helper_rsm(void)
1384
{
1385
}
1386

    
1387
#else
1388

    
1389
#ifdef TARGET_X86_64
1390
#define SMM_REVISION_ID 0x00020064
1391
#else
1392
#define SMM_REVISION_ID 0x00020000
1393
#endif
1394

    
1395
void do_smm_enter(void)
1396
{
1397
    target_ulong sm_state;
1398
    SegmentCache *dt;
1399
    int i, offset;
1400

    
1401
    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
1402
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1403

    
1404
    env->hflags |= HF_SMM_MASK;
1405
    cpu_smm_update(env);
1406

    
1407
    sm_state = env->smbase + 0x8000;
1408

    
1409
#ifdef TARGET_X86_64
1410
    for(i = 0; i < 6; i++) {
1411
        dt = &env->segs[i];
1412
        offset = 0x7e00 + i * 16;
1413
        stw_phys(sm_state + offset, dt->selector);
1414
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1415
        stl_phys(sm_state + offset + 4, dt->limit);
1416
        stq_phys(sm_state + offset + 8, dt->base);
1417
    }
1418

    
1419
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1420
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1421

    
1422
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1423
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1424
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1425
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1426

    
1427
    stq_phys(sm_state + 0x7e88, env->idt.base);
1428
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1429

    
1430
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1431
    stq_phys(sm_state + 0x7e98, env->tr.base);
1432
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1433
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1434

    
1435
    stq_phys(sm_state + 0x7ed0, env->efer);
1436

    
1437
    stq_phys(sm_state + 0x7ff8, EAX);
1438
    stq_phys(sm_state + 0x7ff0, ECX);
1439
    stq_phys(sm_state + 0x7fe8, EDX);
1440
    stq_phys(sm_state + 0x7fe0, EBX);
1441
    stq_phys(sm_state + 0x7fd8, ESP);
1442
    stq_phys(sm_state + 0x7fd0, EBP);
1443
    stq_phys(sm_state + 0x7fc8, ESI);
1444
    stq_phys(sm_state + 0x7fc0, EDI);
1445
    for(i = 8; i < 16; i++)
1446
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1447
    stq_phys(sm_state + 0x7f78, env->eip);
1448
    stl_phys(sm_state + 0x7f70, compute_eflags());
1449
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1450
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1451

    
1452
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1453
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1454
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1455

    
1456
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1457
    stl_phys(sm_state + 0x7f00, env->smbase);
1458
#else
1459
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1460
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1461
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1462
    stl_phys(sm_state + 0x7ff0, env->eip);
1463
    stl_phys(sm_state + 0x7fec, EDI);
1464
    stl_phys(sm_state + 0x7fe8, ESI);
1465
    stl_phys(sm_state + 0x7fe4, EBP);
1466
    stl_phys(sm_state + 0x7fe0, ESP);
1467
    stl_phys(sm_state + 0x7fdc, EBX);
1468
    stl_phys(sm_state + 0x7fd8, EDX);
1469
    stl_phys(sm_state + 0x7fd4, ECX);
1470
    stl_phys(sm_state + 0x7fd0, EAX);
1471
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1472
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1473

    
1474
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1475
    stl_phys(sm_state + 0x7f64, env->tr.base);
1476
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1477
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1478

    
1479
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1480
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1481
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1482
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1483

    
1484
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1485
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1486

    
1487
    stl_phys(sm_state + 0x7f58, env->idt.base);
1488
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1489

    
1490
    for(i = 0; i < 6; i++) {
1491
        dt = &env->segs[i];
1492
        if (i < 3)
1493
            offset = 0x7f84 + i * 12;
1494
        else
1495
            offset = 0x7f2c + (i - 3) * 12;
1496
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1497
        stl_phys(sm_state + offset + 8, dt->base);
1498
        stl_phys(sm_state + offset + 4, dt->limit);
1499
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1500
    }
1501
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1502

    
1503
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1504
    stl_phys(sm_state + 0x7ef8, env->smbase);
1505
#endif
1506
    /* init SMM cpu state */
1507

    
1508
#ifdef TARGET_X86_64
1509
    cpu_load_efer(env, 0);
1510
#endif
1511
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1512
    env->eip = 0x00008000;
1513
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1514
                           0xffffffff, 0);
1515
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1516
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1517
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1518
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1519
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1520

    
1521
    cpu_x86_update_cr0(env,
1522
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1523
    cpu_x86_update_cr4(env, 0);
1524
    env->dr[7] = 0x00000400;
1525
    CC_OP = CC_OP_EFLAGS;
1526
}
1527

    
1528
void helper_rsm(void)
1529
{
1530
    target_ulong sm_state;
1531
    int i, offset;
1532
    uint32_t val;
1533

    
1534
    sm_state = env->smbase + 0x8000;
1535
#ifdef TARGET_X86_64
1536
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1537

    
1538
    for(i = 0; i < 6; i++) {
1539
        offset = 0x7e00 + i * 16;
1540
        cpu_x86_load_seg_cache(env, i,
1541
                               lduw_phys(sm_state + offset),
1542
                               ldq_phys(sm_state + offset + 8),
1543
                               ldl_phys(sm_state + offset + 4),
1544
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1545
    }
1546

    
1547
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1548
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1549

    
1550
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1551
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1552
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1553
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1554

    
1555
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1556
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1557

    
1558
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1559
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1560
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1561
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1562

    
1563
    EAX = ldq_phys(sm_state + 0x7ff8);
1564
    ECX = ldq_phys(sm_state + 0x7ff0);
1565
    EDX = ldq_phys(sm_state + 0x7fe8);
1566
    EBX = ldq_phys(sm_state + 0x7fe0);
1567
    ESP = ldq_phys(sm_state + 0x7fd8);
1568
    EBP = ldq_phys(sm_state + 0x7fd0);
1569
    ESI = ldq_phys(sm_state + 0x7fc8);
1570
    EDI = ldq_phys(sm_state + 0x7fc0);
1571
    for(i = 8; i < 16; i++)
1572
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1573
    env->eip = ldq_phys(sm_state + 0x7f78);
1574
    load_eflags(ldl_phys(sm_state + 0x7f70),
1575
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1576
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1577
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1578

    
1579
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1580
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1581
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1582

    
1583
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1584
    if (val & 0x20000) {
1585
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1586
    }
1587
#else
1588
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1589
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1590
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1591
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1592
    env->eip = ldl_phys(sm_state + 0x7ff0);
1593
    EDI = ldl_phys(sm_state + 0x7fec);
1594
    ESI = ldl_phys(sm_state + 0x7fe8);
1595
    EBP = ldl_phys(sm_state + 0x7fe4);
1596
    ESP = ldl_phys(sm_state + 0x7fe0);
1597
    EBX = ldl_phys(sm_state + 0x7fdc);
1598
    EDX = ldl_phys(sm_state + 0x7fd8);
1599
    ECX = ldl_phys(sm_state + 0x7fd4);
1600
    EAX = ldl_phys(sm_state + 0x7fd0);
1601
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1602
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1603

    
1604
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1605
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1606
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1607
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1608

    
1609
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1610
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1611
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1612
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1613

    
1614
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1615
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1616

    
1617
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1618
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1619

    
1620
    for(i = 0; i < 6; i++) {
1621
        if (i < 3)
1622
            offset = 0x7f84 + i * 12;
1623
        else
1624
            offset = 0x7f2c + (i - 3) * 12;
1625
        cpu_x86_load_seg_cache(env, i,
1626
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1627
                               ldl_phys(sm_state + offset + 8),
1628
                               ldl_phys(sm_state + offset + 4),
1629
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1630
    }
1631
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1632

    
1633
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1634
    if (val & 0x20000) {
1635
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1636
    }
1637
#endif
1638
    CC_OP = CC_OP_EFLAGS;
1639
    env->hflags &= ~HF_SMM_MASK;
1640
    cpu_smm_update(env);
1641

    
1642
    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
1643
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1644
}
1645

    
1646
#endif /* !CONFIG_USER_ONLY */
1647

    
1648

    
1649
/* division, flags are undefined */
1650

    
1651
void helper_divb_AL(target_ulong t0)
1652
{
1653
    unsigned int num, den, q, r;
1654

    
1655
    num = (EAX & 0xffff);
1656
    den = (t0 & 0xff);
1657
    if (den == 0) {
1658
        raise_exception(EXCP00_DIVZ);
1659
    }
1660
    q = (num / den);
1661
    if (q > 0xff)
1662
        raise_exception(EXCP00_DIVZ);
1663
    q &= 0xff;
1664
    r = (num % den) & 0xff;
1665
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1666
}
1667

    
1668
void helper_idivb_AL(target_ulong t0)
1669
{
1670
    int num, den, q, r;
1671

    
1672
    num = (int16_t)EAX;
1673
    den = (int8_t)t0;
1674
    if (den == 0) {
1675
        raise_exception(EXCP00_DIVZ);
1676
    }
1677
    q = (num / den);
1678
    if (q != (int8_t)q)
1679
        raise_exception(EXCP00_DIVZ);
1680
    q &= 0xff;
1681
    r = (num % den) & 0xff;
1682
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1683
}
1684

    
1685
void helper_divw_AX(target_ulong t0)
1686
{
1687
    unsigned int num, den, q, r;
1688

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

    
1703
void helper_idivw_AX(target_ulong t0)
1704
{
1705
    int num, den, q, r;
1706

    
1707
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1708
    den = (int16_t)t0;
1709
    if (den == 0) {
1710
        raise_exception(EXCP00_DIVZ);
1711
    }
1712
    q = (num / den);
1713
    if (q != (int16_t)q)
1714
        raise_exception(EXCP00_DIVZ);
1715
    q &= 0xffff;
1716
    r = (num % den) & 0xffff;
1717
    EAX = (EAX & ~0xffff) | q;
1718
    EDX = (EDX & ~0xffff) | r;
1719
}
1720

    
1721
void helper_divl_EAX(target_ulong t0)
1722
{
1723
    unsigned int den, r;
1724
    uint64_t num, q;
1725

    
1726
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1727
    den = t0;
1728
    if (den == 0) {
1729
        raise_exception(EXCP00_DIVZ);
1730
    }
1731
    q = (num / den);
1732
    r = (num % den);
1733
    if (q > 0xffffffff)
1734
        raise_exception(EXCP00_DIVZ);
1735
    EAX = (uint32_t)q;
1736
    EDX = (uint32_t)r;
1737
}
1738

    
1739
void helper_idivl_EAX(target_ulong t0)
1740
{
1741
    int den, r;
1742
    int64_t num, q;
1743

    
1744
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1745
    den = t0;
1746
    if (den == 0) {
1747
        raise_exception(EXCP00_DIVZ);
1748
    }
1749
    q = (num / den);
1750
    r = (num % den);
1751
    if (q != (int32_t)q)
1752
        raise_exception(EXCP00_DIVZ);
1753
    EAX = (uint32_t)q;
1754
    EDX = (uint32_t)r;
1755
}
1756

    
1757
/* bcd */
1758

    
1759
/* XXX: exception */
1760
void helper_aam(int base)
1761
{
1762
    int al, ah;
1763
    al = EAX & 0xff;
1764
    ah = al / base;
1765
    al = al % base;
1766
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1767
    CC_DST = al;
1768
}
1769

    
1770
void helper_aad(int base)
1771
{
1772
    int al, ah;
1773
    al = EAX & 0xff;
1774
    ah = (EAX >> 8) & 0xff;
1775
    al = ((ah * base) + al) & 0xff;
1776
    EAX = (EAX & ~0xffff) | al;
1777
    CC_DST = al;
1778
}
1779

    
1780
void helper_aaa(void)
1781
{
1782
    int icarry;
1783
    int al, ah, af;
1784
    int eflags;
1785

    
1786
    eflags = helper_cc_compute_all(CC_OP);
1787
    af = eflags & CC_A;
1788
    al = EAX & 0xff;
1789
    ah = (EAX >> 8) & 0xff;
1790

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

    
1804
void helper_aas(void)
1805
{
1806
    int icarry;
1807
    int al, ah, af;
1808
    int eflags;
1809

    
1810
    eflags = helper_cc_compute_all(CC_OP);
1811
    af = eflags & CC_A;
1812
    al = EAX & 0xff;
1813
    ah = (EAX >> 8) & 0xff;
1814

    
1815
    icarry = (al < 6);
1816
    if (((al & 0x0f) > 9 ) || af) {
1817
        al = (al - 6) & 0x0f;
1818
        ah = (ah - 1 - icarry) & 0xff;
1819
        eflags |= CC_C | CC_A;
1820
    } else {
1821
        eflags &= ~(CC_C | CC_A);
1822
        al &= 0x0f;
1823
    }
1824
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1825
    CC_SRC = eflags;
1826
}
1827

    
1828
void helper_daa(void)
1829
{
1830
    int al, af, cf;
1831
    int eflags;
1832

    
1833
    eflags = helper_cc_compute_all(CC_OP);
1834
    cf = eflags & CC_C;
1835
    af = eflags & CC_A;
1836
    al = EAX & 0xff;
1837

    
1838
    eflags = 0;
1839
    if (((al & 0x0f) > 9 ) || af) {
1840
        al = (al + 6) & 0xff;
1841
        eflags |= CC_A;
1842
    }
1843
    if ((al > 0x9f) || cf) {
1844
        al = (al + 0x60) & 0xff;
1845
        eflags |= CC_C;
1846
    }
1847
    EAX = (EAX & ~0xff) | al;
1848
    /* well, speed is not an issue here, so we compute the flags by hand */
1849
    eflags |= (al == 0) << 6; /* zf */
1850
    eflags |= parity_table[al]; /* pf */
1851
    eflags |= (al & 0x80); /* sf */
1852
    CC_SRC = eflags;
1853
}
1854

    
1855
void helper_das(void)
1856
{
1857
    int al, al1, af, cf;
1858
    int eflags;
1859

    
1860
    eflags = helper_cc_compute_all(CC_OP);
1861
    cf = eflags & CC_C;
1862
    af = eflags & CC_A;
1863
    al = EAX & 0xff;
1864

    
1865
    eflags = 0;
1866
    al1 = al;
1867
    if (((al & 0x0f) > 9 ) || af) {
1868
        eflags |= CC_A;
1869
        if (al < 6 || cf)
1870
            eflags |= CC_C;
1871
        al = (al - 6) & 0xff;
1872
    }
1873
    if ((al1 > 0x99) || cf) {
1874
        al = (al - 0x60) & 0xff;
1875
        eflags |= CC_C;
1876
    }
1877
    EAX = (EAX & ~0xff) | al;
1878
    /* well, speed is not an issue here, so we compute the flags by hand */
1879
    eflags |= (al == 0) << 6; /* zf */
1880
    eflags |= parity_table[al]; /* pf */
1881
    eflags |= (al & 0x80); /* sf */
1882
    CC_SRC = eflags;
1883
}
1884

    
1885
void helper_into(int next_eip_addend)
1886
{
1887
    int eflags;
1888
    eflags = helper_cc_compute_all(CC_OP);
1889
    if (eflags & CC_O) {
1890
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1891
    }
1892
}
1893

    
1894
void helper_cmpxchg8b(target_ulong a0)
1895
{
1896
    uint64_t d;
1897
    int eflags;
1898

    
1899
    eflags = helper_cc_compute_all(CC_OP);
1900
    d = ldq(a0);
1901
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1902
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1903
        eflags |= CC_Z;
1904
    } else {
1905
        /* always do the store */
1906
        stq(a0, d); 
1907
        EDX = (uint32_t)(d >> 32);
1908
        EAX = (uint32_t)d;
1909
        eflags &= ~CC_Z;
1910
    }
1911
    CC_SRC = eflags;
1912
}
1913

    
1914
#ifdef TARGET_X86_64
1915
void helper_cmpxchg16b(target_ulong a0)
1916
{
1917
    uint64_t d0, d1;
1918
    int eflags;
1919

    
1920
    if ((a0 & 0xf) != 0)
1921
        raise_exception(EXCP0D_GPF);
1922
    eflags = helper_cc_compute_all(CC_OP);
1923
    d0 = ldq(a0);
1924
    d1 = ldq(a0 + 8);
1925
    if (d0 == EAX && d1 == EDX) {
1926
        stq(a0, EBX);
1927
        stq(a0 + 8, ECX);
1928
        eflags |= CC_Z;
1929
    } else {
1930
        /* always do the store */
1931
        stq(a0, d0); 
1932
        stq(a0 + 8, d1); 
1933
        EDX = d1;
1934
        EAX = d0;
1935
        eflags &= ~CC_Z;
1936
    }
1937
    CC_SRC = eflags;
1938
}
1939
#endif
1940

    
1941
void helper_single_step(void)
1942
{
1943
#ifndef CONFIG_USER_ONLY
1944
    check_hw_breakpoints(env, 1);
1945
    env->dr[6] |= DR6_BS;
1946
#endif
1947
    raise_exception(EXCP01_DB);
1948
}
1949

    
1950
void helper_cpuid(void)
1951
{
1952
    uint32_t eax, ebx, ecx, edx;
1953

    
1954
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1955

    
1956
    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
1957
    EAX = eax;
1958
    EBX = ebx;
1959
    ECX = ecx;
1960
    EDX = edx;
1961
}
1962

    
1963
void helper_enter_level(int level, int data32, target_ulong t1)
1964
{
1965
    target_ulong ssp;
1966
    uint32_t esp_mask, esp, ebp;
1967

    
1968
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1969
    ssp = env->segs[R_SS].base;
1970
    ebp = EBP;
1971
    esp = ESP;
1972
    if (data32) {
1973
        /* 32 bit */
1974
        esp -= 4;
1975
        while (--level) {
1976
            esp -= 4;
1977
            ebp -= 4;
1978
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1979
        }
1980
        esp -= 4;
1981
        stl(ssp + (esp & esp_mask), t1);
1982
    } else {
1983
        /* 16 bit */
1984
        esp -= 2;
1985
        while (--level) {
1986
            esp -= 2;
1987
            ebp -= 2;
1988
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1989
        }
1990
        esp -= 2;
1991
        stw(ssp + (esp & esp_mask), t1);
1992
    }
1993
}
1994

    
1995
#ifdef TARGET_X86_64
1996
void helper_enter64_level(int level, int data64, target_ulong t1)
1997
{
1998
    target_ulong esp, ebp;
1999
    ebp = EBP;
2000
    esp = ESP;
2001

    
2002
    if (data64) {
2003
        /* 64 bit */
2004
        esp -= 8;
2005
        while (--level) {
2006
            esp -= 8;
2007
            ebp -= 8;
2008
            stq(esp, ldq(ebp));
2009
        }
2010
        esp -= 8;
2011
        stq(esp, t1);
2012
    } else {
2013
        /* 16 bit */
2014
        esp -= 2;
2015
        while (--level) {
2016
            esp -= 2;
2017
            ebp -= 2;
2018
            stw(esp, lduw(ebp));
2019
        }
2020
        esp -= 2;
2021
        stw(esp, t1);
2022
    }
2023
}
2024
#endif
2025

    
2026
void helper_lldt(int selector)
2027
{
2028
    SegmentCache *dt;
2029
    uint32_t e1, e2;
2030
    int index, entry_limit;
2031
    target_ulong ptr;
2032

    
2033
    selector &= 0xffff;
2034
    if ((selector & 0xfffc) == 0) {
2035
        /* XXX: NULL selector case: invalid LDT */
2036
        env->ldt.base = 0;
2037
        env->ldt.limit = 0;
2038
    } else {
2039
        if (selector & 0x4)
2040
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2041
        dt = &env->gdt;
2042
        index = selector & ~7;
2043
#ifdef TARGET_X86_64
2044
        if (env->hflags & HF_LMA_MASK)
2045
            entry_limit = 15;
2046
        else
2047
#endif
2048
            entry_limit = 7;
2049
        if ((index + entry_limit) > dt->limit)
2050
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2051
        ptr = dt->base + index;
2052
        e1 = ldl_kernel(ptr);
2053
        e2 = ldl_kernel(ptr + 4);
2054
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2055
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2056
        if (!(e2 & DESC_P_MASK))
2057
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2058
#ifdef TARGET_X86_64
2059
        if (env->hflags & HF_LMA_MASK) {
2060
            uint32_t e3;
2061
            e3 = ldl_kernel(ptr + 8);
2062
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2063
            env->ldt.base |= (target_ulong)e3 << 32;
2064
        } else
2065
#endif
2066
        {
2067
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2068
        }
2069
    }
2070
    env->ldt.selector = selector;
2071
}
2072

    
2073
void helper_ltr(int selector)
2074
{
2075
    SegmentCache *dt;
2076
    uint32_t e1, e2;
2077
    int index, type, entry_limit;
2078
    target_ulong ptr;
2079

    
2080
    selector &= 0xffff;
2081
    if ((selector & 0xfffc) == 0) {
2082
        /* NULL selector case: invalid TR */
2083
        env->tr.base = 0;
2084
        env->tr.limit = 0;
2085
        env->tr.flags = 0;
2086
    } else {
2087
        if (selector & 0x4)
2088
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2089
        dt = &env->gdt;
2090
        index = selector & ~7;
2091
#ifdef TARGET_X86_64
2092
        if (env->hflags & HF_LMA_MASK)
2093
            entry_limit = 15;
2094
        else
2095
#endif
2096
            entry_limit = 7;
2097
        if ((index + entry_limit) > dt->limit)
2098
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2099
        ptr = dt->base + index;
2100
        e1 = ldl_kernel(ptr);
2101
        e2 = ldl_kernel(ptr + 4);
2102
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2103
        if ((e2 & DESC_S_MASK) ||
2104
            (type != 1 && type != 9))
2105
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2106
        if (!(e2 & DESC_P_MASK))
2107
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2108
#ifdef TARGET_X86_64
2109
        if (env->hflags & HF_LMA_MASK) {
2110
            uint32_t e3, e4;
2111
            e3 = ldl_kernel(ptr + 8);
2112
            e4 = ldl_kernel(ptr + 12);
2113
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2114
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2115
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2116
            env->tr.base |= (target_ulong)e3 << 32;
2117
        } else
2118
#endif
2119
        {
2120
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2121
        }
2122
        e2 |= DESC_TSS_BUSY_MASK;
2123
        stl_kernel(ptr + 4, e2);
2124
    }
2125
    env->tr.selector = selector;
2126
}
2127

    
2128
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2129
void helper_load_seg(int seg_reg, int selector)
2130
{
2131
    uint32_t e1, e2;
2132
    int cpl, dpl, rpl;
2133
    SegmentCache *dt;
2134
    int index;
2135
    target_ulong ptr;
2136

    
2137
    selector &= 0xffff;
2138
    cpl = env->hflags & HF_CPL_MASK;
2139
    if ((selector & 0xfffc) == 0) {
2140
        /* null selector case */
2141
        if (seg_reg == R_SS
2142
#ifdef TARGET_X86_64
2143
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2144
#endif
2145
            )
2146
            raise_exception_err(EXCP0D_GPF, 0);
2147
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2148
    } else {
2149

    
2150
        if (selector & 0x4)
2151
            dt = &env->ldt;
2152
        else
2153
            dt = &env->gdt;
2154
        index = selector & ~7;
2155
        if ((index + 7) > dt->limit)
2156
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2157
        ptr = dt->base + index;
2158
        e1 = ldl_kernel(ptr);
2159
        e2 = ldl_kernel(ptr + 4);
2160

    
2161
        if (!(e2 & DESC_S_MASK))
2162
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2163
        rpl = selector & 3;
2164
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2165
        if (seg_reg == R_SS) {
2166
            /* must be writable segment */
2167
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2168
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2169
            if (rpl != cpl || dpl != cpl)
2170
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2171
        } else {
2172
            /* must be readable segment */
2173
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2174
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2175

    
2176
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2177
                /* if not conforming code, test rights */
2178
                if (dpl < cpl || dpl < rpl)
2179
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2180
            }
2181
        }
2182

    
2183
        if (!(e2 & DESC_P_MASK)) {
2184
            if (seg_reg == R_SS)
2185
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2186
            else
2187
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2188
        }
2189

    
2190
        /* set the access bit if not already set */
2191
        if (!(e2 & DESC_A_MASK)) {
2192
            e2 |= DESC_A_MASK;
2193
            stl_kernel(ptr + 4, e2);
2194
        }
2195

    
2196
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2197
                       get_seg_base(e1, e2),
2198
                       get_seg_limit(e1, e2),
2199
                       e2);
2200
#if 0
2201
        qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2202
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2203
#endif
2204
    }
2205
}
2206

    
2207
/* protected mode jump */
2208
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2209
                           int next_eip_addend)
2210
{
2211
    int gate_cs, type;
2212
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2213
    target_ulong next_eip;
2214

    
2215
    if ((new_cs & 0xfffc) == 0)
2216
        raise_exception_err(EXCP0D_GPF, 0);
2217
    if (load_segment(&e1, &e2, new_cs) != 0)
2218
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2219
    cpl = env->hflags & HF_CPL_MASK;
2220
    if (e2 & DESC_S_MASK) {
2221
        if (!(e2 & DESC_CS_MASK))
2222
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2223
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2224
        if (e2 & DESC_C_MASK) {
2225
            /* conforming code segment */
2226
            if (dpl > cpl)
2227
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2228
        } else {
2229
            /* non conforming code segment */
2230
            rpl = new_cs & 3;
2231
            if (rpl > cpl)
2232
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2233
            if (dpl != cpl)
2234
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2235
        }
2236
        if (!(e2 & DESC_P_MASK))
2237
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2238
        limit = get_seg_limit(e1, e2);
2239
        if (new_eip > limit &&
2240
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2241
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2242
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2243
                       get_seg_base(e1, e2), limit, e2);
2244
        EIP = new_eip;
2245
    } else {
2246
        /* jump to call or task gate */
2247
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2248
        rpl = new_cs & 3;
2249
        cpl = env->hflags & HF_CPL_MASK;
2250
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2251
        switch(type) {
2252
        case 1: /* 286 TSS */
2253
        case 9: /* 386 TSS */
2254
        case 5: /* task gate */
2255
            if (dpl < cpl || dpl < rpl)
2256
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2257
            next_eip = env->eip + next_eip_addend;
2258
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2259
            CC_OP = CC_OP_EFLAGS;
2260
            break;
2261
        case 4: /* 286 call gate */
2262
        case 12: /* 386 call gate */
2263
            if ((dpl < cpl) || (dpl < rpl))
2264
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2265
            if (!(e2 & DESC_P_MASK))
2266
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2267
            gate_cs = e1 >> 16;
2268
            new_eip = (e1 & 0xffff);
2269
            if (type == 12)
2270
                new_eip |= (e2 & 0xffff0000);
2271
            if (load_segment(&e1, &e2, gate_cs) != 0)
2272
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2273
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2274
            /* must be code segment */
2275
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2276
                 (DESC_S_MASK | DESC_CS_MASK)))
2277
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2278
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2279
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2280
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2281
            if (!(e2 & DESC_P_MASK))
2282
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2283
            limit = get_seg_limit(e1, e2);
2284
            if (new_eip > limit)
2285
                raise_exception_err(EXCP0D_GPF, 0);
2286
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2287
                                   get_seg_base(e1, e2), limit, e2);
2288
            EIP = new_eip;
2289
            break;
2290
        default:
2291
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2292
            break;
2293
        }
2294
    }
2295
}
2296

    
2297
/* real mode call */
2298
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2299
                       int shift, int next_eip)
2300
{
2301
    int new_eip;
2302
    uint32_t esp, esp_mask;
2303
    target_ulong ssp;
2304

    
2305
    new_eip = new_eip1;
2306
    esp = ESP;
2307
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2308
    ssp = env->segs[R_SS].base;
2309
    if (shift) {
2310
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2311
        PUSHL(ssp, esp, esp_mask, next_eip);
2312
    } else {
2313
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2314
        PUSHW(ssp, esp, esp_mask, next_eip);
2315
    }
2316

    
2317
    SET_ESP(esp, esp_mask);
2318
    env->eip = new_eip;
2319
    env->segs[R_CS].selector = new_cs;
2320
    env->segs[R_CS].base = (new_cs << 4);
2321
}
2322

    
2323
/* protected mode call */
2324
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2325
                            int shift, int next_eip_addend)
2326
{
2327
    int new_stack, i;
2328
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2329
    uint32_t ss = 0, ss_e1 = 0, ss_e2 = 0, sp, type, ss_dpl, sp_mask;
2330
    uint32_t val, limit, old_sp_mask;
2331
    target_ulong ssp, old_ssp, next_eip;
2332

    
2333
    next_eip = env->eip + next_eip_addend;
2334
    LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
2335
    LOG_PCALL_STATE(env);
2336
    if ((new_cs & 0xfffc) == 0)
2337
        raise_exception_err(EXCP0D_GPF, 0);
2338
    if (load_segment(&e1, &e2, new_cs) != 0)
2339
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2340
    cpl = env->hflags & HF_CPL_MASK;
2341
    LOG_PCALL("desc=%08x:%08x\n", e1, e2);
2342
    if (e2 & DESC_S_MASK) {
2343
        if (!(e2 & DESC_CS_MASK))
2344
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2345
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2346
        if (e2 & DESC_C_MASK) {
2347
            /* conforming code segment */
2348
            if (dpl > cpl)
2349
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2350
        } else {
2351
            /* non conforming code segment */
2352
            rpl = new_cs & 3;
2353
            if (rpl > cpl)
2354
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2355
            if (dpl != cpl)
2356
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2357
        }
2358
        if (!(e2 & DESC_P_MASK))
2359
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2360

    
2361
#ifdef TARGET_X86_64
2362
        /* XXX: check 16/32 bit cases in long mode */
2363
        if (shift == 2) {
2364
            target_ulong rsp;
2365
            /* 64 bit case */
2366
            rsp = ESP;
2367
            PUSHQ(rsp, env->segs[R_CS].selector);
2368
            PUSHQ(rsp, next_eip);
2369
            /* from this point, not restartable */
2370
            ESP = rsp;
2371
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2372
                                   get_seg_base(e1, e2),
2373
                                   get_seg_limit(e1, e2), e2);
2374
            EIP = new_eip;
2375
        } else
2376
#endif
2377
        {
2378
            sp = ESP;
2379
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2380
            ssp = env->segs[R_SS].base;
2381
            if (shift) {
2382
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2383
                PUSHL(ssp, sp, sp_mask, next_eip);
2384
            } else {
2385
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2386
                PUSHW(ssp, sp, sp_mask, next_eip);
2387
            }
2388

    
2389
            limit = get_seg_limit(e1, e2);
2390
            if (new_eip > limit)
2391
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2392
            /* from this point, not restartable */
2393
            SET_ESP(sp, sp_mask);
2394
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2395
                                   get_seg_base(e1, e2), limit, e2);
2396
            EIP = new_eip;
2397
        }
2398
    } else {
2399
        /* check gate type */
2400
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2401
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2402
        rpl = new_cs & 3;
2403
        switch(type) {
2404
        case 1: /* available 286 TSS */
2405
        case 9: /* available 386 TSS */
2406
        case 5: /* task gate */
2407
            if (dpl < cpl || dpl < rpl)
2408
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2409
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2410
            CC_OP = CC_OP_EFLAGS;
2411
            return;
2412
        case 4: /* 286 call gate */
2413
        case 12: /* 386 call gate */
2414
            break;
2415
        default:
2416
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2417
            break;
2418
        }
2419
        shift = type >> 3;
2420

    
2421
        if (dpl < cpl || dpl < rpl)
2422
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2423
        /* check valid bit */
2424
        if (!(e2 & DESC_P_MASK))
2425
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2426
        selector = e1 >> 16;
2427
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2428
        param_count = e2 & 0x1f;
2429
        if ((selector & 0xfffc) == 0)
2430
            raise_exception_err(EXCP0D_GPF, 0);
2431

    
2432
        if (load_segment(&e1, &e2, selector) != 0)
2433
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2434
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2435
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2436
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2437
        if (dpl > cpl)
2438
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2439
        if (!(e2 & DESC_P_MASK))
2440
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2441

    
2442
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2443
            /* to inner privilege */
2444
            get_ss_esp_from_tss(&ss, &sp, dpl);
2445
            LOG_PCALL("new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2446
                        ss, sp, param_count, ESP);
2447
            if ((ss & 0xfffc) == 0)
2448
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2449
            if ((ss & 3) != dpl)
2450
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2451
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2452
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2453
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2454
            if (ss_dpl != dpl)
2455
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2456
            if (!(ss_e2 & DESC_S_MASK) ||
2457
                (ss_e2 & DESC_CS_MASK) ||
2458
                !(ss_e2 & DESC_W_MASK))
2459
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2460
            if (!(ss_e2 & DESC_P_MASK))
2461
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2462

    
2463
            //            push_size = ((param_count * 2) + 8) << shift;
2464

    
2465
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2466
            old_ssp = env->segs[R_SS].base;
2467

    
2468
            sp_mask = get_sp_mask(ss_e2);
2469
            ssp = get_seg_base(ss_e1, ss_e2);
2470
            if (shift) {
2471
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2472
                PUSHL(ssp, sp, sp_mask, ESP);
2473
                for(i = param_count - 1; i >= 0; i--) {
2474
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2475
                    PUSHL(ssp, sp, sp_mask, val);
2476
                }
2477
            } else {
2478
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2479
                PUSHW(ssp, sp, sp_mask, ESP);
2480
                for(i = param_count - 1; i >= 0; i--) {
2481
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2482
                    PUSHW(ssp, sp, sp_mask, val);
2483
                }
2484
            }
2485
            new_stack = 1;
2486
        } else {
2487
            /* to same privilege */
2488
            sp = ESP;
2489
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2490
            ssp = env->segs[R_SS].base;
2491
            //            push_size = (4 << shift);
2492
            new_stack = 0;
2493
        }
2494

    
2495
        if (shift) {
2496
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2497
            PUSHL(ssp, sp, sp_mask, next_eip);
2498
        } else {
2499
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2500
            PUSHW(ssp, sp, sp_mask, next_eip);
2501
        }
2502

    
2503
        /* from this point, not restartable */
2504

    
2505
        if (new_stack) {
2506
            ss = (ss & ~3) | dpl;
2507
            cpu_x86_load_seg_cache(env, R_SS, ss,
2508
                                   ssp,
2509
                                   get_seg_limit(ss_e1, ss_e2),
2510
                                   ss_e2);
2511
        }
2512

    
2513
        selector = (selector & ~3) | dpl;
2514
        cpu_x86_load_seg_cache(env, R_CS, selector,
2515
                       get_seg_base(e1, e2),
2516
                       get_seg_limit(e1, e2),
2517
                       e2);
2518
        cpu_x86_set_cpl(env, dpl);
2519
        SET_ESP(sp, sp_mask);
2520
        EIP = offset;
2521
    }
2522
}
2523

    
2524
/* real and vm86 mode iret */
2525
void helper_iret_real(int shift)
2526
{
2527
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2528
    target_ulong ssp;
2529
    int eflags_mask;
2530

    
2531
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2532
    sp = ESP;
2533
    ssp = env->segs[R_SS].base;
2534
    if (shift == 1) {
2535
        /* 32 bits */
2536
        POPL(ssp, sp, sp_mask, new_eip);
2537
        POPL(ssp, sp, sp_mask, new_cs);
2538
        new_cs &= 0xffff;
2539
        POPL(ssp, sp, sp_mask, new_eflags);
2540
    } else {
2541
        /* 16 bits */
2542
        POPW(ssp, sp, sp_mask, new_eip);
2543
        POPW(ssp, sp, sp_mask, new_cs);
2544
        POPW(ssp, sp, sp_mask, new_eflags);
2545
    }
2546
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2547
    env->segs[R_CS].selector = new_cs;
2548
    env->segs[R_CS].base = (new_cs << 4);
2549
    env->eip = new_eip;
2550
    if (env->eflags & VM_MASK)
2551
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2552
    else
2553
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2554
    if (shift == 0)
2555
        eflags_mask &= 0xffff;
2556
    load_eflags(new_eflags, eflags_mask);
2557
    env->hflags2 &= ~HF2_NMI_MASK;
2558
}
2559

    
2560
static inline void validate_seg(int seg_reg, int cpl)
2561
{
2562
    int dpl;
2563
    uint32_t e2;
2564

    
2565
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2566
       they may still contain a valid base. I would be interested to
2567
       know how a real x86_64 CPU behaves */
2568
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2569
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2570
        return;
2571

    
2572
    e2 = env->segs[seg_reg].flags;
2573
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2574
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2575
        /* data or non conforming code segment */
2576
        if (dpl < cpl) {
2577
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2578
        }
2579
    }
2580
}
2581

    
2582
/* protected mode iret */
2583
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2584
{
2585
    uint32_t new_cs, new_eflags, new_ss;
2586
    uint32_t new_es, new_ds, new_fs, new_gs;
2587
    uint32_t e1, e2, ss_e1, ss_e2;
2588
    int cpl, dpl, rpl, eflags_mask, iopl;
2589
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2590

    
2591
#ifdef TARGET_X86_64
2592
    if (shift == 2)
2593
        sp_mask = -1;
2594
    else
2595
#endif
2596
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2597
    sp = ESP;
2598
    ssp = env->segs[R_SS].base;
2599
    new_eflags = 0; /* avoid warning */
2600
#ifdef TARGET_X86_64
2601
    if (shift == 2) {
2602
        POPQ(sp, new_eip);
2603
        POPQ(sp, new_cs);
2604
        new_cs &= 0xffff;
2605
        if (is_iret) {
2606
            POPQ(sp, new_eflags);
2607
        }
2608
    } else
2609
#endif
2610
    if (shift == 1) {
2611
        /* 32 bits */
2612
        POPL(ssp, sp, sp_mask, new_eip);
2613
        POPL(ssp, sp, sp_mask, new_cs);
2614
        new_cs &= 0xffff;
2615
        if (is_iret) {
2616
            POPL(ssp, sp, sp_mask, new_eflags);
2617
            if (new_eflags & VM_MASK)
2618
                goto return_to_vm86;
2619
        }
2620
    } else {
2621
        /* 16 bits */
2622
        POPW(ssp, sp, sp_mask, new_eip);
2623
        POPW(ssp, sp, sp_mask, new_cs);
2624
        if (is_iret)
2625
            POPW(ssp, sp, sp_mask, new_eflags);
2626
    }
2627
    LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2628
              new_cs, new_eip, shift, addend);
2629
    LOG_PCALL_STATE(env);
2630
    if ((new_cs & 0xfffc) == 0)
2631
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2632
    if (load_segment(&e1, &e2, new_cs) != 0)
2633
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2634
    if (!(e2 & DESC_S_MASK) ||
2635
        !(e2 & DESC_CS_MASK))
2636
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2637
    cpl = env->hflags & HF_CPL_MASK;
2638
    rpl = new_cs & 3;
2639
    if (rpl < cpl)
2640
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2641
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2642
    if (e2 & DESC_C_MASK) {
2643
        if (dpl > rpl)
2644
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2645
    } else {
2646
        if (dpl != rpl)
2647
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2648
    }
2649
    if (!(e2 & DESC_P_MASK))
2650
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2651

    
2652
    sp += addend;
2653
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2654
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2655
        /* return to same privilege level */
2656
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2657
                       get_seg_base(e1, e2),
2658
                       get_seg_limit(e1, e2),
2659
                       e2);
2660
    } else {
2661
        /* return to different privilege level */
2662
#ifdef TARGET_X86_64
2663
        if (shift == 2) {
2664
            POPQ(sp, new_esp);
2665
            POPQ(sp, new_ss);
2666
            new_ss &= 0xffff;
2667
        } else
2668
#endif
2669
        if (shift == 1) {
2670
            /* 32 bits */
2671
            POPL(ssp, sp, sp_mask, new_esp);
2672
            POPL(ssp, sp, sp_mask, new_ss);
2673
            new_ss &= 0xffff;
2674
        } else {
2675
            /* 16 bits */
2676
            POPW(ssp, sp, sp_mask, new_esp);
2677
            POPW(ssp, sp, sp_mask, new_ss);
2678
        }
2679
        LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",
2680
                    new_ss, new_esp);
2681
        if ((new_ss & 0xfffc) == 0) {
2682
#ifdef TARGET_X86_64
2683
            /* NULL ss is allowed in long mode if cpl != 3*/
2684
            /* XXX: test CS64 ? */
2685
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2686
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2687
                                       0, 0xffffffff,
2688
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2689
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2690
                                       DESC_W_MASK | DESC_A_MASK);
2691
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2692
            } else
2693
#endif
2694
            {
2695
                raise_exception_err(EXCP0D_GPF, 0);
2696
            }
2697
        } else {
2698
            if ((new_ss & 3) != rpl)
2699
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2700
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2701
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2702
            if (!(ss_e2 & DESC_S_MASK) ||
2703
                (ss_e2 & DESC_CS_MASK) ||
2704
                !(ss_e2 & DESC_W_MASK))
2705
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2706
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2707
            if (dpl != rpl)
2708
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2709
            if (!(ss_e2 & DESC_P_MASK))
2710
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2711
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2712
                                   get_seg_base(ss_e1, ss_e2),
2713
                                   get_seg_limit(ss_e1, ss_e2),
2714
                                   ss_e2);
2715
        }
2716

    
2717
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2718
                       get_seg_base(e1, e2),
2719
                       get_seg_limit(e1, e2),
2720
                       e2);
2721
        cpu_x86_set_cpl(env, rpl);
2722
        sp = new_esp;
2723
#ifdef TARGET_X86_64
2724
        if (env->hflags & HF_CS64_MASK)
2725
            sp_mask = -1;
2726
        else
2727
#endif
2728
            sp_mask = get_sp_mask(ss_e2);
2729

    
2730
        /* validate data segments */
2731
        validate_seg(R_ES, rpl);
2732
        validate_seg(R_DS, rpl);
2733
        validate_seg(R_FS, rpl);
2734
        validate_seg(R_GS, rpl);
2735

    
2736
        sp += addend;
2737
    }
2738
    SET_ESP(sp, sp_mask);
2739
    env->eip = new_eip;
2740
    if (is_iret) {
2741
        /* NOTE: 'cpl' is the _old_ CPL */
2742
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2743
        if (cpl == 0)
2744
            eflags_mask |= IOPL_MASK;
2745
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2746
        if (cpl <= iopl)
2747
            eflags_mask |= IF_MASK;
2748
        if (shift == 0)
2749
            eflags_mask &= 0xffff;
2750
        load_eflags(new_eflags, eflags_mask);
2751
    }
2752
    return;
2753

    
2754
 return_to_vm86:
2755
    POPL(ssp, sp, sp_mask, new_esp);
2756
    POPL(ssp, sp, sp_mask, new_ss);
2757
    POPL(ssp, sp, sp_mask, new_es);
2758
    POPL(ssp, sp, sp_mask, new_ds);
2759
    POPL(ssp, sp, sp_mask, new_fs);
2760
    POPL(ssp, sp, sp_mask, new_gs);
2761

    
2762
    /* modify processor state */
2763
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2764
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2765
    load_seg_vm(R_CS, new_cs & 0xffff);
2766
    cpu_x86_set_cpl(env, 3);
2767
    load_seg_vm(R_SS, new_ss & 0xffff);
2768
    load_seg_vm(R_ES, new_es & 0xffff);
2769
    load_seg_vm(R_DS, new_ds & 0xffff);
2770
    load_seg_vm(R_FS, new_fs & 0xffff);
2771
    load_seg_vm(R_GS, new_gs & 0xffff);
2772

    
2773
    env->eip = new_eip & 0xffff;
2774
    ESP = new_esp;
2775
}
2776

    
2777
void helper_iret_protected(int shift, int next_eip)
2778
{
2779
    int tss_selector, type;
2780
    uint32_t e1, e2;
2781

    
2782
    /* specific case for TSS */
2783
    if (env->eflags & NT_MASK) {
2784
#ifdef TARGET_X86_64
2785
        if (env->hflags & HF_LMA_MASK)
2786
            raise_exception_err(EXCP0D_GPF, 0);
2787
#endif
2788
        tss_selector = lduw_kernel(env->tr.base + 0);
2789
        if (tss_selector & 4)
2790
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2791
        if (load_segment(&e1, &e2, tss_selector) != 0)
2792
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2793
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2794
        /* NOTE: we check both segment and busy TSS */
2795
        if (type != 3)
2796
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2797
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2798
    } else {
2799
        helper_ret_protected(shift, 1, 0);
2800
    }
2801
    env->hflags2 &= ~HF2_NMI_MASK;
2802
}
2803

    
2804
void helper_lret_protected(int shift, int addend)
2805
{
2806
    helper_ret_protected(shift, 0, addend);
2807
}
2808

    
2809
void helper_sysenter(void)
2810
{
2811
    if (env->sysenter_cs == 0) {
2812
        raise_exception_err(EXCP0D_GPF, 0);
2813
    }
2814
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2815
    cpu_x86_set_cpl(env, 0);
2816

    
2817
#ifdef TARGET_X86_64
2818
    if (env->hflags & HF_LMA_MASK) {
2819
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2820
                               0, 0xffffffff,
2821
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2822
                               DESC_S_MASK |
2823
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2824
    } else
2825
#endif
2826
    {
2827
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2828
                               0, 0xffffffff,
2829
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2830
                               DESC_S_MASK |
2831
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2832
    }
2833
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2834
                           0, 0xffffffff,
2835
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2836
                           DESC_S_MASK |
2837
                           DESC_W_MASK | DESC_A_MASK);
2838
    ESP = env->sysenter_esp;
2839
    EIP = env->sysenter_eip;
2840
}
2841

    
2842
void helper_sysexit(int dflag)
2843
{
2844
    int cpl;
2845

    
2846
    cpl = env->hflags & HF_CPL_MASK;
2847
    if (env->sysenter_cs == 0 || cpl != 0) {
2848
        raise_exception_err(EXCP0D_GPF, 0);
2849
    }
2850
    cpu_x86_set_cpl(env, 3);
2851
#ifdef TARGET_X86_64
2852
    if (dflag == 2) {
2853
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3,
2854
                               0, 0xffffffff,
2855
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2856
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2857
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2858
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3,
2859
                               0, 0xffffffff,
2860
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2861
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2862
                               DESC_W_MASK | DESC_A_MASK);
2863
    } else
2864
#endif
2865
    {
2866
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2867
                               0, 0xffffffff,
2868
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2869
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2870
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2871
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2872
                               0, 0xffffffff,
2873
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2874
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2875
                               DESC_W_MASK | DESC_A_MASK);
2876
    }
2877
    ESP = ECX;
2878
    EIP = EDX;
2879
}
2880

    
2881
#if defined(CONFIG_USER_ONLY)
2882
target_ulong helper_read_crN(int reg)
2883
{
2884
    return 0;
2885
}
2886

    
2887
void helper_write_crN(int reg, target_ulong t0)
2888
{
2889
}
2890

    
2891
void helper_movl_drN_T0(int reg, target_ulong t0)
2892
{
2893
}
2894
#else
2895
target_ulong helper_read_crN(int reg)
2896
{
2897
    target_ulong val;
2898

    
2899
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
2900
    switch(reg) {
2901
    default:
2902
        val = env->cr[reg];
2903
        break;
2904
    case 8:
2905
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2906
            val = cpu_get_apic_tpr(env->apic_state);
2907
        } else {
2908
            val = env->v_tpr;
2909
        }
2910
        break;
2911
    }
2912
    return val;
2913
}
2914

    
2915
void helper_write_crN(int reg, target_ulong t0)
2916
{
2917
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
2918
    switch(reg) {
2919
    case 0:
2920
        cpu_x86_update_cr0(env, t0);
2921
        break;
2922
    case 3:
2923
        cpu_x86_update_cr3(env, t0);
2924
        break;
2925
    case 4:
2926
        cpu_x86_update_cr4(env, t0);
2927
        break;
2928
    case 8:
2929
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2930
            cpu_set_apic_tpr(env->apic_state, t0);
2931
        }
2932
        env->v_tpr = t0 & 0x0f;
2933
        break;
2934
    default:
2935
        env->cr[reg] = t0;
2936
        break;
2937
    }
2938
}
2939

    
2940
void helper_movl_drN_T0(int reg, target_ulong t0)
2941
{
2942
    int i;
2943

    
2944
    if (reg < 4) {
2945
        hw_breakpoint_remove(env, reg);
2946
        env->dr[reg] = t0;
2947
        hw_breakpoint_insert(env, reg);
2948
    } else if (reg == 7) {
2949
        for (i = 0; i < 4; i++)
2950
            hw_breakpoint_remove(env, i);
2951
        env->dr[7] = t0;
2952
        for (i = 0; i < 4; i++)
2953
            hw_breakpoint_insert(env, i);
2954
    } else
2955
        env->dr[reg] = t0;
2956
}
2957
#endif
2958

    
2959
void helper_lmsw(target_ulong t0)
2960
{
2961
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2962
       if already set to one. */
2963
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2964
    helper_write_crN(0, t0);
2965
}
2966

    
2967
void helper_clts(void)
2968
{
2969
    env->cr[0] &= ~CR0_TS_MASK;
2970
    env->hflags &= ~HF_TS_MASK;
2971
}
2972

    
2973
void helper_invlpg(target_ulong addr)
2974
{
2975
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
2976
    tlb_flush_page(env, addr);
2977
}
2978

    
2979
void helper_rdtsc(void)
2980
{
2981
    uint64_t val;
2982

    
2983
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2984
        raise_exception(EXCP0D_GPF);
2985
    }
2986
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
2987

    
2988
    val = cpu_get_tsc(env) + env->tsc_offset;
2989
    EAX = (uint32_t)(val);
2990
    EDX = (uint32_t)(val >> 32);
2991
}
2992

    
2993
void helper_rdtscp(void)
2994
{
2995
    helper_rdtsc();
2996
    ECX = (uint32_t)(env->tsc_aux);
2997
}
2998

    
2999
void helper_rdpmc(void)
3000
{
3001
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3002
        raise_exception(EXCP0D_GPF);
3003
    }
3004
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3005
    
3006
    /* currently unimplemented */
3007
    raise_exception_err(EXCP06_ILLOP, 0);
3008
}
3009

    
3010
#if defined(CONFIG_USER_ONLY)
3011
void helper_wrmsr(void)
3012
{
3013
}
3014

    
3015
void helper_rdmsr(void)
3016
{
3017
}
3018
#else
3019
void helper_wrmsr(void)
3020
{
3021
    uint64_t val;
3022

    
3023
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3024

    
3025
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3026

    
3027
    switch((uint32_t)ECX) {
3028
    case MSR_IA32_SYSENTER_CS:
3029
        env->sysenter_cs = val & 0xffff;
3030
        break;
3031
    case MSR_IA32_SYSENTER_ESP:
3032
        env->sysenter_esp = val;
3033
        break;
3034
    case MSR_IA32_SYSENTER_EIP:
3035
        env->sysenter_eip = val;
3036
        break;
3037
    case MSR_IA32_APICBASE:
3038
        cpu_set_apic_base(env->apic_state, val);
3039
        break;
3040
    case MSR_EFER:
3041
        {
3042
            uint64_t update_mask;
3043
            update_mask = 0;
3044
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3045
                update_mask |= MSR_EFER_SCE;
3046
            if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3047
                update_mask |= MSR_EFER_LME;
3048
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3049
                update_mask |= MSR_EFER_FFXSR;
3050
            if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3051
                update_mask |= MSR_EFER_NXE;
3052
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3053
                update_mask |= MSR_EFER_SVME;
3054
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3055
                update_mask |= MSR_EFER_FFXSR;
3056
            cpu_load_efer(env, (env->efer & ~update_mask) |
3057
                          (val & update_mask));
3058
        }
3059
        break;
3060
    case MSR_STAR:
3061
        env->star = val;
3062
        break;
3063
    case MSR_PAT:
3064
        env->pat = val;
3065
        break;
3066
    case MSR_VM_HSAVE_PA:
3067
        env->vm_hsave = val;
3068
        break;
3069
#ifdef TARGET_X86_64
3070
    case MSR_LSTAR:
3071
        env->lstar = val;
3072
        break;
3073
    case MSR_CSTAR:
3074
        env->cstar = val;
3075
        break;
3076
    case MSR_FMASK:
3077
        env->fmask = val;
3078
        break;
3079
    case MSR_FSBASE:
3080
        env->segs[R_FS].base = val;
3081
        break;
3082
    case MSR_GSBASE:
3083
        env->segs[R_GS].base = val;
3084
        break;
3085
    case MSR_KERNELGSBASE:
3086
        env->kernelgsbase = val;
3087
        break;
3088
#endif
3089
    case MSR_MTRRphysBase(0):
3090
    case MSR_MTRRphysBase(1):
3091
    case MSR_MTRRphysBase(2):
3092
    case MSR_MTRRphysBase(3):
3093
    case MSR_MTRRphysBase(4):
3094
    case MSR_MTRRphysBase(5):
3095
    case MSR_MTRRphysBase(6):
3096
    case MSR_MTRRphysBase(7):
3097
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
3098
        break;
3099
    case MSR_MTRRphysMask(0):
3100
    case MSR_MTRRphysMask(1):
3101
    case MSR_MTRRphysMask(2):
3102
    case MSR_MTRRphysMask(3):
3103
    case MSR_MTRRphysMask(4):
3104
    case MSR_MTRRphysMask(5):
3105
    case MSR_MTRRphysMask(6):
3106
    case MSR_MTRRphysMask(7):
3107
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
3108
        break;
3109
    case MSR_MTRRfix64K_00000:
3110
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
3111
        break;
3112
    case MSR_MTRRfix16K_80000:
3113
    case MSR_MTRRfix16K_A0000:
3114
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
3115
        break;
3116
    case MSR_MTRRfix4K_C0000:
3117
    case MSR_MTRRfix4K_C8000:
3118
    case MSR_MTRRfix4K_D0000:
3119
    case MSR_MTRRfix4K_D8000:
3120
    case MSR_MTRRfix4K_E0000:
3121
    case MSR_MTRRfix4K_E8000:
3122
    case MSR_MTRRfix4K_F0000:
3123
    case MSR_MTRRfix4K_F8000:
3124
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
3125
        break;
3126
    case MSR_MTRRdefType:
3127
        env->mtrr_deftype = val;
3128
        break;
3129
    case MSR_MCG_STATUS:
3130
        env->mcg_status = val;
3131
        break;
3132
    case MSR_MCG_CTL:
3133
        if ((env->mcg_cap & MCG_CTL_P)
3134
            && (val == 0 || val == ~(uint64_t)0))
3135
            env->mcg_ctl = val;
3136
        break;
3137
    case MSR_TSC_AUX:
3138
        env->tsc_aux = val;
3139
        break;
3140
    default:
3141
        if ((uint32_t)ECX >= MSR_MC0_CTL
3142
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3143
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3144
            if ((offset & 0x3) != 0
3145
                || (val == 0 || val == ~(uint64_t)0))
3146
                env->mce_banks[offset] = val;
3147
            break;
3148
        }
3149
        /* XXX: exception ? */
3150
        break;
3151
    }
3152
}
3153

    
3154
void helper_rdmsr(void)
3155
{
3156
    uint64_t val;
3157

    
3158
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3159

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

    
3289
target_ulong helper_lsl(target_ulong selector1)
3290
{
3291
    unsigned int limit;
3292
    uint32_t e1, e2, eflags, selector;
3293
    int rpl, dpl, cpl, type;
3294

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

    
3334
target_ulong helper_lar(target_ulong selector1)
3335
{
3336
    uint32_t e1, e2, eflags, selector;
3337
    int rpl, dpl, cpl, type;
3338

    
3339
    selector = selector1 & 0xffff;
3340
    eflags = helper_cc_compute_all(CC_OP);
3341
    if ((selector & 0xfffc) == 0)
3342
        goto fail;
3343
    if (load_segment(&e1, &e2, selector) != 0)
3344
        goto fail;
3345
    rpl = selector & 3;
3346
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3347
    cpl = env->hflags & HF_CPL_MASK;
3348
    if (e2 & DESC_S_MASK) {
3349
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3350
            /* conforming */
3351
        } else {
3352
            if (dpl < cpl || dpl < rpl)
3353
                goto fail;
3354
        }
3355
    } else {
3356
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3357
        switch(type) {
3358
        case 1:
3359
        case 2:
3360
        case 3:
3361
        case 4:
3362
        case 5:
3363
        case 9:
3364
        case 11:
3365
        case 12:
3366
            break;
3367
        default:
3368
            goto fail;
3369
        }
3370
        if (dpl < cpl || dpl < rpl) {
3371
        fail:
3372
            CC_SRC = eflags & ~CC_Z;
3373
            return 0;
3374
        }
3375
    }
3376
    CC_SRC = eflags | CC_Z;
3377
    return e2 & 0x00f0ff00;
3378
}
3379

    
3380
void helper_verr(target_ulong selector1)
3381
{
3382
    uint32_t e1, e2, eflags, selector;
3383
    int rpl, dpl, cpl;
3384

    
3385
    selector = selector1 & 0xffff;
3386
    eflags = helper_cc_compute_all(CC_OP);
3387
    if ((selector & 0xfffc) == 0)
3388
        goto fail;
3389
    if (load_segment(&e1, &e2, selector) != 0)
3390
        goto fail;
3391
    if (!(e2 & DESC_S_MASK))
3392
        goto fail;
3393
    rpl = selector & 3;
3394
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3395
    cpl = env->hflags & HF_CPL_MASK;
3396
    if (e2 & DESC_CS_MASK) {
3397
        if (!(e2 & DESC_R_MASK))
3398
            goto fail;
3399
        if (!(e2 & DESC_C_MASK)) {
3400
            if (dpl < cpl || dpl < rpl)
3401
                goto fail;
3402
        }
3403
    } else {
3404
        if (dpl < cpl || dpl < rpl) {
3405
        fail:
3406
            CC_SRC = eflags & ~CC_Z;
3407
            return;
3408
        }
3409
    }
3410
    CC_SRC = eflags | CC_Z;
3411
}
3412

    
3413
void helper_verw(target_ulong selector1)
3414
{
3415
    uint32_t e1, e2, eflags, selector;
3416
    int rpl, dpl, cpl;
3417

    
3418
    selector = selector1 & 0xffff;
3419
    eflags = helper_cc_compute_all(CC_OP);
3420
    if ((selector & 0xfffc) == 0)
3421
        goto fail;
3422
    if (load_segment(&e1, &e2, selector) != 0)
3423
        goto fail;
3424
    if (!(e2 & DESC_S_MASK))
3425
        goto fail;
3426
    rpl = selector & 3;
3427
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3428
    cpl = env->hflags & HF_CPL_MASK;
3429
    if (e2 & DESC_CS_MASK) {
3430
        goto fail;
3431
    } else {
3432
        if (dpl < cpl || dpl < rpl)
3433
            goto fail;
3434
        if (!(e2 & DESC_W_MASK)) {
3435
        fail:
3436
            CC_SRC = eflags & ~CC_Z;
3437
            return;
3438
        }
3439
    }
3440
    CC_SRC = eflags | CC_Z;
3441
}
3442

    
3443
/* x87 FPU helpers */
3444

    
3445
static inline double CPU86_LDouble_to_double(CPU86_LDouble a)
3446
{
3447
    union {
3448
        float64 f64;
3449
        double d;
3450
    } u;
3451

    
3452
    u.f64 = floatx_to_float64(a, &env->fp_status);
3453
    return u.d;
3454
}
3455

    
3456
static inline CPU86_LDouble double_to_CPU86_LDouble(double a)
3457
{
3458
    union {
3459
        float64 f64;
3460
        double d;
3461
    } u;
3462

    
3463
    u.d = a;
3464
    return float64_to_floatx(u.f64, &env->fp_status);
3465
}
3466

    
3467
static void fpu_set_exception(int mask)
3468
{
3469
    env->fpus |= mask;
3470
    if (env->fpus & (~env->fpuc & FPUC_EM))
3471
        env->fpus |= FPUS_SE | FPUS_B;
3472
}
3473

    
3474
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3475
{
3476
    if (floatx_is_zero(b)) {
3477
        fpu_set_exception(FPUS_ZE);
3478
    }
3479
    return floatx_div(a, b, &env->fp_status);
3480
}
3481

    
3482
static void fpu_raise_exception(void)
3483
{
3484
    if (env->cr[0] & CR0_NE_MASK) {
3485
        raise_exception(EXCP10_COPR);
3486
    }
3487
#if !defined(CONFIG_USER_ONLY)
3488
    else {
3489
        cpu_set_ferr(env);
3490
    }
3491
#endif
3492
}
3493

    
3494
void helper_flds_FT0(uint32_t val)
3495
{
3496
    union {
3497
        float32 f;
3498
        uint32_t i;
3499
    } u;
3500
    u.i = val;
3501
    FT0 = float32_to_floatx(u.f, &env->fp_status);
3502
}
3503

    
3504
void helper_fldl_FT0(uint64_t val)
3505
{
3506
    union {
3507
        float64 f;
3508
        uint64_t i;
3509
    } u;
3510
    u.i = val;
3511
    FT0 = float64_to_floatx(u.f, &env->fp_status);
3512
}
3513

    
3514
void helper_fildl_FT0(int32_t val)
3515
{
3516
    FT0 = int32_to_floatx(val, &env->fp_status);
3517
}
3518

    
3519
void helper_flds_ST0(uint32_t val)
3520
{
3521
    int new_fpstt;
3522
    union {
3523
        float32 f;
3524
        uint32_t i;
3525
    } u;
3526
    new_fpstt = (env->fpstt - 1) & 7;
3527
    u.i = val;
3528
    env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3529
    env->fpstt = new_fpstt;
3530
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3531
}
3532

    
3533
void helper_fldl_ST0(uint64_t val)
3534
{
3535
    int new_fpstt;
3536
    union {
3537
        float64 f;
3538
        uint64_t i;
3539
    } u;
3540
    new_fpstt = (env->fpstt - 1) & 7;
3541
    u.i = val;
3542
    env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3543
    env->fpstt = new_fpstt;
3544
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3545
}
3546

    
3547
void helper_fildl_ST0(int32_t val)
3548
{
3549
    int new_fpstt;
3550
    new_fpstt = (env->fpstt - 1) & 7;
3551
    env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3552
    env->fpstt = new_fpstt;
3553
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3554
}
3555

    
3556
void helper_fildll_ST0(int64_t val)
3557
{
3558
    int new_fpstt;
3559
    new_fpstt = (env->fpstt - 1) & 7;
3560
    env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3561
    env->fpstt = new_fpstt;
3562
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3563
}
3564

    
3565
uint32_t helper_fsts_ST0(void)
3566
{
3567
    union {
3568
        float32 f;
3569
        uint32_t i;
3570
    } u;
3571
    u.f = floatx_to_float32(ST0, &env->fp_status);
3572
    return u.i;
3573
}
3574

    
3575
uint64_t helper_fstl_ST0(void)
3576
{
3577
    union {
3578
        float64 f;
3579
        uint64_t i;
3580
    } u;
3581
    u.f = floatx_to_float64(ST0, &env->fp_status);
3582
    return u.i;
3583
}
3584

    
3585
int32_t helper_fist_ST0(void)
3586
{
3587
    int32_t val;
3588
    val = floatx_to_int32(ST0, &env->fp_status);
3589
    if (val != (int16_t)val)
3590
        val = -32768;
3591
    return val;
3592
}
3593

    
3594
int32_t helper_fistl_ST0(void)
3595
{
3596
    int32_t val;
3597
    val = floatx_to_int32(ST0, &env->fp_status);
3598
    return val;
3599
}
3600

    
3601
int64_t helper_fistll_ST0(void)
3602
{
3603
    int64_t val;
3604
    val = floatx_to_int64(ST0, &env->fp_status);
3605
    return val;
3606
}
3607

    
3608
int32_t helper_fistt_ST0(void)
3609
{
3610
    int32_t val;
3611
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3612
    if (val != (int16_t)val)
3613
        val = -32768;
3614
    return val;
3615
}
3616

    
3617
int32_t helper_fisttl_ST0(void)
3618
{
3619
    int32_t val;
3620
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3621
    return val;
3622
}
3623

    
3624
int64_t helper_fisttll_ST0(void)
3625
{
3626
    int64_t val;
3627
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3628
    return val;
3629
}
3630

    
3631
void helper_fldt_ST0(target_ulong ptr)
3632
{
3633
    int new_fpstt;
3634
    new_fpstt = (env->fpstt - 1) & 7;
3635
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3636
    env->fpstt = new_fpstt;
3637
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3638
}
3639

    
3640
void helper_fstt_ST0(target_ulong ptr)
3641
{
3642
    helper_fstt(ST0, ptr);
3643
}
3644

    
3645
void helper_fpush(void)
3646
{
3647
    fpush();
3648
}
3649

    
3650
void helper_fpop(void)
3651
{
3652
    fpop();
3653
}
3654

    
3655
void helper_fdecstp(void)
3656
{
3657
    env->fpstt = (env->fpstt - 1) & 7;
3658
    env->fpus &= (~0x4700);
3659
}
3660

    
3661
void helper_fincstp(void)
3662
{
3663
    env->fpstt = (env->fpstt + 1) & 7;
3664
    env->fpus &= (~0x4700);
3665
}
3666

    
3667
/* FPU move */
3668

    
3669
void helper_ffree_STN(int st_index)
3670
{
3671
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3672
}
3673

    
3674
void helper_fmov_ST0_FT0(void)
3675
{
3676
    ST0 = FT0;
3677
}
3678

    
3679
void helper_fmov_FT0_STN(int st_index)
3680
{
3681
    FT0 = ST(st_index);
3682
}
3683

    
3684
void helper_fmov_ST0_STN(int st_index)
3685
{
3686
    ST0 = ST(st_index);
3687
}
3688

    
3689
void helper_fmov_STN_ST0(int st_index)
3690
{
3691
    ST(st_index) = ST0;
3692
}
3693

    
3694
void helper_fxchg_ST0_STN(int st_index)
3695
{
3696
    CPU86_LDouble tmp;
3697
    tmp = ST(st_index);
3698
    ST(st_index) = ST0;
3699
    ST0 = tmp;
3700
}
3701

    
3702
/* FPU operations */
3703

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

    
3706
void helper_fcom_ST0_FT0(void)
3707
{
3708
    int ret;
3709

    
3710
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3711
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3712
}
3713

    
3714
void helper_fucom_ST0_FT0(void)
3715
{
3716
    int ret;
3717

    
3718
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3719
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3720
}
3721

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

    
3724
void helper_fcomi_ST0_FT0(void)
3725
{
3726
    int eflags;
3727
    int ret;
3728

    
3729
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3730
    eflags = helper_cc_compute_all(CC_OP);
3731
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3732
    CC_SRC = eflags;
3733
}
3734

    
3735
void helper_fucomi_ST0_FT0(void)
3736
{
3737
    int eflags;
3738
    int ret;
3739

    
3740
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3741
    eflags = helper_cc_compute_all(CC_OP);
3742
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3743
    CC_SRC = eflags;
3744
}
3745

    
3746
void helper_fadd_ST0_FT0(void)
3747
{
3748
    ST0 = floatx_add(ST0, FT0, &env->fp_status);
3749
}
3750

    
3751
void helper_fmul_ST0_FT0(void)
3752
{
3753
    ST0 = floatx_mul(ST0, FT0, &env->fp_status);
3754
}
3755

    
3756
void helper_fsub_ST0_FT0(void)
3757
{
3758
    ST0 = floatx_sub(ST0, FT0, &env->fp_status);
3759
}
3760

    
3761
void helper_fsubr_ST0_FT0(void)
3762
{
3763
    ST0 = floatx_sub(FT0, ST0, &env->fp_status);
3764
}
3765

    
3766
void helper_fdiv_ST0_FT0(void)
3767
{
3768
    ST0 = helper_fdiv(ST0, FT0);
3769
}
3770

    
3771
void helper_fdivr_ST0_FT0(void)
3772
{
3773
    ST0 = helper_fdiv(FT0, ST0);
3774
}
3775

    
3776
/* fp operations between STN and ST0 */
3777

    
3778
void helper_fadd_STN_ST0(int st_index)
3779
{
3780
    ST(st_index) = floatx_add(ST(st_index), ST0, &env->fp_status);
3781
}
3782

    
3783
void helper_fmul_STN_ST0(int st_index)
3784
{
3785
    ST(st_index) = floatx_mul(ST(st_index), ST0, &env->fp_status);
3786
}
3787

    
3788
void helper_fsub_STN_ST0(int st_index)
3789
{
3790
    ST(st_index) = floatx_sub(ST(st_index), ST0, &env->fp_status);
3791
}
3792

    
3793
void helper_fsubr_STN_ST0(int st_index)
3794
{
3795
    ST(st_index) = floatx_sub(ST0, ST(st_index), &env->fp_status);
3796
}
3797

    
3798
void helper_fdiv_STN_ST0(int st_index)
3799
{
3800
    CPU86_LDouble *p;
3801
    p = &ST(st_index);
3802
    *p = helper_fdiv(*p, ST0);
3803
}
3804

    
3805
void helper_fdivr_STN_ST0(int st_index)
3806
{
3807
    CPU86_LDouble *p;
3808
    p = &ST(st_index);
3809
    *p = helper_fdiv(ST0, *p);
3810
}
3811

    
3812
/* misc FPU operations */
3813
void helper_fchs_ST0(void)
3814
{
3815
    ST0 = floatx_chs(ST0);
3816
}
3817

    
3818
void helper_fabs_ST0(void)
3819
{
3820
    ST0 = floatx_abs(ST0);
3821
}
3822

    
3823
void helper_fld1_ST0(void)
3824
{
3825
    ST0 = f15rk[1];
3826
}
3827

    
3828
void helper_fldl2t_ST0(void)
3829
{
3830
    ST0 = f15rk[6];
3831
}
3832

    
3833
void helper_fldl2e_ST0(void)
3834
{
3835
    ST0 = f15rk[5];
3836
}
3837

    
3838
void helper_fldpi_ST0(void)
3839
{
3840
    ST0 = f15rk[2];
3841
}
3842

    
3843
void helper_fldlg2_ST0(void)
3844
{
3845
    ST0 = f15rk[3];
3846
}
3847

    
3848
void helper_fldln2_ST0(void)
3849
{
3850
    ST0 = f15rk[4];
3851
}
3852

    
3853
void helper_fldz_ST0(void)
3854
{
3855
    ST0 = f15rk[0];
3856
}
3857

    
3858
void helper_fldz_FT0(void)
3859
{
3860
    FT0 = f15rk[0];
3861
}
3862

    
3863
uint32_t helper_fnstsw(void)
3864
{
3865
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3866
}
3867

    
3868
uint32_t helper_fnstcw(void)
3869
{
3870
    return env->fpuc;
3871
}
3872

    
3873
static void update_fp_status(void)
3874
{
3875
    int rnd_type;
3876

    
3877
    /* set rounding mode */
3878
    switch(env->fpuc & RC_MASK) {
3879
    default:
3880
    case RC_NEAR:
3881
        rnd_type = float_round_nearest_even;
3882
        break;
3883
    case RC_DOWN:
3884
        rnd_type = float_round_down;
3885
        break;
3886
    case RC_UP:
3887
        rnd_type = float_round_up;
3888
        break;
3889
    case RC_CHOP:
3890
        rnd_type = float_round_to_zero;
3891
        break;
3892
    }
3893
    set_float_rounding_mode(rnd_type, &env->fp_status);
3894
#ifdef FLOATX80
3895
    switch((env->fpuc >> 8) & 3) {
3896
    case 0:
3897
        rnd_type = 32;
3898
        break;
3899
    case 2:
3900
        rnd_type = 64;
3901
        break;
3902
    case 3:
3903
    default:
3904
        rnd_type = 80;
3905
        break;
3906
    }
3907
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3908
#endif
3909
}
3910

    
3911
void helper_fldcw(uint32_t val)
3912
{
3913
    env->fpuc = val;
3914
    update_fp_status();
3915
}
3916

    
3917
void helper_fclex(void)
3918
{
3919
    env->fpus &= 0x7f00;
3920
}
3921

    
3922
void helper_fwait(void)
3923
{
3924
    if (env->fpus & FPUS_SE)
3925
        fpu_raise_exception();
3926
}
3927

    
3928
void helper_fninit(void)
3929
{
3930
    env->fpus = 0;
3931
    env->fpstt = 0;
3932
    env->fpuc = 0x37f;
3933
    env->fptags[0] = 1;
3934
    env->fptags[1] = 1;
3935
    env->fptags[2] = 1;
3936
    env->fptags[3] = 1;
3937
    env->fptags[4] = 1;
3938
    env->fptags[5] = 1;
3939
    env->fptags[6] = 1;
3940
    env->fptags[7] = 1;
3941
}
3942

    
3943
/* BCD ops */
3944

    
3945
void helper_fbld_ST0(target_ulong ptr)
3946
{
3947
    CPU86_LDouble tmp;
3948
    uint64_t val;
3949
    unsigned int v;
3950
    int i;
3951

    
3952
    val = 0;
3953
    for(i = 8; i >= 0; i--) {
3954
        v = ldub(ptr + i);
3955
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3956
    }
3957
    tmp = int64_to_floatx(val, &env->fp_status);
3958
    if (ldub(ptr + 9) & 0x80) {
3959
        floatx_chs(tmp);
3960
    }
3961
    fpush();
3962
    ST0 = tmp;
3963
}
3964

    
3965
void helper_fbst_ST0(target_ulong ptr)
3966
{
3967
    int v;
3968
    target_ulong mem_ref, mem_end;
3969
    int64_t val;
3970

    
3971
    val = floatx_to_int64(ST0, &env->fp_status);
3972
    mem_ref = ptr;
3973
    mem_end = mem_ref + 9;
3974
    if (val < 0) {
3975
        stb(mem_end, 0x80);
3976
        val = -val;
3977
    } else {
3978
        stb(mem_end, 0x00);
3979
    }
3980
    while (mem_ref < mem_end) {
3981
        if (val == 0)
3982
            break;
3983
        v = val % 100;
3984
        val = val / 100;
3985
        v = ((v / 10) << 4) | (v % 10);
3986
        stb(mem_ref++, v);
3987
    }
3988
    while (mem_ref < mem_end) {
3989
        stb(mem_ref++, 0);
3990
    }
3991
}
3992

    
3993
void helper_f2xm1(void)
3994
{
3995
    double val = CPU86_LDouble_to_double(ST0);
3996
    val = pow(2.0, val) - 1.0;
3997
    ST0 = double_to_CPU86_LDouble(val);
3998
}
3999

    
4000
void helper_fyl2x(void)
4001
{
4002
    double fptemp = CPU86_LDouble_to_double(ST0);
4003

    
4004
    if (fptemp>0.0){
4005
        fptemp = log(fptemp)/log(2.0);    /* log2(ST) */
4006
        fptemp *= CPU86_LDouble_to_double(ST1);
4007
        ST1 = double_to_CPU86_LDouble(fptemp);
4008
        fpop();
4009
    } else {
4010
        env->fpus &= (~0x4700);
4011
        env->fpus |= 0x400;
4012
    }
4013
}
4014

    
4015
void helper_fptan(void)
4016
{
4017
    double fptemp = CPU86_LDouble_to_double(ST0);
4018

    
4019
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4020
        env->fpus |= 0x400;
4021
    } else {
4022
        fptemp = tan(fptemp);
4023
        ST0 = double_to_CPU86_LDouble(fptemp);
4024
        fpush();
4025
        ST0 = floatx_one;
4026
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4027
        /* the above code is for  |arg| < 2**52 only */
4028
    }
4029
}
4030

    
4031
void helper_fpatan(void)
4032
{
4033
    double fptemp, fpsrcop;
4034

    
4035
    fpsrcop = CPU86_LDouble_to_double(ST1);
4036
    fptemp = CPU86_LDouble_to_double(ST0);
4037
    ST1 = double_to_CPU86_LDouble(atan2(fpsrcop, fptemp));
4038
    fpop();
4039
}
4040

    
4041
void helper_fxtract(void)
4042
{
4043
    CPU86_LDoubleU temp;
4044

    
4045
    temp.d = ST0;
4046

    
4047
    if (floatx_is_zero(ST0)) {
4048
        /* Easy way to generate -inf and raising division by 0 exception */
4049
        ST0 = floatx_div(floatx_chs(floatx_one), floatx_zero, &env->fp_status);
4050
        fpush();
4051
        ST0 = temp.d;
4052
    } else {
4053
        int expdif;
4054

    
4055
        expdif = EXPD(temp) - EXPBIAS;
4056
        /*DP exponent bias*/
4057
        ST0 = int32_to_floatx(expdif, &env->fp_status);
4058
        fpush();
4059
        BIASEXPONENT(temp);
4060
        ST0 = temp.d;
4061
    }
4062
}
4063

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

    
4071
    st0 = CPU86_LDouble_to_double(ST0);
4072
    st1 = CPU86_LDouble_to_double(ST1);
4073

    
4074
    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
4075
        ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
4076
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4077
        return;
4078
    }
4079

    
4080
    fpsrcop = st0;
4081
    fptemp = st1;
4082
    fpsrcop1.d = ST0;
4083
    fptemp1.d = ST1;
4084
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4085

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

    
4093
    if (expdif < 53) {
4094
        dblq = fpsrcop / fptemp;
4095
        /* round dblq towards nearest integer */
4096
        dblq = rint(dblq);
4097
        st0 = fpsrcop - fptemp * dblq;
4098

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

    
4105
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4106
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4107
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4108
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4109
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4110
    } else {
4111
        env->fpus |= 0x400;  /* C2 <-- 1 */
4112
        fptemp = pow(2.0, expdif - 50);
4113
        fpsrcop = (st0 / st1) / fptemp;
4114
        /* fpsrcop = integer obtained by chopping */
4115
        fpsrcop = (fpsrcop < 0.0) ?
4116
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4117
        st0 -= (st1 * fpsrcop * fptemp);
4118
    }
4119
    ST0 = double_to_CPU86_LDouble(st0);
4120
}
4121

    
4122
void helper_fprem(void)
4123
{
4124
    double st0, st1, dblq, fpsrcop, fptemp;
4125
    CPU86_LDoubleU fpsrcop1, fptemp1;
4126
    int expdif;
4127
    signed long long int q;
4128

    
4129
    st0 = CPU86_LDouble_to_double(ST0);
4130
    st1 = CPU86_LDouble_to_double(ST1);
4131

    
4132
    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
4133
       ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
4134
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4135
       return;
4136
    }
4137

    
4138
    fpsrcop = st0;
4139
    fptemp = st1;
4140
    fpsrcop1.d = ST0;
4141
    fptemp1.d = ST1;
4142
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4143

    
4144
    if (expdif < 0) {
4145
        /* optimisation? taken from the AMD docs */
4146
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4147
        /* ST0 is unchanged */
4148
        return;
4149
    }
4150

    
4151
    if ( expdif < 53 ) {
4152
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4153
        /* round dblq towards zero */
4154
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4155
        st0 = fpsrcop/*ST0*/ - fptemp * dblq;
4156

    
4157
        /* convert dblq to q by truncating towards zero */
4158
        if (dblq < 0.0)
4159
           q = (signed long long int)(-dblq);
4160
        else
4161
           q = (signed long long int)dblq;
4162

    
4163
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4164
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4165
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4166
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4167
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4168
    } else {
4169
        int N = 32 + (expdif % 32); /* as per AMD docs */
4170
        env->fpus |= 0x400;  /* C2 <-- 1 */
4171
        fptemp = pow(2.0, (double)(expdif - N));
4172
        fpsrcop = (st0 / st1) / fptemp;
4173
        /* fpsrcop = integer obtained by chopping */
4174
        fpsrcop = (fpsrcop < 0.0) ?
4175
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4176
        st0 -= (st1 * fpsrcop * fptemp);
4177
    }
4178
    ST0 = double_to_CPU86_LDouble(st0);
4179
}
4180

    
4181
void helper_fyl2xp1(void)
4182
{
4183
    double fptemp = CPU86_LDouble_to_double(ST0);
4184

    
4185
    if ((fptemp+1.0)>0.0) {
4186
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4187
        fptemp *= CPU86_LDouble_to_double(ST1);
4188
        ST1 = double_to_CPU86_LDouble(fptemp);
4189
        fpop();
4190
    } else {
4191
        env->fpus &= (~0x4700);
4192
        env->fpus |= 0x400;
4193
    }
4194
}
4195

    
4196
void helper_fsqrt(void)
4197
{
4198
    if (floatx_is_neg(ST0)) {
4199
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4200
        env->fpus |= 0x400;
4201
    }
4202
    ST0 = floatx_sqrt(ST0, &env->fp_status);
4203
}
4204

    
4205
void helper_fsincos(void)
4206
{
4207
    double fptemp = CPU86_LDouble_to_double(ST0);
4208

    
4209
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4210
        env->fpus |= 0x400;
4211
    } else {
4212
        ST0 = double_to_CPU86_LDouble(sin(fptemp));
4213
        fpush();
4214
        ST0 = double_to_CPU86_LDouble(cos(fptemp));
4215
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4216
        /* the above code is for  |arg| < 2**63 only */
4217
    }
4218
}
4219

    
4220
void helper_frndint(void)
4221
{
4222
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4223
}
4224

    
4225
void helper_fscale(void)
4226
{
4227
    if (floatx_is_any_nan(ST1)) {
4228
        ST0 = ST1;
4229
    } else {
4230
        int n = floatx_to_int32_round_to_zero(ST1, &env->fp_status);
4231
        ST0 = floatx_scalbn(ST0, n, &env->fp_status);
4232
    }
4233
}
4234

    
4235
void helper_fsin(void)
4236
{
4237
    double fptemp = CPU86_LDouble_to_double(ST0);
4238

    
4239
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4240
        env->fpus |= 0x400;
4241
    } else {
4242
        ST0 = double_to_CPU86_LDouble(sin(fptemp));
4243
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4244
        /* the above code is for  |arg| < 2**53 only */
4245
    }
4246
}
4247

    
4248
void helper_fcos(void)
4249
{
4250
    double fptemp = CPU86_LDouble_to_double(ST0);
4251

    
4252
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4253
        env->fpus |= 0x400;
4254
    } else {
4255
        ST0 = double_to_CPU86_LDouble(cos(fptemp));
4256
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4257
        /* the above code is for  |arg5 < 2**63 only */
4258
    }
4259
}
4260

    
4261
void helper_fxam_ST0(void)
4262
{
4263
    CPU86_LDoubleU temp;
4264
    int expdif;
4265

    
4266
    temp.d = ST0;
4267

    
4268
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4269
    if (SIGND(temp))
4270
        env->fpus |= 0x200; /* C1 <-- 1 */
4271

    
4272
    /* XXX: test fptags too */
4273
    expdif = EXPD(temp);
4274
    if (expdif == MAXEXPD) {
4275
#ifdef USE_X86LDOUBLE
4276
        if (MANTD(temp) == 0x8000000000000000ULL)
4277
#else
4278
        if (MANTD(temp) == 0)
4279
#endif
4280
            env->fpus |=  0x500 /*Infinity*/;
4281
        else
4282
            env->fpus |=  0x100 /*NaN*/;
4283
    } else if (expdif == 0) {
4284
        if (MANTD(temp) == 0)
4285
            env->fpus |=  0x4000 /*Zero*/;
4286
        else
4287
            env->fpus |= 0x4400 /*Denormal*/;
4288
    } else {
4289
        env->fpus |= 0x400;
4290
    }
4291
}
4292

    
4293
void helper_fstenv(target_ulong ptr, int data32)
4294
{
4295
    int fpus, fptag, exp, i;
4296
    uint64_t mant;
4297
    CPU86_LDoubleU tmp;
4298

    
4299
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4300
    fptag = 0;
4301
    for (i=7; i>=0; i--) {
4302
        fptag <<= 2;
4303
        if (env->fptags[i]) {
4304
            fptag |= 3;
4305
        } else {
4306
            tmp.d = env->fpregs[i].d;
4307
            exp = EXPD(tmp);
4308
            mant = MANTD(tmp);
4309
            if (exp == 0 && mant == 0) {
4310
                /* zero */
4311
                fptag |= 1;
4312
            } else if (exp == 0 || exp == MAXEXPD
4313
#ifdef USE_X86LDOUBLE
4314
                       || (mant & (1LL << 63)) == 0
4315
#endif
4316
                       ) {
4317
                /* NaNs, infinity, denormal */
4318
                fptag |= 2;
4319
            }
4320
        }
4321
    }
4322
    if (data32) {
4323
        /* 32 bit */
4324
        stl(ptr, env->fpuc);
4325
        stl(ptr + 4, fpus);
4326
        stl(ptr + 8, fptag);
4327
        stl(ptr + 12, 0); /* fpip */
4328
        stl(ptr + 16, 0); /* fpcs */
4329
        stl(ptr + 20, 0); /* fpoo */
4330
        stl(ptr + 24, 0); /* fpos */
4331
    } else {
4332
        /* 16 bit */
4333
        stw(ptr, env->fpuc);
4334
        stw(ptr + 2, fpus);
4335
        stw(ptr + 4, fptag);
4336
        stw(ptr + 6, 0);
4337
        stw(ptr + 8, 0);
4338
        stw(ptr + 10, 0);
4339
        stw(ptr + 12, 0);
4340
    }
4341
}
4342

    
4343
void helper_fldenv(target_ulong ptr, int data32)
4344
{
4345
    int i, fpus, fptag;
4346

    
4347
    if (data32) {
4348
        env->fpuc = lduw(ptr);
4349
        fpus = lduw(ptr + 4);
4350
        fptag = lduw(ptr + 8);
4351
    }
4352
    else {
4353
        env->fpuc = lduw(ptr);
4354
        fpus = lduw(ptr + 2);
4355
        fptag = lduw(ptr + 4);
4356
    }
4357
    env->fpstt = (fpus >> 11) & 7;
4358
    env->fpus = fpus & ~0x3800;
4359
    for(i = 0;i < 8; i++) {
4360
        env->fptags[i] = ((fptag & 3) == 3);
4361
        fptag >>= 2;
4362
    }
4363
}
4364

    
4365
void helper_fsave(target_ulong ptr, int data32)
4366
{
4367
    CPU86_LDouble tmp;
4368
    int i;
4369

    
4370
    helper_fstenv(ptr, data32);
4371

    
4372
    ptr += (14 << data32);
4373
    for(i = 0;i < 8; i++) {
4374
        tmp = ST(i);
4375
        helper_fstt(tmp, ptr);
4376
        ptr += 10;
4377
    }
4378

    
4379
    /* fninit */
4380
    env->fpus = 0;
4381
    env->fpstt = 0;
4382
    env->fpuc = 0x37f;
4383
    env->fptags[0] = 1;
4384
    env->fptags[1] = 1;
4385
    env->fptags[2] = 1;
4386
    env->fptags[3] = 1;
4387
    env->fptags[4] = 1;
4388
    env->fptags[5] = 1;
4389
    env->fptags[6] = 1;
4390
    env->fptags[7] = 1;
4391
}
4392

    
4393
void helper_frstor(target_ulong ptr, int data32)
4394
{
4395
    CPU86_LDouble tmp;
4396
    int i;
4397

    
4398
    helper_fldenv(ptr, data32);
4399
    ptr += (14 << data32);
4400

    
4401
    for(i = 0;i < 8; i++) {
4402
        tmp = helper_fldt(ptr);
4403
        ST(i) = tmp;
4404
        ptr += 10;
4405
    }
4406
}
4407

    
4408
void helper_fxsave(target_ulong ptr, int data64)
4409
{
4410
    int fpus, fptag, i, 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
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4420
    fptag = 0;
4421
    for(i = 0; i < 8; i++) {
4422
        fptag |= (env->fptags[i] << i);
4423
    }
4424
    stw(ptr, env->fpuc);
4425
    stw(ptr + 2, fpus);
4426
    stw(ptr + 4, fptag ^ 0xff);
4427
#ifdef TARGET_X86_64
4428
    if (data64) {
4429
        stq(ptr + 0x08, 0); /* rip */
4430
        stq(ptr + 0x10, 0); /* rdp */
4431
    } else 
4432
#endif
4433
    {
4434
        stl(ptr + 0x08, 0); /* eip */
4435
        stl(ptr + 0x0c, 0); /* sel  */
4436
        stl(ptr + 0x10, 0); /* dp */
4437
        stl(ptr + 0x14, 0); /* sel  */
4438
    }
4439

    
4440
    addr = ptr + 0x20;
4441
    for(i = 0;i < 8; i++) {
4442
        tmp = ST(i);
4443
        helper_fstt(tmp, addr);
4444
        addr += 16;
4445
    }
4446

    
4447
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4448
        /* XXX: finish it */
4449
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4450
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4451
        if (env->hflags & HF_CS64_MASK)
4452
            nb_xmm_regs = 16;
4453
        else
4454
            nb_xmm_regs = 8;
4455
        addr = ptr + 0xa0;
4456
        /* Fast FXSAVE leaves out the XMM registers */
4457
        if (!(env->efer & MSR_EFER_FFXSR)
4458
          || (env->hflags & HF_CPL_MASK)
4459
          || !(env->hflags & HF_LMA_MASK)) {
4460
            for(i = 0; i < nb_xmm_regs; i++) {
4461
                stq(addr, env->xmm_regs[i].XMM_Q(0));
4462
                stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4463
                addr += 16;
4464
            }
4465
        }
4466
    }
4467
}
4468

    
4469
void helper_fxrstor(target_ulong ptr, int data64)
4470
{
4471
    int i, fpus, fptag, nb_xmm_regs;
4472
    CPU86_LDouble tmp;
4473
    target_ulong addr;
4474

    
4475
    /* The operand must be 16 byte aligned */
4476
    if (ptr & 0xf) {
4477
        raise_exception(EXCP0D_GPF);
4478
    }
4479

    
4480
    env->fpuc = lduw(ptr);
4481
    fpus = lduw(ptr + 2);
4482
    fptag = lduw(ptr + 4);
4483
    env->fpstt = (fpus >> 11) & 7;
4484
    env->fpus = fpus & ~0x3800;
4485
    fptag ^= 0xff;
4486
    for(i = 0;i < 8; i++) {
4487
        env->fptags[i] = ((fptag >> i) & 1);
4488
    }
4489

    
4490
    addr = ptr + 0x20;
4491
    for(i = 0;i < 8; i++) {
4492
        tmp = helper_fldt(addr);
4493
        ST(i) = tmp;
4494
        addr += 16;
4495
    }
4496

    
4497
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4498
        /* XXX: finish it */
4499
        env->mxcsr = ldl(ptr + 0x18);
4500
        //ldl(ptr + 0x1c);
4501
        if (env->hflags & HF_CS64_MASK)
4502
            nb_xmm_regs = 16;
4503
        else
4504
            nb_xmm_regs = 8;
4505
        addr = ptr + 0xa0;
4506
        /* Fast FXRESTORE leaves out the XMM registers */
4507
        if (!(env->efer & MSR_EFER_FFXSR)
4508
          || (env->hflags & HF_CPL_MASK)
4509
          || !(env->hflags & HF_LMA_MASK)) {
4510
            for(i = 0; i < nb_xmm_regs; i++) {
4511
                env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4512
                env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4513
                addr += 16;
4514
            }
4515
        }
4516
    }
4517
}
4518

    
4519
#ifndef USE_X86LDOUBLE
4520

    
4521
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4522
{
4523
    CPU86_LDoubleU temp;
4524
    int e;
4525

    
4526
    temp.d = f;
4527
    /* mantissa */
4528
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4529
    /* exponent + sign */
4530
    e = EXPD(temp) - EXPBIAS + 16383;
4531
    e |= SIGND(temp) >> 16;
4532
    *pexp = e;
4533
}
4534

    
4535
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4536
{
4537
    CPU86_LDoubleU temp;
4538
    int e;
4539
    uint64_t ll;
4540

    
4541
    /* XXX: handle overflow ? */
4542
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4543
    e |= (upper >> 4) & 0x800; /* sign */
4544
    ll = (mant >> 11) & ((1LL << 52) - 1);
4545
#ifdef __arm__
4546
    temp.l.upper = (e << 20) | (ll >> 32);
4547
    temp.l.lower = ll;
4548
#else
4549
    temp.ll = ll | ((uint64_t)e << 52);
4550
#endif
4551
    return temp.d;
4552
}
4553

    
4554
#else
4555

    
4556
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4557
{
4558
    CPU86_LDoubleU temp;
4559

    
4560
    temp.d = f;
4561
    *pmant = temp.l.lower;
4562
    *pexp = temp.l.upper;
4563
}
4564

    
4565
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4566
{
4567
    CPU86_LDoubleU temp;
4568

    
4569
    temp.l.upper = upper;
4570
    temp.l.lower = mant;
4571
    return temp.d;
4572
}
4573
#endif
4574

    
4575
#ifdef TARGET_X86_64
4576

    
4577
//#define DEBUG_MULDIV
4578

    
4579
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4580
{
4581
    *plow += a;
4582
    /* carry test */
4583
    if (*plow < a)
4584
        (*phigh)++;
4585
    *phigh += b;
4586
}
4587

    
4588
static void neg128(uint64_t *plow, uint64_t *phigh)
4589
{
4590
    *plow = ~ *plow;
4591
    *phigh = ~ *phigh;
4592
    add128(plow, phigh, 1, 0);
4593
}
4594

    
4595
/* return TRUE if overflow */
4596
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4597
{
4598
    uint64_t q, r, a1, a0;
4599
    int i, qb, ab;
4600

    
4601
    a0 = *plow;
4602
    a1 = *phigh;
4603
    if (a1 == 0) {
4604
        q = a0 / b;
4605
        r = a0 % b;
4606
        *plow = q;
4607
        *phigh = r;
4608
    } else {
4609
        if (a1 >= b)
4610
            return 1;
4611
        /* XXX: use a better algorithm */
4612
        for(i = 0; i < 64; i++) {
4613
            ab = a1 >> 63;
4614
            a1 = (a1 << 1) | (a0 >> 63);
4615
            if (ab || a1 >= b) {
4616
                a1 -= b;
4617
                qb = 1;
4618
            } else {
4619
                qb = 0;
4620
            }
4621
            a0 = (a0 << 1) | qb;
4622
        }
4623
#if defined(DEBUG_MULDIV)
4624
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4625
               *phigh, *plow, b, a0, a1);
4626
#endif
4627
        *plow = a0;
4628
        *phigh = a1;
4629
    }
4630
    return 0;
4631
}
4632

    
4633
/* return TRUE if overflow */
4634
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4635
{
4636
    int sa, sb;
4637
    sa = ((int64_t)*phigh < 0);
4638
    if (sa)
4639
        neg128(plow, phigh);
4640
    sb = (b < 0);
4641
    if (sb)
4642
        b = -b;
4643
    if (div64(plow, phigh, b) != 0)
4644
        return 1;
4645
    if (sa ^ sb) {
4646
        if (*plow > (1ULL << 63))
4647
            return 1;
4648
        *plow = - *plow;
4649
    } else {
4650
        if (*plow >= (1ULL << 63))
4651
            return 1;
4652
    }
4653
    if (sa)
4654
        *phigh = - *phigh;
4655
    return 0;
4656
}
4657

    
4658
void helper_mulq_EAX_T0(target_ulong t0)
4659
{
4660
    uint64_t r0, r1;
4661

    
4662
    mulu64(&r0, &r1, EAX, t0);
4663
    EAX = r0;
4664
    EDX = r1;
4665
    CC_DST = r0;
4666
    CC_SRC = r1;
4667
}
4668

    
4669
void helper_imulq_EAX_T0(target_ulong t0)
4670
{
4671
    uint64_t r0, r1;
4672

    
4673
    muls64(&r0, &r1, EAX, t0);
4674
    EAX = r0;
4675
    EDX = r1;
4676
    CC_DST = r0;
4677
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4678
}
4679

    
4680
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4681
{
4682
    uint64_t r0, r1;
4683

    
4684
    muls64(&r0, &r1, t0, t1);
4685
    CC_DST = r0;
4686
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4687
    return r0;
4688
}
4689

    
4690
void helper_divq_EAX(target_ulong t0)
4691
{
4692
    uint64_t r0, r1;
4693
    if (t0 == 0) {
4694
        raise_exception(EXCP00_DIVZ);
4695
    }
4696
    r0 = EAX;
4697
    r1 = EDX;
4698
    if (div64(&r0, &r1, t0))
4699
        raise_exception(EXCP00_DIVZ);
4700
    EAX = r0;
4701
    EDX = r1;
4702
}
4703

    
4704
void helper_idivq_EAX(target_ulong t0)
4705
{
4706
    uint64_t r0, r1;
4707
    if (t0 == 0) {
4708
        raise_exception(EXCP00_DIVZ);
4709
    }
4710
    r0 = EAX;
4711
    r1 = EDX;
4712
    if (idiv64(&r0, &r1, t0))
4713
        raise_exception(EXCP00_DIVZ);
4714
    EAX = r0;
4715
    EDX = r1;
4716
}
4717
#endif
4718

    
4719
static void do_hlt(void)
4720
{
4721
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4722
    env->halted = 1;
4723
    env->exception_index = EXCP_HLT;
4724
    cpu_loop_exit();
4725
}
4726

    
4727
void helper_hlt(int next_eip_addend)
4728
{
4729
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4730
    EIP += next_eip_addend;
4731
    
4732
    do_hlt();
4733
}
4734

    
4735
void helper_monitor(target_ulong ptr)
4736
{
4737
    if ((uint32_t)ECX != 0)
4738
        raise_exception(EXCP0D_GPF);
4739
    /* XXX: store address ? */
4740
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4741
}
4742

    
4743
void helper_mwait(int next_eip_addend)
4744
{
4745
    if ((uint32_t)ECX != 0)
4746
        raise_exception(EXCP0D_GPF);
4747
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4748
    EIP += next_eip_addend;
4749

    
4750
    /* XXX: not complete but not completely erroneous */
4751
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4752
        /* more than one CPU: do not sleep because another CPU may
4753
           wake this one */
4754
    } else {
4755
        do_hlt();
4756
    }
4757
}
4758

    
4759
void helper_debug(void)
4760
{
4761
    env->exception_index = EXCP_DEBUG;
4762
    cpu_loop_exit();
4763
}
4764

    
4765
void helper_reset_rf(void)
4766
{
4767
    env->eflags &= ~RF_MASK;
4768
}
4769

    
4770
void helper_raise_interrupt(int intno, int next_eip_addend)
4771
{
4772
    raise_interrupt(intno, 1, 0, next_eip_addend);
4773
}
4774

    
4775
void helper_raise_exception(int exception_index)
4776
{
4777
    raise_exception(exception_index);
4778
}
4779

    
4780
void helper_cli(void)
4781
{
4782
    env->eflags &= ~IF_MASK;
4783
}
4784

    
4785
void helper_sti(void)
4786
{
4787
    env->eflags |= IF_MASK;
4788
}
4789

    
4790
#if 0
4791
/* vm86plus instructions */
4792
void helper_cli_vm(void)
4793
{
4794
    env->eflags &= ~VIF_MASK;
4795
}
4796

4797
void helper_sti_vm(void)
4798
{
4799
    env->eflags |= VIF_MASK;
4800
    if (env->eflags & VIP_MASK) {
4801
        raise_exception(EXCP0D_GPF);
4802
    }
4803
}
4804
#endif
4805

    
4806
void helper_set_inhibit_irq(void)
4807
{
4808
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4809
}
4810

    
4811
void helper_reset_inhibit_irq(void)
4812
{
4813
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4814
}
4815

    
4816
void helper_boundw(target_ulong a0, int v)
4817
{
4818
    int low, high;
4819
    low = ldsw(a0);
4820
    high = ldsw(a0 + 2);
4821
    v = (int16_t)v;
4822
    if (v < low || v > high) {
4823
        raise_exception(EXCP05_BOUND);
4824
    }
4825
}
4826

    
4827
void helper_boundl(target_ulong a0, int v)
4828
{
4829
    int low, high;
4830
    low = ldl(a0);
4831
    high = ldl(a0 + 4);
4832
    if (v < low || v > high) {
4833
        raise_exception(EXCP05_BOUND);
4834
    }
4835
}
4836

    
4837
#if !defined(CONFIG_USER_ONLY)
4838

    
4839
#define MMUSUFFIX _mmu
4840

    
4841
#define SHIFT 0
4842
#include "softmmu_template.h"
4843

    
4844
#define SHIFT 1
4845
#include "softmmu_template.h"
4846

    
4847
#define SHIFT 2
4848
#include "softmmu_template.h"
4849

    
4850
#define SHIFT 3
4851
#include "softmmu_template.h"
4852

    
4853
#endif
4854

    
4855
#if !defined(CONFIG_USER_ONLY)
4856
/* try to fill the TLB and return an exception if error. If retaddr is
4857
   NULL, it means that the function was called in C code (i.e. not
4858
   from generated code or from helper.c) */
4859
/* XXX: fix it to restore all registers */
4860
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4861
{
4862
    TranslationBlock *tb;
4863
    int ret;
4864
    unsigned long pc;
4865
    CPUX86State *saved_env;
4866

    
4867
    /* XXX: hack to restore env in all cases, even if not called from
4868
       generated code */
4869
    saved_env = env;
4870
    env = cpu_single_env;
4871

    
4872
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4873
    if (ret) {
4874
        if (retaddr) {
4875
            /* now we have a real cpu fault */
4876
            pc = (unsigned long)retaddr;
4877
            tb = tb_find_pc(pc);
4878
            if (tb) {
4879
                /* the PC is inside the translated code. It means that we have
4880
                   a virtual CPU fault */
4881
                cpu_restore_state(tb, env, pc);
4882
            }
4883
        }
4884
        raise_exception_err(env->exception_index, env->error_code);
4885
    }
4886
    env = saved_env;
4887
}
4888
#endif
4889

    
4890
/* Secure Virtual Machine helpers */
4891

    
4892
#if defined(CONFIG_USER_ONLY)
4893

    
4894
void helper_vmrun(int aflag, int next_eip_addend)
4895
{ 
4896
}
4897
void helper_vmmcall(void) 
4898
{ 
4899
}
4900
void helper_vmload(int aflag)
4901
{ 
4902
}
4903
void helper_vmsave(int aflag)
4904
{ 
4905
}
4906
void helper_stgi(void)
4907
{
4908
}
4909
void helper_clgi(void)
4910
{
4911
}
4912
void helper_skinit(void) 
4913
{ 
4914
}
4915
void helper_invlpga(int aflag)
4916
{ 
4917
}
4918
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4919
{ 
4920
}
4921
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4922
{
4923
}
4924

    
4925
void helper_svm_check_io(uint32_t port, uint32_t param, 
4926
                         uint32_t next_eip_addend)
4927
{
4928
}
4929
#else
4930

    
4931
static inline void svm_save_seg(target_phys_addr_t addr,
4932
                                const SegmentCache *sc)
4933
{
4934
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4935
             sc->selector);
4936
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4937
             sc->base);
4938
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4939
             sc->limit);
4940
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4941
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4942
}
4943
                                
4944
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4945
{
4946
    unsigned int flags;
4947

    
4948
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4949
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4950
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4951
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4952
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4953
}
4954

    
4955
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4956
                                      CPUState *env, int seg_reg)
4957
{
4958
    SegmentCache sc1, *sc = &sc1;
4959
    svm_load_seg(addr, sc);
4960
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4961
                           sc->base, sc->limit, sc->flags);
4962
}
4963

    
4964
void helper_vmrun(int aflag, int next_eip_addend)
4965
{
4966
    target_ulong addr;
4967
    uint32_t event_inj;
4968
    uint32_t int_ctl;
4969

    
4970
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4971

    
4972
    if (aflag == 2)
4973
        addr = EAX;
4974
    else
4975
        addr = (uint32_t)EAX;
4976

    
4977
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
4978

    
4979
    env->vm_vmcb = addr;
4980

    
4981
    /* save the current CPU state in the hsave page */
4982
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4983
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4984

    
4985
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4986
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4987

    
4988
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4989
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4990
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4991
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4992
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4993
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4994

    
4995
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4996
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4997

    
4998
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4999
                  &env->segs[R_ES]);
5000
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
5001
                 &env->segs[R_CS]);
5002
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
5003
                 &env->segs[R_SS]);
5004
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
5005
                 &env->segs[R_DS]);
5006

    
5007
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
5008
             EIP + next_eip_addend);
5009
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
5010
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
5011

    
5012
    /* load the interception bitmaps so we do not need to access the
5013
       vmcb in svm mode */
5014
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
5015
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
5016
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
5017
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
5018
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
5019
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
5020

    
5021
    /* enable intercepts */
5022
    env->hflags |= HF_SVMI_MASK;
5023

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

    
5026
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
5027
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
5028

    
5029
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
5030
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
5031

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

    
5035
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
5036
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
5037
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
5038
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
5039
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5040
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5041
    if (int_ctl & V_INTR_MASKING_MASK) {
5042
        env->v_tpr = int_ctl & V_TPR_MASK;
5043
        env->hflags2 |= HF2_VINTR_MASK;
5044
        if (env->eflags & IF_MASK)
5045
            env->hflags2 |= HF2_HIF_MASK;
5046
    }
5047

    
5048
    cpu_load_efer(env, 
5049
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
5050
    env->eflags = 0;
5051
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
5052
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5053