Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ d5e49a81

History | View | Annotate | Download (155.5 kB)

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

    
24
//#define DEBUG_PCALL
25

    
26
#if 0
27
#define raise_exception_err(a, b)\
28
do {\
29
    if (logfile)\
30
        fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
31
    (raise_exception_err)(a, b);\
32
} while (0)
33
#endif
34

    
35
const uint8_t parity_table[256] = {
36
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
37
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
38
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
40
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
41
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
42
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
44
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
47
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
52
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
53
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
55
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
56
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
57
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
58
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
59
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
60
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
61
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
62
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
63
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
64
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
65
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
66
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
67
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
68
};
69

    
70
/* modulo 17 table */
71
const uint8_t rclw_table[32] = {
72
    0, 1, 2, 3, 4, 5, 6, 7,
73
    8, 9,10,11,12,13,14,15,
74
   16, 0, 1, 2, 3, 4, 5, 6,
75
    7, 8, 9,10,11,12,13,14,
76
};
77

    
78
/* modulo 9 table */
79
const uint8_t rclb_table[32] = {
80
    0, 1, 2, 3, 4, 5, 6, 7,
81
    8, 0, 1, 2, 3, 4, 5, 6,
82
    7, 8, 0, 1, 2, 3, 4, 5,
83
    6, 7, 8, 0, 1, 2, 3, 4,
84
};
85

    
86
const CPU86_LDouble f15rk[7] =
87
{
88
    0.00000000000000000000L,
89
    1.00000000000000000000L,
90
    3.14159265358979323851L,  /*pi*/
91
    0.30102999566398119523L,  /*lg2*/
92
    0.69314718055994530943L,  /*ln2*/
93
    1.44269504088896340739L,  /*l2e*/
94
    3.32192809488736234781L,  /*l2t*/
95
};
96

    
97
/* broken thread support */
98

    
99
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
100

    
101
void helper_lock(void)
102
{
103
    spin_lock(&global_cpu_lock);
104
}
105

    
106
void helper_unlock(void)
107
{
108
    spin_unlock(&global_cpu_lock);
109
}
110

    
111
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
112
{
113
    load_eflags(t0, update_mask);
114
}
115

    
116
target_ulong helper_read_eflags(void)
117
{
118
    uint32_t eflags;
119
    eflags = cc_table[CC_OP].compute_all();
120
    eflags |= (DF & DF_MASK);
121
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
122
    return eflags;
123
}
124

    
125
/* return non zero if error */
126
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
127
                               int selector)
128
{
129
    SegmentCache *dt;
130
    int index;
131
    target_ulong ptr;
132

    
133
    if (selector & 0x4)
134
        dt = &env->ldt;
135
    else
136
        dt = &env->gdt;
137
    index = selector & ~7;
138
    if ((index + 7) > dt->limit)
139
        return -1;
140
    ptr = dt->base + index;
141
    *e1_ptr = ldl_kernel(ptr);
142
    *e2_ptr = ldl_kernel(ptr + 4);
143
    return 0;
144
}
145

    
146
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
147
{
148
    unsigned int limit;
149
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
150
    if (e2 & DESC_G_MASK)
151
        limit = (limit << 12) | 0xfff;
152
    return limit;
153
}
154

    
155
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
156
{
157
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
158
}
159

    
160
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
161
{
162
    sc->base = get_seg_base(e1, e2);
163
    sc->limit = get_seg_limit(e1, e2);
164
    sc->flags = e2;
165
}
166

    
167
/* init the segment cache in vm86 mode. */
168
static inline void load_seg_vm(int seg, int selector)
169
{
170
    selector &= 0xffff;
171
    cpu_x86_load_seg_cache(env, seg, selector,
172
                           (selector << 4), 0xffff, 0);
173
}
174

    
175
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
176
                                       uint32_t *esp_ptr, int dpl)
177
{
178
    int type, index, shift;
179

    
180
#if 0
181
    {
182
        int i;
183
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
184
        for(i=0;i<env->tr.limit;i++) {
185
            printf("%02x ", env->tr.base[i]);
186
            if ((i & 7) == 7) printf("\n");
187
        }
188
        printf("\n");
189
    }
190
#endif
191

    
192
    if (!(env->tr.flags & DESC_P_MASK))
193
        cpu_abort(env, "invalid tss");
194
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
195
    if ((type & 7) != 1)
196
        cpu_abort(env, "invalid tss type");
197
    shift = type >> 3;
198
    index = (dpl * 4 + 2) << shift;
199
    if (index + (4 << shift) - 1 > env->tr.limit)
200
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
201
    if (shift == 0) {
202
        *esp_ptr = lduw_kernel(env->tr.base + index);
203
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
204
    } else {
205
        *esp_ptr = ldl_kernel(env->tr.base + index);
206
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
207
    }
208
}
209

    
210
/* XXX: merge with load_seg() */
211
static void tss_load_seg(int seg_reg, int selector)
212
{
213
    uint32_t e1, e2;
214
    int rpl, dpl, cpl;
215

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

    
260
#define SWITCH_TSS_JMP  0
261
#define SWITCH_TSS_IRET 1
262
#define SWITCH_TSS_CALL 2
263

    
264
/* XXX: restore CPU state in registers (PowerPC case) */
265
static void switch_tss(int tss_selector,
266
                       uint32_t e1, uint32_t e2, int source,
267
                       uint32_t next_eip)
268
{
269
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
270
    target_ulong tss_base;
271
    uint32_t new_regs[8], new_segs[6];
272
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
273
    uint32_t old_eflags, eflags_mask;
274
    SegmentCache *dt;
275
    int index;
276
    target_ulong ptr;
277

    
278
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
279
#ifdef DEBUG_PCALL
280
    if (loglevel & CPU_LOG_PCALL)
281
        fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
282
#endif
283

    
284
    /* if task gate, we read the TSS segment and we load it */
285
    if (type == 5) {
286
        if (!(e2 & DESC_P_MASK))
287
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
288
        tss_selector = e1 >> 16;
289
        if (tss_selector & 4)
290
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
291
        if (load_segment(&e1, &e2, tss_selector) != 0)
292
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
293
        if (e2 & DESC_S_MASK)
294
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
295
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
296
        if ((type & 7) != 1)
297
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
298
    }
299

    
300
    if (!(e2 & DESC_P_MASK))
301
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
302

    
303
    if (type & 8)
304
        tss_limit_max = 103;
305
    else
306
        tss_limit_max = 43;
307
    tss_limit = get_seg_limit(e1, e2);
308
    tss_base = get_seg_base(e1, e2);
309
    if ((tss_selector & 4) != 0 ||
310
        tss_limit < tss_limit_max)
311
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
312
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
313
    if (old_type & 8)
314
        old_tss_limit_max = 103;
315
    else
316
        old_tss_limit_max = 43;
317

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

    
345
    /* NOTE: we must avoid memory exceptions during the task switch,
346
       so we make dummy accesses before */
347
    /* XXX: it can still fail in some cases, so a bigger hack is
348
       necessary to valid the TLB after having done the accesses */
349

    
350
    v1 = ldub_kernel(env->tr.base);
351
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
352
    stb_kernel(env->tr.base, v1);
353
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
354

    
355
    /* clear busy bit (it is restartable) */
356
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
357
        target_ulong ptr;
358
        uint32_t e2;
359
        ptr = env->gdt.base + (env->tr.selector & ~7);
360
        e2 = ldl_kernel(ptr + 4);
361
        e2 &= ~DESC_TSS_BUSY_MASK;
362
        stl_kernel(ptr + 4, e2);
363
    }
364
    old_eflags = compute_eflags();
365
    if (source == SWITCH_TSS_IRET)
366
        old_eflags &= ~NT_MASK;
367

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

    
399
    /* now if an exception occurs, it will occurs in the next task
400
       context */
401

    
402
    if (source == SWITCH_TSS_CALL) {
403
        stw_kernel(tss_base, env->tr.selector);
404
        new_eflags |= NT_MASK;
405
    }
406

    
407
    /* set busy bit */
408
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
409
        target_ulong ptr;
410
        uint32_t e2;
411
        ptr = env->gdt.base + (tss_selector & ~7);
412
        e2 = ldl_kernel(ptr + 4);
413
        e2 |= DESC_TSS_BUSY_MASK;
414
        stl_kernel(ptr + 4, e2);
415
    }
416

    
417
    /* set the new CPU state */
418
    /* from this point, any exception which occurs can give problems */
419
    env->cr[0] |= CR0_TS_MASK;
420
    env->hflags |= HF_TS_MASK;
421
    env->tr.selector = tss_selector;
422
    env->tr.base = tss_base;
423
    env->tr.limit = tss_limit;
424
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
425

    
426
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
427
        cpu_x86_update_cr3(env, new_cr3);
428
    }
429

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

    
460
    env->ldt.selector = new_ldt & ~4;
461
    env->ldt.base = 0;
462
    env->ldt.limit = 0;
463
    env->ldt.flags = 0;
464

    
465
    /* load the LDT */
466
    if (new_ldt & 4)
467
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
468

    
469
    if ((new_ldt & 0xfffc) != 0) {
470
        dt = &env->gdt;
471
        index = new_ldt & ~7;
472
        if ((index + 7) > dt->limit)
473
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
474
        ptr = dt->base + index;
475
        e1 = ldl_kernel(ptr);
476
        e2 = ldl_kernel(ptr + 4);
477
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
478
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
479
        if (!(e2 & DESC_P_MASK))
480
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
481
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
482
    }
483

    
484
    /* load the segments */
485
    if (!(new_eflags & VM_MASK)) {
486
        tss_load_seg(R_CS, new_segs[R_CS]);
487
        tss_load_seg(R_SS, new_segs[R_SS]);
488
        tss_load_seg(R_ES, new_segs[R_ES]);
489
        tss_load_seg(R_DS, new_segs[R_DS]);
490
        tss_load_seg(R_FS, new_segs[R_FS]);
491
        tss_load_seg(R_GS, new_segs[R_GS]);
492
    }
493

    
494
    /* check that EIP is in the CS segment limits */
495
    if (new_eip > env->segs[R_CS].limit) {
496
        /* XXX: different exception if CALL ? */
497
        raise_exception_err(EXCP0D_GPF, 0);
498
    }
499
}
500

    
501
/* check if Port I/O is allowed in TSS */
502
static inline void check_io(int addr, int size)
503
{
504
    int io_offset, val, mask;
505

    
506
    /* TSS must be a valid 32 bit one */
507
    if (!(env->tr.flags & DESC_P_MASK) ||
508
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
509
        env->tr.limit < 103)
510
        goto fail;
511
    io_offset = lduw_kernel(env->tr.base + 0x66);
512
    io_offset += (addr >> 3);
513
    /* Note: the check needs two bytes */
514
    if ((io_offset + 1) > env->tr.limit)
515
        goto fail;
516
    val = lduw_kernel(env->tr.base + io_offset);
517
    val >>= (addr & 7);
518
    mask = (1 << size) - 1;
519
    /* all bits must be zero to allow the I/O */
520
    if ((val & mask) != 0) {
521
    fail:
522
        raise_exception_err(EXCP0D_GPF, 0);
523
    }
524
}
525

    
526
void helper_check_iob(uint32_t t0)
527
{
528
    check_io(t0, 1);
529
}
530

    
531
void helper_check_iow(uint32_t t0)
532
{
533
    check_io(t0, 2);
534
}
535

    
536
void helper_check_iol(uint32_t t0)
537
{
538
    check_io(t0, 4);
539
}
540

    
541
void helper_outb(uint32_t port, uint32_t data)
542
{
543
    cpu_outb(env, port, data & 0xff);
544
}
545

    
546
target_ulong helper_inb(uint32_t port)
547
{
548
    return cpu_inb(env, port);
549
}
550

    
551
void helper_outw(uint32_t port, uint32_t data)
552
{
553
    cpu_outw(env, port, data & 0xffff);
554
}
555

    
556
target_ulong helper_inw(uint32_t port)
557
{
558
    return cpu_inw(env, port);
559
}
560

    
561
void helper_outl(uint32_t port, uint32_t data)
562
{
563
    cpu_outl(env, port, data);
564
}
565

    
566
target_ulong helper_inl(uint32_t port)
567
{
568
    return cpu_inl(env, port);
569
}
570

    
571
static inline unsigned int get_sp_mask(unsigned int e2)
572
{
573
    if (e2 & DESC_B_MASK)
574
        return 0xffffffff;
575
    else
576
        return 0xffff;
577
}
578

    
579
#ifdef TARGET_X86_64
580
#define SET_ESP(val, sp_mask)\
581
do {\
582
    if ((sp_mask) == 0xffff)\
583
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
584
    else if ((sp_mask) == 0xffffffffLL)\
585
        ESP = (uint32_t)(val);\
586
    else\
587
        ESP = (val);\
588
} while (0)
589
#else
590
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
591
#endif
592

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

    
597
/* XXX: add a is_user flag to have proper security support */
598
#define PUSHW(ssp, sp, sp_mask, val)\
599
{\
600
    sp -= 2;\
601
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
602
}
603

    
604
#define PUSHL(ssp, sp, sp_mask, val)\
605
{\
606
    sp -= 4;\
607
    stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
608
}
609

    
610
#define POPW(ssp, sp, sp_mask, val)\
611
{\
612
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
613
    sp += 2;\
614
}
615

    
616
#define POPL(ssp, sp, sp_mask, val)\
617
{\
618
    val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
619
    sp += 4;\
620
}
621

    
622
/* protected mode interrupt */
623
static void do_interrupt_protected(int intno, int is_int, int error_code,
624
                                   unsigned int next_eip, int is_hw)
625
{
626
    SegmentCache *dt;
627
    target_ulong ptr, ssp;
628
    int type, dpl, selector, ss_dpl, cpl;
629
    int has_error_code, new_stack, shift;
630
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
631
    uint32_t old_eip, sp_mask;
632

    
633
    has_error_code = 0;
634
    if (!is_int && !is_hw) {
635
        switch(intno) {
636
        case 8:
637
        case 10:
638
        case 11:
639
        case 12:
640
        case 13:
641
        case 14:
642
        case 17:
643
            has_error_code = 1;
644
            break;
645
        }
646
    }
647
    if (is_int)
648
        old_eip = next_eip;
649
    else
650
        old_eip = env->eip;
651

    
652
    dt = &env->idt;
653
    if (intno * 8 + 7 > dt->limit)
654
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
655
    ptr = dt->base + intno * 8;
656
    e1 = ldl_kernel(ptr);
657
    e2 = ldl_kernel(ptr + 4);
658
    /* check gate type */
659
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
660
    switch(type) {
661
    case 5: /* task gate */
662
        /* must do that check here to return the correct error code */
663
        if (!(e2 & DESC_P_MASK))
664
            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
665
        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
666
        if (has_error_code) {
667
            int type;
668
            uint32_t mask;
669
            /* push the error code */
670
            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
671
            shift = type >> 3;
672
            if (env->segs[R_SS].flags & DESC_B_MASK)
673
                mask = 0xffffffff;
674
            else
675
                mask = 0xffff;
676
            esp = (ESP - (2 << shift)) & mask;
677
            ssp = env->segs[R_SS].base + esp;
678
            if (shift)
679
                stl_kernel(ssp, error_code);
680
            else
681
                stw_kernel(ssp, error_code);
682
            SET_ESP(esp, mask);
683
        }
684
        return;
685
    case 6: /* 286 interrupt gate */
686
    case 7: /* 286 trap gate */
687
    case 14: /* 386 interrupt gate */
688
    case 15: /* 386 trap gate */
689
        break;
690
    default:
691
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
692
        break;
693
    }
694
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
695
    cpl = env->hflags & HF_CPL_MASK;
696
    /* check privilege if software int */
697
    if (is_int && dpl < cpl)
698
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
699
    /* check valid bit */
700
    if (!(e2 & DESC_P_MASK))
701
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
702
    selector = e1 >> 16;
703
    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
704
    if ((selector & 0xfffc) == 0)
705
        raise_exception_err(EXCP0D_GPF, 0);
706

    
707
    if (load_segment(&e1, &e2, selector) != 0)
708
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
709
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
710
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
711
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
712
    if (dpl > cpl)
713
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
714
    if (!(e2 & DESC_P_MASK))
715
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
716
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
717
        /* to inner privilege */
718
        get_ss_esp_from_tss(&ss, &esp, dpl);
719
        if ((ss & 0xfffc) == 0)
720
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
721
        if ((ss & 3) != dpl)
722
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
723
        if (load_segment(&ss_e1, &ss_e2, ss) != 0)
724
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
725
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
726
        if (ss_dpl != dpl)
727
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
728
        if (!(ss_e2 & DESC_S_MASK) ||
729
            (ss_e2 & DESC_CS_MASK) ||
730
            !(ss_e2 & DESC_W_MASK))
731
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
732
        if (!(ss_e2 & DESC_P_MASK))
733
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
734
        new_stack = 1;
735
        sp_mask = get_sp_mask(ss_e2);
736
        ssp = get_seg_base(ss_e1, ss_e2);
737
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
738
        /* to same privilege */
739
        if (env->eflags & VM_MASK)
740
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
741
        new_stack = 0;
742
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
743
        ssp = env->segs[R_SS].base;
744
        esp = ESP;
745
        dpl = cpl;
746
    } else {
747
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
748
        new_stack = 0; /* avoid warning */
749
        sp_mask = 0; /* avoid warning */
750
        ssp = 0; /* avoid warning */
751
        esp = 0; /* avoid warning */
752
    }
753

    
754
    shift = type >> 3;
755

    
756
#if 0
757
    /* XXX: check that enough room is available */
758
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
759
    if (env->eflags & VM_MASK)
760
        push_size += 8;
761
    push_size <<= shift;
762
#endif
763
    if (shift == 1) {
764
        if (new_stack) {
765
            if (env->eflags & VM_MASK) {
766
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
767
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
768
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
769
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
770
            }
771
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
772
            PUSHL(ssp, esp, sp_mask, ESP);
773
        }
774
        PUSHL(ssp, esp, sp_mask, compute_eflags());
775
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
776
        PUSHL(ssp, esp, sp_mask, old_eip);
777
        if (has_error_code) {
778
            PUSHL(ssp, esp, sp_mask, error_code);
779
        }
780
    } else {
781
        if (new_stack) {
782
            if (env->eflags & VM_MASK) {
783
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
784
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
785
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
786
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
787
            }
788
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
789
            PUSHW(ssp, esp, sp_mask, ESP);
790
        }
791
        PUSHW(ssp, esp, sp_mask, compute_eflags());
792
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
793
        PUSHW(ssp, esp, sp_mask, old_eip);
794
        if (has_error_code) {
795
            PUSHW(ssp, esp, sp_mask, error_code);
796
        }
797
    }
798

    
799
    if (new_stack) {
800
        if (env->eflags & VM_MASK) {
801
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
802
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
803
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
804
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
805
        }
806
        ss = (ss & ~3) | dpl;
807
        cpu_x86_load_seg_cache(env, R_SS, ss,
808
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
809
    }
810
    SET_ESP(esp, sp_mask);
811

    
812
    selector = (selector & ~3) | dpl;
813
    cpu_x86_load_seg_cache(env, R_CS, selector,
814
                   get_seg_base(e1, e2),
815
                   get_seg_limit(e1, e2),
816
                   e2);
817
    cpu_x86_set_cpl(env, dpl);
818
    env->eip = offset;
819

    
820
    /* interrupt gate clear IF mask */
821
    if ((type & 1) == 0) {
822
        env->eflags &= ~IF_MASK;
823
    }
824
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
825
}
826

    
827
#ifdef TARGET_X86_64
828

    
829
#define PUSHQ(sp, val)\
830
{\
831
    sp -= 8;\
832
    stq_kernel(sp, (val));\
833
}
834

    
835
#define POPQ(sp, val)\
836
{\
837
    val = ldq_kernel(sp);\
838
    sp += 8;\
839
}
840

    
841
static inline target_ulong get_rsp_from_tss(int level)
842
{
843
    int index;
844

    
845
#if 0
846
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
847
           env->tr.base, env->tr.limit);
848
#endif
849

    
850
    if (!(env->tr.flags & DESC_P_MASK))
851
        cpu_abort(env, "invalid tss");
852
    index = 8 * level + 4;
853
    if ((index + 7) > env->tr.limit)
854
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
855
    return ldq_kernel(env->tr.base + index);
856
}
857

    
858
/* 64 bit interrupt */
859
static void do_interrupt64(int intno, int is_int, int error_code,
860
                           target_ulong next_eip, int is_hw)
861
{
862
    SegmentCache *dt;
863
    target_ulong ptr;
864
    int type, dpl, selector, cpl, ist;
865
    int has_error_code, new_stack;
866
    uint32_t e1, e2, e3, ss;
867
    target_ulong old_eip, esp, offset;
868

    
869
    has_error_code = 0;
870
    if (!is_int && !is_hw) {
871
        switch(intno) {
872
        case 8:
873
        case 10:
874
        case 11:
875
        case 12:
876
        case 13:
877
        case 14:
878
        case 17:
879
            has_error_code = 1;
880
            break;
881
        }
882
    }
883
    if (is_int)
884
        old_eip = next_eip;
885
    else
886
        old_eip = env->eip;
887

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

    
919
    if (load_segment(&e1, &e2, selector) != 0)
920
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
921
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
922
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
923
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
924
    if (dpl > cpl)
925
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
926
    if (!(e2 & DESC_P_MASK))
927
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
928
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
929
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
930
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
931
        /* to inner privilege */
932
        if (ist != 0)
933
            esp = get_rsp_from_tss(ist + 3);
934
        else
935
            esp = get_rsp_from_tss(dpl);
936
        esp &= ~0xfLL; /* align stack */
937
        ss = 0;
938
        new_stack = 1;
939
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
940
        /* to same privilege */
941
        if (env->eflags & VM_MASK)
942
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
943
        new_stack = 0;
944
        if (ist != 0)
945
            esp = get_rsp_from_tss(ist + 3);
946
        else
947
            esp = ESP;
948
        esp &= ~0xfLL; /* align stack */
949
        dpl = cpl;
950
    } else {
951
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
952
        new_stack = 0; /* avoid warning */
953
        esp = 0; /* avoid warning */
954
    }
955

    
956
    PUSHQ(esp, env->segs[R_SS].selector);
957
    PUSHQ(esp, ESP);
958
    PUSHQ(esp, compute_eflags());
959
    PUSHQ(esp, env->segs[R_CS].selector);
960
    PUSHQ(esp, old_eip);
961
    if (has_error_code) {
962
        PUSHQ(esp, error_code);
963
    }
964

    
965
    if (new_stack) {
966
        ss = 0 | dpl;
967
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
968
    }
969
    ESP = esp;
970

    
971
    selector = (selector & ~3) | dpl;
972
    cpu_x86_load_seg_cache(env, R_CS, selector,
973
                   get_seg_base(e1, e2),
974
                   get_seg_limit(e1, e2),
975
                   e2);
976
    cpu_x86_set_cpl(env, dpl);
977
    env->eip = offset;
978

    
979
    /* interrupt gate clear IF mask */
980
    if ((type & 1) == 0) {
981
        env->eflags &= ~IF_MASK;
982
    }
983
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
984
}
985
#endif
986

    
987
#if defined(CONFIG_USER_ONLY)
988
void helper_syscall(int next_eip_addend)
989
{
990
    env->exception_index = EXCP_SYSCALL;
991
    env->exception_next_eip = env->eip + next_eip_addend;
992
    cpu_loop_exit();
993
}
994
#else
995
void helper_syscall(int next_eip_addend)
996
{
997
    int selector;
998

    
999
    if (!(env->efer & MSR_EFER_SCE)) {
1000
        raise_exception_err(EXCP06_ILLOP, 0);
1001
    }
1002
    selector = (env->star >> 32) & 0xffff;
1003
#ifdef TARGET_X86_64
1004
    if (env->hflags & HF_LMA_MASK) {
1005
        int code64;
1006

    
1007
        ECX = env->eip + next_eip_addend;
1008
        env->regs[11] = compute_eflags();
1009

    
1010
        code64 = env->hflags & HF_CS64_MASK;
1011

    
1012
        cpu_x86_set_cpl(env, 0);
1013
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1014
                           0, 0xffffffff,
1015
                               DESC_G_MASK | DESC_P_MASK |
1016
                               DESC_S_MASK |
1017
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1018
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1019
                               0, 0xffffffff,
1020
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1021
                               DESC_S_MASK |
1022
                               DESC_W_MASK | DESC_A_MASK);
1023
        env->eflags &= ~env->fmask;
1024
        load_eflags(env->eflags, 0);
1025
        if (code64)
1026
            env->eip = env->lstar;
1027
        else
1028
            env->eip = env->cstar;
1029
    } else
1030
#endif
1031
    {
1032
        ECX = (uint32_t)(env->eip + next_eip_addend);
1033

    
1034
        cpu_x86_set_cpl(env, 0);
1035
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1036
                           0, 0xffffffff,
1037
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1038
                               DESC_S_MASK |
1039
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1040
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1041
                               0, 0xffffffff,
1042
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1043
                               DESC_S_MASK |
1044
                               DESC_W_MASK | DESC_A_MASK);
1045
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1046
        env->eip = (uint32_t)env->star;
1047
    }
1048
}
1049
#endif
1050

    
1051
void helper_sysret(int dflag)
1052
{
1053
    int cpl, selector;
1054

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

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

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

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

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

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

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

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

    
1184
/*
1185
 * Begin execution of an interruption. is_int is TRUE if coming from
1186
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1187
 * instruction. It is only relevant if is_int is TRUE.
1188
 */
1189
void do_interrupt(int intno, int is_int, int error_code,
1190
                  target_ulong next_eip, int is_hw)
1191
{
1192
    if (loglevel & CPU_LOG_INT) {
1193
        if ((env->cr[0] & CR0_PE_MASK)) {
1194
            static int count;
1195
            fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1196
                    count, intno, error_code, is_int,
1197
                    env->hflags & HF_CPL_MASK,
1198
                    env->segs[R_CS].selector, EIP,
1199
                    (int)env->segs[R_CS].base + EIP,
1200
                    env->segs[R_SS].selector, ESP);
1201
            if (intno == 0x0e) {
1202
                fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1203
            } else {
1204
                fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1205
            }
1206
            fprintf(logfile, "\n");
1207
            cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1208
#if 0
1209
            {
1210
                int i;
1211
                uint8_t *ptr;
1212
                fprintf(logfile, "       code=");
1213
                ptr = env->segs[R_CS].base + env->eip;
1214
                for(i = 0; i < 16; i++) {
1215
                    fprintf(logfile, " %02x", ldub(ptr + i));
1216
                }
1217
                fprintf(logfile, "\n");
1218
            }
1219
#endif
1220
            count++;
1221
        }
1222
    }
1223
    if (env->cr[0] & CR0_PE_MASK) {
1224
#ifdef TARGET_X86_64
1225
        if (env->hflags & HF_LMA_MASK) {
1226
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1227
        } else
1228
#endif
1229
        {
1230
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1231
        }
1232
    } else {
1233
        do_interrupt_real(intno, is_int, error_code, next_eip);
1234
    }
1235
}
1236

    
1237
/*
1238
 * Check nested exceptions and change to double or triple fault if
1239
 * needed. It should only be called, if this is not an interrupt.
1240
 * Returns the new exception number.
1241
 */
1242
static int check_exception(int intno, int *error_code)
1243
{
1244
    int first_contributory = env->old_exception == 0 ||
1245
                              (env->old_exception >= 10 &&
1246
                               env->old_exception <= 13);
1247
    int second_contributory = intno == 0 ||
1248
                               (intno >= 10 && intno <= 13);
1249

    
1250
    if (loglevel & CPU_LOG_INT)
1251
        fprintf(logfile, "check_exception old: 0x%x new 0x%x\n",
1252
                env->old_exception, intno);
1253

    
1254
    if (env->old_exception == EXCP08_DBLE)
1255
        cpu_abort(env, "triple fault");
1256

    
1257
    if ((first_contributory && second_contributory)
1258
        || (env->old_exception == EXCP0E_PAGE &&
1259
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1260
        intno = EXCP08_DBLE;
1261
        *error_code = 0;
1262
    }
1263

    
1264
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1265
        (intno == EXCP08_DBLE))
1266
        env->old_exception = intno;
1267

    
1268
    return intno;
1269
}
1270

    
1271
/*
1272
 * Signal an interruption. It is executed in the main CPU loop.
1273
 * is_int is TRUE if coming from the int instruction. next_eip is the
1274
 * EIP value AFTER the interrupt instruction. It is only relevant if
1275
 * is_int is TRUE.
1276
 */
1277
void raise_interrupt(int intno, int is_int, int error_code,
1278
                     int next_eip_addend)
1279
{
1280
    if (!is_int) {
1281
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1282
        intno = check_exception(intno, &error_code);
1283
    } else {
1284
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1285
    }
1286

    
1287
    env->exception_index = intno;
1288
    env->error_code = error_code;
1289
    env->exception_is_int = is_int;
1290
    env->exception_next_eip = env->eip + next_eip_addend;
1291
    cpu_loop_exit();
1292
}
1293

    
1294
/* shortcuts to generate exceptions */
1295

    
1296
void (raise_exception_err)(int exception_index, int error_code)
1297
{
1298
    raise_interrupt(exception_index, 0, error_code, 0);
1299
}
1300

    
1301
void raise_exception(int exception_index)
1302
{
1303
    raise_interrupt(exception_index, 0, 0, 0);
1304
}
1305

    
1306
/* SMM support */
1307

    
1308
#if defined(CONFIG_USER_ONLY)
1309

    
1310
void do_smm_enter(void)
1311
{
1312
}
1313

    
1314
void helper_rsm(void)
1315
{
1316
}
1317

    
1318
#else
1319

    
1320
#ifdef TARGET_X86_64
1321
#define SMM_REVISION_ID 0x00020064
1322
#else
1323
#define SMM_REVISION_ID 0x00020000
1324
#endif
1325

    
1326
void do_smm_enter(void)
1327
{
1328
    target_ulong sm_state;
1329
    SegmentCache *dt;
1330
    int i, offset;
1331

    
1332
    if (loglevel & CPU_LOG_INT) {
1333
        fprintf(logfile, "SMM: enter\n");
1334
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1335
    }
1336

    
1337
    env->hflags |= HF_SMM_MASK;
1338
    cpu_smm_update(env);
1339

    
1340
    sm_state = env->smbase + 0x8000;
1341

    
1342
#ifdef TARGET_X86_64
1343
    for(i = 0; i < 6; i++) {
1344
        dt = &env->segs[i];
1345
        offset = 0x7e00 + i * 16;
1346
        stw_phys(sm_state + offset, dt->selector);
1347
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1348
        stl_phys(sm_state + offset + 4, dt->limit);
1349
        stq_phys(sm_state + offset + 8, dt->base);
1350
    }
1351

    
1352
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1353
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1354

    
1355
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1356
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1357
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1358
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1359

    
1360
    stq_phys(sm_state + 0x7e88, env->idt.base);
1361
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1362

    
1363
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1364
    stq_phys(sm_state + 0x7e98, env->tr.base);
1365
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1366
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1367

    
1368
    stq_phys(sm_state + 0x7ed0, env->efer);
1369

    
1370
    stq_phys(sm_state + 0x7ff8, EAX);
1371
    stq_phys(sm_state + 0x7ff0, ECX);
1372
    stq_phys(sm_state + 0x7fe8, EDX);
1373
    stq_phys(sm_state + 0x7fe0, EBX);
1374
    stq_phys(sm_state + 0x7fd8, ESP);
1375
    stq_phys(sm_state + 0x7fd0, EBP);
1376
    stq_phys(sm_state + 0x7fc8, ESI);
1377
    stq_phys(sm_state + 0x7fc0, EDI);
1378
    for(i = 8; i < 16; i++)
1379
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1380
    stq_phys(sm_state + 0x7f78, env->eip);
1381
    stl_phys(sm_state + 0x7f70, compute_eflags());
1382
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1383
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1384

    
1385
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1386
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1387
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1388

    
1389
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1390
    stl_phys(sm_state + 0x7f00, env->smbase);
1391
#else
1392
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1393
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1394
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1395
    stl_phys(sm_state + 0x7ff0, env->eip);
1396
    stl_phys(sm_state + 0x7fec, EDI);
1397
    stl_phys(sm_state + 0x7fe8, ESI);
1398
    stl_phys(sm_state + 0x7fe4, EBP);
1399
    stl_phys(sm_state + 0x7fe0, ESP);
1400
    stl_phys(sm_state + 0x7fdc, EBX);
1401
    stl_phys(sm_state + 0x7fd8, EDX);
1402
    stl_phys(sm_state + 0x7fd4, ECX);
1403
    stl_phys(sm_state + 0x7fd0, EAX);
1404
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1405
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1406

    
1407
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1408
    stl_phys(sm_state + 0x7f64, env->tr.base);
1409
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1410
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1411

    
1412
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1413
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1414
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1415
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1416

    
1417
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1418
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1419

    
1420
    stl_phys(sm_state + 0x7f58, env->idt.base);
1421
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1422

    
1423
    for(i = 0; i < 6; i++) {
1424
        dt = &env->segs[i];
1425
        if (i < 3)
1426
            offset = 0x7f84 + i * 12;
1427
        else
1428
            offset = 0x7f2c + (i - 3) * 12;
1429
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1430
        stl_phys(sm_state + offset + 8, dt->base);
1431
        stl_phys(sm_state + offset + 4, dt->limit);
1432
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1433
    }
1434
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1435

    
1436
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1437
    stl_phys(sm_state + 0x7ef8, env->smbase);
1438
#endif
1439
    /* init SMM cpu state */
1440

    
1441
#ifdef TARGET_X86_64
1442
    cpu_load_efer(env, 0);
1443
#endif
1444
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1445
    env->eip = 0x00008000;
1446
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1447
                           0xffffffff, 0);
1448
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1449
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1450
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1451
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1452
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1453

    
1454
    cpu_x86_update_cr0(env,
1455
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1456
    cpu_x86_update_cr4(env, 0);
1457
    env->dr[7] = 0x00000400;
1458
    CC_OP = CC_OP_EFLAGS;
1459
}
1460

    
1461
void helper_rsm(void)
1462
{
1463
    target_ulong sm_state;
1464
    int i, offset;
1465
    uint32_t val;
1466

    
1467
    sm_state = env->smbase + 0x8000;
1468
#ifdef TARGET_X86_64
1469
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1470

    
1471
    for(i = 0; i < 6; i++) {
1472
        offset = 0x7e00 + i * 16;
1473
        cpu_x86_load_seg_cache(env, i,
1474
                               lduw_phys(sm_state + offset),
1475
                               ldq_phys(sm_state + offset + 8),
1476
                               ldl_phys(sm_state + offset + 4),
1477
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1478
    }
1479

    
1480
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1481
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1482

    
1483
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1484
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1485
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1486
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1487

    
1488
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1489
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1490

    
1491
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1492
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1493
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1494
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1495

    
1496
    EAX = ldq_phys(sm_state + 0x7ff8);
1497
    ECX = ldq_phys(sm_state + 0x7ff0);
1498
    EDX = ldq_phys(sm_state + 0x7fe8);
1499
    EBX = ldq_phys(sm_state + 0x7fe0);
1500
    ESP = ldq_phys(sm_state + 0x7fd8);
1501
    EBP = ldq_phys(sm_state + 0x7fd0);
1502
    ESI = ldq_phys(sm_state + 0x7fc8);
1503
    EDI = ldq_phys(sm_state + 0x7fc0);
1504
    for(i = 8; i < 16; i++)
1505
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1506
    env->eip = ldq_phys(sm_state + 0x7f78);
1507
    load_eflags(ldl_phys(sm_state + 0x7f70),
1508
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1509
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1510
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1511

    
1512
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1513
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1514
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1515

    
1516
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1517
    if (val & 0x20000) {
1518
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1519
    }
1520
#else
1521
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1522
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1523
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1524
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1525
    env->eip = ldl_phys(sm_state + 0x7ff0);
1526
    EDI = ldl_phys(sm_state + 0x7fec);
1527
    ESI = ldl_phys(sm_state + 0x7fe8);
1528
    EBP = ldl_phys(sm_state + 0x7fe4);
1529
    ESP = ldl_phys(sm_state + 0x7fe0);
1530
    EBX = ldl_phys(sm_state + 0x7fdc);
1531
    EDX = ldl_phys(sm_state + 0x7fd8);
1532
    ECX = ldl_phys(sm_state + 0x7fd4);
1533
    EAX = ldl_phys(sm_state + 0x7fd0);
1534
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1535
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1536

    
1537
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1538
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1539
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1540
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1541

    
1542
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1543
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1544
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1545
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1546

    
1547
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1548
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1549

    
1550
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1551
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1552

    
1553
    for(i = 0; i < 6; i++) {
1554
        if (i < 3)
1555
            offset = 0x7f84 + i * 12;
1556
        else
1557
            offset = 0x7f2c + (i - 3) * 12;
1558
        cpu_x86_load_seg_cache(env, i,
1559
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1560
                               ldl_phys(sm_state + offset + 8),
1561
                               ldl_phys(sm_state + offset + 4),
1562
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1563
    }
1564
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1565

    
1566
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1567
    if (val & 0x20000) {
1568
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1569
    }
1570
#endif
1571
    CC_OP = CC_OP_EFLAGS;
1572
    env->hflags &= ~HF_SMM_MASK;
1573
    cpu_smm_update(env);
1574

    
1575
    if (loglevel & CPU_LOG_INT) {
1576
        fprintf(logfile, "SMM: after RSM\n");
1577
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1578
    }
1579
}
1580

    
1581
#endif /* !CONFIG_USER_ONLY */
1582

    
1583

    
1584
/* division, flags are undefined */
1585

    
1586
void helper_divb_AL(target_ulong t0)
1587
{
1588
    unsigned int num, den, q, r;
1589

    
1590
    num = (EAX & 0xffff);
1591
    den = (t0 & 0xff);
1592
    if (den == 0) {
1593
        raise_exception(EXCP00_DIVZ);
1594
    }
1595
    q = (num / den);
1596
    if (q > 0xff)
1597
        raise_exception(EXCP00_DIVZ);
1598
    q &= 0xff;
1599
    r = (num % den) & 0xff;
1600
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1601
}
1602

    
1603
void helper_idivb_AL(target_ulong t0)
1604
{
1605
    int num, den, q, r;
1606

    
1607
    num = (int16_t)EAX;
1608
    den = (int8_t)t0;
1609
    if (den == 0) {
1610
        raise_exception(EXCP00_DIVZ);
1611
    }
1612
    q = (num / den);
1613
    if (q != (int8_t)q)
1614
        raise_exception(EXCP00_DIVZ);
1615
    q &= 0xff;
1616
    r = (num % den) & 0xff;
1617
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1618
}
1619

    
1620
void helper_divw_AX(target_ulong t0)
1621
{
1622
    unsigned int num, den, q, r;
1623

    
1624
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1625
    den = (t0 & 0xffff);
1626
    if (den == 0) {
1627
        raise_exception(EXCP00_DIVZ);
1628
    }
1629
    q = (num / den);
1630
    if (q > 0xffff)
1631
        raise_exception(EXCP00_DIVZ);
1632
    q &= 0xffff;
1633
    r = (num % den) & 0xffff;
1634
    EAX = (EAX & ~0xffff) | q;
1635
    EDX = (EDX & ~0xffff) | r;
1636
}
1637

    
1638
void helper_idivw_AX(target_ulong t0)
1639
{
1640
    int num, den, q, r;
1641

    
1642
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1643
    den = (int16_t)t0;
1644
    if (den == 0) {
1645
        raise_exception(EXCP00_DIVZ);
1646
    }
1647
    q = (num / den);
1648
    if (q != (int16_t)q)
1649
        raise_exception(EXCP00_DIVZ);
1650
    q &= 0xffff;
1651
    r = (num % den) & 0xffff;
1652
    EAX = (EAX & ~0xffff) | q;
1653
    EDX = (EDX & ~0xffff) | r;
1654
}
1655

    
1656
void helper_divl_EAX(target_ulong t0)
1657
{
1658
    unsigned int den, r;
1659
    uint64_t num, q;
1660

    
1661
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1662
    den = t0;
1663
    if (den == 0) {
1664
        raise_exception(EXCP00_DIVZ);
1665
    }
1666
    q = (num / den);
1667
    r = (num % den);
1668
    if (q > 0xffffffff)
1669
        raise_exception(EXCP00_DIVZ);
1670
    EAX = (uint32_t)q;
1671
    EDX = (uint32_t)r;
1672
}
1673

    
1674
void helper_idivl_EAX(target_ulong t0)
1675
{
1676
    int den, r;
1677
    int64_t num, q;
1678

    
1679
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1680
    den = t0;
1681
    if (den == 0) {
1682
        raise_exception(EXCP00_DIVZ);
1683
    }
1684
    q = (num / den);
1685
    r = (num % den);
1686
    if (q != (int32_t)q)
1687
        raise_exception(EXCP00_DIVZ);
1688
    EAX = (uint32_t)q;
1689
    EDX = (uint32_t)r;
1690
}
1691

    
1692
/* bcd */
1693

    
1694
/* XXX: exception */
1695
void helper_aam(int base)
1696
{
1697
    int al, ah;
1698
    al = EAX & 0xff;
1699
    ah = al / base;
1700
    al = al % base;
1701
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1702
    CC_DST = al;
1703
}
1704

    
1705
void helper_aad(int base)
1706
{
1707
    int al, ah;
1708
    al = EAX & 0xff;
1709
    ah = (EAX >> 8) & 0xff;
1710
    al = ((ah * base) + al) & 0xff;
1711
    EAX = (EAX & ~0xffff) | al;
1712
    CC_DST = al;
1713
}
1714

    
1715
void helper_aaa(void)
1716
{
1717
    int icarry;
1718
    int al, ah, af;
1719
    int eflags;
1720

    
1721
    eflags = cc_table[CC_OP].compute_all();
1722
    af = eflags & CC_A;
1723
    al = EAX & 0xff;
1724
    ah = (EAX >> 8) & 0xff;
1725

    
1726
    icarry = (al > 0xf9);
1727
    if (((al & 0x0f) > 9 ) || af) {
1728
        al = (al + 6) & 0x0f;
1729
        ah = (ah + 1 + icarry) & 0xff;
1730
        eflags |= CC_C | CC_A;
1731
    } else {
1732
        eflags &= ~(CC_C | CC_A);
1733
        al &= 0x0f;
1734
    }
1735
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1736
    CC_SRC = eflags;
1737
    FORCE_RET();
1738
}
1739

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

    
1746
    eflags = cc_table[CC_OP].compute_all();
1747
    af = eflags & CC_A;
1748
    al = EAX & 0xff;
1749
    ah = (EAX >> 8) & 0xff;
1750

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

    
1765
void helper_daa(void)
1766
{
1767
    int al, af, cf;
1768
    int eflags;
1769

    
1770
    eflags = cc_table[CC_OP].compute_all();
1771
    cf = eflags & CC_C;
1772
    af = eflags & CC_A;
1773
    al = EAX & 0xff;
1774

    
1775
    eflags = 0;
1776
    if (((al & 0x0f) > 9 ) || af) {
1777
        al = (al + 6) & 0xff;
1778
        eflags |= CC_A;
1779
    }
1780
    if ((al > 0x9f) || cf) {
1781
        al = (al + 0x60) & 0xff;
1782
        eflags |= CC_C;
1783
    }
1784
    EAX = (EAX & ~0xff) | al;
1785
    /* well, speed is not an issue here, so we compute the flags by hand */
1786
    eflags |= (al == 0) << 6; /* zf */
1787
    eflags |= parity_table[al]; /* pf */
1788
    eflags |= (al & 0x80); /* sf */
1789
    CC_SRC = eflags;
1790
    FORCE_RET();
1791
}
1792

    
1793
void helper_das(void)
1794
{
1795
    int al, al1, af, cf;
1796
    int eflags;
1797

    
1798
    eflags = cc_table[CC_OP].compute_all();
1799
    cf = eflags & CC_C;
1800
    af = eflags & CC_A;
1801
    al = EAX & 0xff;
1802

    
1803
    eflags = 0;
1804
    al1 = al;
1805
    if (((al & 0x0f) > 9 ) || af) {
1806
        eflags |= CC_A;
1807
        if (al < 6 || cf)
1808
            eflags |= CC_C;
1809
        al = (al - 6) & 0xff;
1810
    }
1811
    if ((al1 > 0x99) || cf) {
1812
        al = (al - 0x60) & 0xff;
1813
        eflags |= CC_C;
1814
    }
1815
    EAX = (EAX & ~0xff) | al;
1816
    /* well, speed is not an issue here, so we compute the flags by hand */
1817
    eflags |= (al == 0) << 6; /* zf */
1818
    eflags |= parity_table[al]; /* pf */
1819
    eflags |= (al & 0x80); /* sf */
1820
    CC_SRC = eflags;
1821
    FORCE_RET();
1822
}
1823

    
1824
void helper_into(int next_eip_addend)
1825
{
1826
    int eflags;
1827
    eflags = cc_table[CC_OP].compute_all();
1828
    if (eflags & CC_O) {
1829
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1830
    }
1831
}
1832

    
1833
void helper_cmpxchg8b(target_ulong a0)
1834
{
1835
    uint64_t d;
1836
    int eflags;
1837

    
1838
    eflags = cc_table[CC_OP].compute_all();
1839
    d = ldq(a0);
1840
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1841
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1842
        eflags |= CC_Z;
1843
    } else {
1844
        /* always do the store */
1845
        stq(a0, d); 
1846
        EDX = (uint32_t)(d >> 32);
1847
        EAX = (uint32_t)d;
1848
        eflags &= ~CC_Z;
1849
    }
1850
    CC_SRC = eflags;
1851
}
1852

    
1853
#ifdef TARGET_X86_64
1854
void helper_cmpxchg16b(target_ulong a0)
1855
{
1856
    uint64_t d0, d1;
1857
    int eflags;
1858

    
1859
    if ((a0 & 0xf) != 0)
1860
        raise_exception(EXCP0D_GPF);
1861
    eflags = cc_table[CC_OP].compute_all();
1862
    d0 = ldq(a0);
1863
    d1 = ldq(a0 + 8);
1864
    if (d0 == EAX && d1 == EDX) {
1865
        stq(a0, EBX);
1866
        stq(a0 + 8, ECX);
1867
        eflags |= CC_Z;
1868
    } else {
1869
        /* always do the store */
1870
        stq(a0, d0); 
1871
        stq(a0 + 8, d1); 
1872
        EDX = d1;
1873
        EAX = d0;
1874
        eflags &= ~CC_Z;
1875
    }
1876
    CC_SRC = eflags;
1877
}
1878
#endif
1879

    
1880
void helper_single_step(void)
1881
{
1882
    env->dr[6] |= 0x4000;
1883
    raise_exception(EXCP01_SSTP);
1884
}
1885

    
1886
void helper_cpuid(void)
1887
{
1888
    uint32_t index;
1889

    
1890
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1891
    
1892
    index = (uint32_t)EAX;
1893
    /* test if maximum index reached */
1894
    if (index & 0x80000000) {
1895
        if (index > env->cpuid_xlevel)
1896
            index = env->cpuid_level;
1897
    } else {
1898
        if (index > env->cpuid_level)
1899
            index = env->cpuid_level;
1900
    }
1901

    
1902
    switch(index) {
1903
    case 0:
1904
        EAX = env->cpuid_level;
1905
        EBX = env->cpuid_vendor1;
1906
        EDX = env->cpuid_vendor2;
1907
        ECX = env->cpuid_vendor3;
1908
        break;
1909
    case 1:
1910
        EAX = env->cpuid_version;
1911
        EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1912
        ECX = env->cpuid_ext_features;
1913
        EDX = env->cpuid_features;
1914
        break;
1915
    case 2:
1916
        /* cache info: needed for Pentium Pro compatibility */
1917
        EAX = 1;
1918
        EBX = 0;
1919
        ECX = 0;
1920
        EDX = 0x2c307d;
1921
        break;
1922
    case 4:
1923
        /* cache info: needed for Core compatibility */
1924
        switch (ECX) {
1925
            case 0: /* L1 dcache info */
1926
                EAX = 0x0000121;
1927
                EBX = 0x1c0003f;
1928
                ECX = 0x000003f;
1929
                EDX = 0x0000001;
1930
                break;
1931
            case 1: /* L1 icache info */
1932
                EAX = 0x0000122;
1933
                EBX = 0x1c0003f;
1934
                ECX = 0x000003f;
1935
                EDX = 0x0000001;
1936
                break;
1937
            case 2: /* L2 cache info */
1938
                EAX = 0x0000143;
1939
                EBX = 0x3c0003f;
1940
                ECX = 0x0000fff;
1941
                EDX = 0x0000001;
1942
                break;
1943
            default: /* end of info */
1944
                EAX = 0;
1945
                EBX = 0;
1946
                ECX = 0;
1947
                EDX = 0;
1948
                break;
1949
        }
1950

    
1951
        break;
1952
    case 5:
1953
        /* mwait info: needed for Core compatibility */
1954
        EAX = 0; /* Smallest monitor-line size in bytes */
1955
        EBX = 0; /* Largest monitor-line size in bytes */
1956
        ECX = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
1957
        EDX = 0;
1958
        break;
1959
    case 6:
1960
        /* Thermal and Power Leaf */
1961
        EAX = 0;
1962
        EBX = 0;
1963
        ECX = 0;
1964
        EDX = 0;
1965
        break;
1966
    case 9:
1967
        /* Direct Cache Access Information Leaf */
1968
        EAX = 0; /* Bits 0-31 in DCA_CAP MSR */
1969
        EBX = 0;
1970
        ECX = 0;
1971
        EDX = 0;
1972
        break;
1973
    case 0xA:
1974
        /* Architectural Performance Monitoring Leaf */
1975
        EAX = 0;
1976
        EBX = 0;
1977
        ECX = 0;
1978
        EDX = 0;
1979
        break;
1980
    case 0x80000000:
1981
        EAX = env->cpuid_xlevel;
1982
        EBX = env->cpuid_vendor1;
1983
        EDX = env->cpuid_vendor2;
1984
        ECX = env->cpuid_vendor3;
1985
        break;
1986
    case 0x80000001:
1987
        EAX = env->cpuid_features;
1988
        EBX = 0;
1989
        ECX = env->cpuid_ext3_features;
1990
        EDX = env->cpuid_ext2_features;
1991
        break;
1992
    case 0x80000002:
1993
    case 0x80000003:
1994
    case 0x80000004:
1995
        EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1996
        EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1997
        ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1998
        EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1999
        break;
2000
    case 0x80000005:
2001
        /* cache info (L1 cache) */
2002
        EAX = 0x01ff01ff;
2003
        EBX = 0x01ff01ff;
2004
        ECX = 0x40020140;
2005
        EDX = 0x40020140;
2006
        break;
2007
    case 0x80000006:
2008
        /* cache info (L2 cache) */
2009
        EAX = 0;
2010
        EBX = 0x42004200;
2011
        ECX = 0x02008140;
2012
        EDX = 0;
2013
        break;
2014
    case 0x80000008:
2015
        /* virtual & phys address size in low 2 bytes. */
2016
/* XXX: This value must match the one used in the MMU code. */ 
2017
        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
2018
            /* 64 bit processor */
2019
#if defined(USE_KQEMU)
2020
            EAX = 0x00003020;        /* 48 bits virtual, 32 bits physical */
2021
#else
2022
/* XXX: The physical address space is limited to 42 bits in exec.c. */
2023
            EAX = 0x00003028;        /* 48 bits virtual, 40 bits physical */
2024
#endif
2025
        } else {
2026
#if defined(USE_KQEMU)
2027
            EAX = 0x00000020;        /* 32 bits physical */
2028
#else
2029
            EAX = 0x00000024;        /* 36 bits physical */
2030
#endif
2031
        }
2032
        EBX = 0;
2033
        ECX = 0;
2034
        EDX = 0;
2035
        break;
2036
    case 0x8000000A:
2037
        EAX = 0x00000001;
2038
        EBX = 0;
2039
        ECX = 0;
2040
        EDX = 0;
2041
        break;
2042
    default:
2043
        /* reserved values: zero */
2044
        EAX = 0;
2045
        EBX = 0;
2046
        ECX = 0;
2047
        EDX = 0;
2048
        break;
2049
    }
2050
}
2051

    
2052
void helper_enter_level(int level, int data32, target_ulong t1)
2053
{
2054
    target_ulong ssp;
2055
    uint32_t esp_mask, esp, ebp;
2056

    
2057
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2058
    ssp = env->segs[R_SS].base;
2059
    ebp = EBP;
2060
    esp = ESP;
2061
    if (data32) {
2062
        /* 32 bit */
2063
        esp -= 4;
2064
        while (--level) {
2065
            esp -= 4;
2066
            ebp -= 4;
2067
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
2068
        }
2069
        esp -= 4;
2070
        stl(ssp + (esp & esp_mask), t1);
2071
    } else {
2072
        /* 16 bit */
2073
        esp -= 2;
2074
        while (--level) {
2075
            esp -= 2;
2076
            ebp -= 2;
2077
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
2078
        }
2079
        esp -= 2;
2080
        stw(ssp + (esp & esp_mask), t1);
2081
    }
2082
}
2083

    
2084
#ifdef TARGET_X86_64
2085
void helper_enter64_level(int level, int data64, target_ulong t1)
2086
{
2087
    target_ulong esp, ebp;
2088
    ebp = EBP;
2089
    esp = ESP;
2090

    
2091
    if (data64) {
2092
        /* 64 bit */
2093
        esp -= 8;
2094
        while (--level) {
2095
            esp -= 8;
2096
            ebp -= 8;
2097
            stq(esp, ldq(ebp));
2098
        }
2099
        esp -= 8;
2100
        stq(esp, t1);
2101
    } else {
2102
        /* 16 bit */
2103
        esp -= 2;
2104
        while (--level) {
2105
            esp -= 2;
2106
            ebp -= 2;
2107
            stw(esp, lduw(ebp));
2108
        }
2109
        esp -= 2;
2110
        stw(esp, t1);
2111
    }
2112
}
2113
#endif
2114

    
2115
void helper_lldt(int selector)
2116
{
2117
    SegmentCache *dt;
2118
    uint32_t e1, e2;
2119
    int index, entry_limit;
2120
    target_ulong ptr;
2121

    
2122
    selector &= 0xffff;
2123
    if ((selector & 0xfffc) == 0) {
2124
        /* XXX: NULL selector case: invalid LDT */
2125
        env->ldt.base = 0;
2126
        env->ldt.limit = 0;
2127
    } else {
2128
        if (selector & 0x4)
2129
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2130
        dt = &env->gdt;
2131
        index = selector & ~7;
2132
#ifdef TARGET_X86_64
2133
        if (env->hflags & HF_LMA_MASK)
2134
            entry_limit = 15;
2135
        else
2136
#endif
2137
            entry_limit = 7;
2138
        if ((index + entry_limit) > dt->limit)
2139
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2140
        ptr = dt->base + index;
2141
        e1 = ldl_kernel(ptr);
2142
        e2 = ldl_kernel(ptr + 4);
2143
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2144
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2145
        if (!(e2 & DESC_P_MASK))
2146
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2147
#ifdef TARGET_X86_64
2148
        if (env->hflags & HF_LMA_MASK) {
2149
            uint32_t e3;
2150
            e3 = ldl_kernel(ptr + 8);
2151
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2152
            env->ldt.base |= (target_ulong)e3 << 32;
2153
        } else
2154
#endif
2155
        {
2156
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2157
        }
2158
    }
2159
    env->ldt.selector = selector;
2160
}
2161

    
2162
void helper_ltr(int selector)
2163
{
2164
    SegmentCache *dt;
2165
    uint32_t e1, e2;
2166
    int index, type, entry_limit;
2167
    target_ulong ptr;
2168

    
2169
    selector &= 0xffff;
2170
    if ((selector & 0xfffc) == 0) {
2171
        /* NULL selector case: invalid TR */
2172
        env->tr.base = 0;
2173
        env->tr.limit = 0;
2174
        env->tr.flags = 0;
2175
    } else {
2176
        if (selector & 0x4)
2177
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2178
        dt = &env->gdt;
2179
        index = selector & ~7;
2180
#ifdef TARGET_X86_64
2181
        if (env->hflags & HF_LMA_MASK)
2182
            entry_limit = 15;
2183
        else
2184
#endif
2185
            entry_limit = 7;
2186
        if ((index + entry_limit) > dt->limit)
2187
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2188
        ptr = dt->base + index;
2189
        e1 = ldl_kernel(ptr);
2190
        e2 = ldl_kernel(ptr + 4);
2191
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2192
        if ((e2 & DESC_S_MASK) ||
2193
            (type != 1 && type != 9))
2194
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2195
        if (!(e2 & DESC_P_MASK))
2196
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2197
#ifdef TARGET_X86_64
2198
        if (env->hflags & HF_LMA_MASK) {
2199
            uint32_t e3, e4;
2200
            e3 = ldl_kernel(ptr + 8);
2201
            e4 = ldl_kernel(ptr + 12);
2202
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2203
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2204
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2205
            env->tr.base |= (target_ulong)e3 << 32;
2206
        } else
2207
#endif
2208
        {
2209
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2210
        }
2211
        e2 |= DESC_TSS_BUSY_MASK;
2212
        stl_kernel(ptr + 4, e2);
2213
    }
2214
    env->tr.selector = selector;
2215
}
2216

    
2217
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2218
void helper_load_seg(int seg_reg, int selector)
2219
{
2220
    uint32_t e1, e2;
2221
    int cpl, dpl, rpl;
2222
    SegmentCache *dt;
2223
    int index;
2224
    target_ulong ptr;
2225

    
2226
    selector &= 0xffff;
2227
    cpl = env->hflags & HF_CPL_MASK;
2228
    if ((selector & 0xfffc) == 0) {
2229
        /* null selector case */
2230
        if (seg_reg == R_SS
2231
#ifdef TARGET_X86_64
2232
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2233
#endif
2234
            )
2235
            raise_exception_err(EXCP0D_GPF, 0);
2236
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2237
    } else {
2238

    
2239
        if (selector & 0x4)
2240
            dt = &env->ldt;
2241
        else
2242
            dt = &env->gdt;
2243
        index = selector & ~7;
2244
        if ((index + 7) > dt->limit)
2245
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2246
        ptr = dt->base + index;
2247
        e1 = ldl_kernel(ptr);
2248
        e2 = ldl_kernel(ptr + 4);
2249

    
2250
        if (!(e2 & DESC_S_MASK))
2251
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2252
        rpl = selector & 3;
2253
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2254
        if (seg_reg == R_SS) {
2255
            /* must be writable segment */
2256
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2257
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2258
            if (rpl != cpl || dpl != cpl)
2259
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2260
        } else {
2261
            /* must be readable segment */
2262
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2263
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2264

    
2265
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2266
                /* if not conforming code, test rights */
2267
                if (dpl < cpl || dpl < rpl)
2268
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2269
            }
2270
        }
2271

    
2272
        if (!(e2 & DESC_P_MASK)) {
2273
            if (seg_reg == R_SS)
2274
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2275
            else
2276
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2277
        }
2278

    
2279
        /* set the access bit if not already set */
2280
        if (!(e2 & DESC_A_MASK)) {
2281
            e2 |= DESC_A_MASK;
2282
            stl_kernel(ptr + 4, e2);
2283
        }
2284

    
2285
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2286
                       get_seg_base(e1, e2),
2287
                       get_seg_limit(e1, e2),
2288
                       e2);
2289
#if 0
2290
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2291
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2292
#endif
2293
    }
2294
}
2295

    
2296
/* protected mode jump */
2297
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2298
                           int next_eip_addend)
2299
{
2300
    int gate_cs, type;
2301
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2302
    target_ulong next_eip;
2303

    
2304
    if ((new_cs & 0xfffc) == 0)
2305
        raise_exception_err(EXCP0D_GPF, 0);
2306
    if (load_segment(&e1, &e2, new_cs) != 0)
2307
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2308
    cpl = env->hflags & HF_CPL_MASK;
2309
    if (e2 & DESC_S_MASK) {
2310
        if (!(e2 & DESC_CS_MASK))
2311
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2312
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2313
        if (e2 & DESC_C_MASK) {
2314
            /* conforming code segment */
2315
            if (dpl > cpl)
2316
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2317
        } else {
2318
            /* non conforming code segment */
2319
            rpl = new_cs & 3;
2320
            if (rpl > cpl)
2321
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2322
            if (dpl != cpl)
2323
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2324
        }
2325
        if (!(e2 & DESC_P_MASK))
2326
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2327
        limit = get_seg_limit(e1, e2);
2328
        if (new_eip > limit &&
2329
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2330
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2331
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2332
                       get_seg_base(e1, e2), limit, e2);
2333
        EIP = new_eip;
2334
    } else {
2335
        /* jump to call or task gate */
2336
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2337
        rpl = new_cs & 3;
2338
        cpl = env->hflags & HF_CPL_MASK;
2339
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2340
        switch(type) {
2341
        case 1: /* 286 TSS */
2342
        case 9: /* 386 TSS */
2343
        case 5: /* task gate */
2344
            if (dpl < cpl || dpl < rpl)
2345
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2346
            next_eip = env->eip + next_eip_addend;
2347
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2348
            CC_OP = CC_OP_EFLAGS;
2349
            break;
2350
        case 4: /* 286 call gate */
2351
        case 12: /* 386 call gate */
2352
            if ((dpl < cpl) || (dpl < rpl))
2353
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2354
            if (!(e2 & DESC_P_MASK))
2355
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2356
            gate_cs = e1 >> 16;
2357
            new_eip = (e1 & 0xffff);
2358
            if (type == 12)
2359
                new_eip |= (e2 & 0xffff0000);
2360
            if (load_segment(&e1, &e2, gate_cs) != 0)
2361
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2362
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2363
            /* must be code segment */
2364
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2365
                 (DESC_S_MASK | DESC_CS_MASK)))
2366
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2367
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2368
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2369
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2370
            if (!(e2 & DESC_P_MASK))
2371
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2372
            limit = get_seg_limit(e1, e2);
2373
            if (new_eip > limit)
2374
                raise_exception_err(EXCP0D_GPF, 0);
2375
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2376
                                   get_seg_base(e1, e2), limit, e2);
2377
            EIP = new_eip;
2378
            break;
2379
        default:
2380
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2381
            break;
2382
        }
2383
    }
2384
}
2385

    
2386
/* real mode call */
2387
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2388
                       int shift, int next_eip)
2389
{
2390
    int new_eip;
2391
    uint32_t esp, esp_mask;
2392
    target_ulong ssp;
2393

    
2394
    new_eip = new_eip1;
2395
    esp = ESP;
2396
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2397
    ssp = env->segs[R_SS].base;
2398
    if (shift) {
2399
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2400
        PUSHL(ssp, esp, esp_mask, next_eip);
2401
    } else {
2402
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2403
        PUSHW(ssp, esp, esp_mask, next_eip);
2404
    }
2405

    
2406
    SET_ESP(esp, esp_mask);
2407
    env->eip = new_eip;
2408
    env->segs[R_CS].selector = new_cs;
2409
    env->segs[R_CS].base = (new_cs << 4);
2410
}
2411

    
2412
/* protected mode call */
2413
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2414
                            int shift, int next_eip_addend)
2415
{
2416
    int new_stack, i;
2417
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2418
    uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
2419
    uint32_t val, limit, old_sp_mask;
2420
    target_ulong ssp, old_ssp, next_eip;
2421

    
2422
    next_eip = env->eip + next_eip_addend;
2423
#ifdef DEBUG_PCALL
2424
    if (loglevel & CPU_LOG_PCALL) {
2425
        fprintf(logfile, "lcall %04x:%08x s=%d\n",
2426
                new_cs, (uint32_t)new_eip, shift);
2427
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2428
    }
2429
#endif
2430
    if ((new_cs & 0xfffc) == 0)
2431
        raise_exception_err(EXCP0D_GPF, 0);
2432
    if (load_segment(&e1, &e2, new_cs) != 0)
2433
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2434
    cpl = env->hflags & HF_CPL_MASK;
2435
#ifdef DEBUG_PCALL
2436
    if (loglevel & CPU_LOG_PCALL) {
2437
        fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
2438
    }
2439
#endif
2440
    if (e2 & DESC_S_MASK) {
2441
        if (!(e2 & DESC_CS_MASK))
2442
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2443
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2444
        if (e2 & DESC_C_MASK) {
2445
            /* conforming code segment */
2446
            if (dpl > cpl)
2447
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2448
        } else {
2449
            /* non conforming code segment */
2450
            rpl = new_cs & 3;
2451
            if (rpl > cpl)
2452
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2453
            if (dpl != cpl)
2454
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2455
        }
2456
        if (!(e2 & DESC_P_MASK))
2457
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2458

    
2459
#ifdef TARGET_X86_64
2460
        /* XXX: check 16/32 bit cases in long mode */
2461
        if (shift == 2) {
2462
            target_ulong rsp;
2463
            /* 64 bit case */
2464
            rsp = ESP;
2465
            PUSHQ(rsp, env->segs[R_CS].selector);
2466
            PUSHQ(rsp, next_eip);
2467
            /* from this point, not restartable */
2468
            ESP = rsp;
2469
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2470
                                   get_seg_base(e1, e2),
2471
                                   get_seg_limit(e1, e2), e2);
2472
            EIP = new_eip;
2473
        } else
2474
#endif
2475
        {
2476
            sp = ESP;
2477
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2478
            ssp = env->segs[R_SS].base;
2479
            if (shift) {
2480
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2481
                PUSHL(ssp, sp, sp_mask, next_eip);
2482
            } else {
2483
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2484
                PUSHW(ssp, sp, sp_mask, next_eip);
2485
            }
2486

    
2487
            limit = get_seg_limit(e1, e2);
2488
            if (new_eip > limit)
2489
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2490
            /* from this point, not restartable */
2491
            SET_ESP(sp, sp_mask);
2492
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2493
                                   get_seg_base(e1, e2), limit, e2);
2494
            EIP = new_eip;
2495
        }
2496
    } else {
2497
        /* check gate type */
2498
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2499
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2500
        rpl = new_cs & 3;
2501
        switch(type) {
2502
        case 1: /* available 286 TSS */
2503
        case 9: /* available 386 TSS */
2504
        case 5: /* task gate */
2505
            if (dpl < cpl || dpl < rpl)
2506
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2507
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2508
            CC_OP = CC_OP_EFLAGS;
2509
            return;
2510
        case 4: /* 286 call gate */
2511
        case 12: /* 386 call gate */
2512
            break;
2513
        default:
2514
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2515
            break;
2516
        }
2517
        shift = type >> 3;
2518

    
2519
        if (dpl < cpl || dpl < rpl)
2520
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2521
        /* check valid bit */
2522
        if (!(e2 & DESC_P_MASK))
2523
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2524
        selector = e1 >> 16;
2525
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2526
        param_count = e2 & 0x1f;
2527
        if ((selector & 0xfffc) == 0)
2528
            raise_exception_err(EXCP0D_GPF, 0);
2529

    
2530
        if (load_segment(&e1, &e2, selector) != 0)
2531
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2532
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2533
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2534
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2535
        if (dpl > cpl)
2536
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2537
        if (!(e2 & DESC_P_MASK))
2538
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2539

    
2540
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2541
            /* to inner privilege */
2542
            get_ss_esp_from_tss(&ss, &sp, dpl);
2543
#ifdef DEBUG_PCALL
2544
            if (loglevel & CPU_LOG_PCALL)
2545
                fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2546
                        ss, sp, param_count, ESP);
2547
#endif
2548
            if ((ss & 0xfffc) == 0)
2549
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2550
            if ((ss & 3) != dpl)
2551
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2552
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2553
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2554
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2555
            if (ss_dpl != dpl)
2556
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2557
            if (!(ss_e2 & DESC_S_MASK) ||
2558
                (ss_e2 & DESC_CS_MASK) ||
2559
                !(ss_e2 & DESC_W_MASK))
2560
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2561
            if (!(ss_e2 & DESC_P_MASK))
2562
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2563

    
2564
            //            push_size = ((param_count * 2) + 8) << shift;
2565

    
2566
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2567
            old_ssp = env->segs[R_SS].base;
2568

    
2569
            sp_mask = get_sp_mask(ss_e2);
2570
            ssp = get_seg_base(ss_e1, ss_e2);
2571
            if (shift) {
2572
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2573
                PUSHL(ssp, sp, sp_mask, ESP);
2574
                for(i = param_count - 1; i >= 0; i--) {
2575
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2576
                    PUSHL(ssp, sp, sp_mask, val);
2577
                }
2578
            } else {
2579
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2580
                PUSHW(ssp, sp, sp_mask, ESP);
2581
                for(i = param_count - 1; i >= 0; i--) {
2582
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2583
                    PUSHW(ssp, sp, sp_mask, val);
2584
                }
2585
            }
2586
            new_stack = 1;
2587
        } else {
2588
            /* to same privilege */
2589
            sp = ESP;
2590
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2591
            ssp = env->segs[R_SS].base;
2592
            //            push_size = (4 << shift);
2593
            new_stack = 0;
2594
        }
2595

    
2596
        if (shift) {
2597
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2598
            PUSHL(ssp, sp, sp_mask, next_eip);
2599
        } else {
2600
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2601
            PUSHW(ssp, sp, sp_mask, next_eip);
2602
        }
2603

    
2604
        /* from this point, not restartable */
2605

    
2606
        if (new_stack) {
2607
            ss = (ss & ~3) | dpl;
2608
            cpu_x86_load_seg_cache(env, R_SS, ss,
2609
                                   ssp,
2610
                                   get_seg_limit(ss_e1, ss_e2),
2611
                                   ss_e2);
2612
        }
2613

    
2614
        selector = (selector & ~3) | dpl;
2615
        cpu_x86_load_seg_cache(env, R_CS, selector,
2616
                       get_seg_base(e1, e2),
2617
                       get_seg_limit(e1, e2),
2618
                       e2);
2619
        cpu_x86_set_cpl(env, dpl);
2620
        SET_ESP(sp, sp_mask);
2621
        EIP = offset;
2622
    }
2623
#ifdef USE_KQEMU
2624
    if (kqemu_is_ok(env)) {
2625
        env->exception_index = -1;
2626
        cpu_loop_exit();
2627
    }
2628
#endif
2629
}
2630

    
2631
/* real and vm86 mode iret */
2632
void helper_iret_real(int shift)
2633
{
2634
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2635
    target_ulong ssp;
2636
    int eflags_mask;
2637

    
2638
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2639
    sp = ESP;
2640
    ssp = env->segs[R_SS].base;
2641
    if (shift == 1) {
2642
        /* 32 bits */
2643
        POPL(ssp, sp, sp_mask, new_eip);
2644
        POPL(ssp, sp, sp_mask, new_cs);
2645
        new_cs &= 0xffff;
2646
        POPL(ssp, sp, sp_mask, new_eflags);
2647
    } else {
2648
        /* 16 bits */
2649
        POPW(ssp, sp, sp_mask, new_eip);
2650
        POPW(ssp, sp, sp_mask, new_cs);
2651
        POPW(ssp, sp, sp_mask, new_eflags);
2652
    }
2653
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2654
    load_seg_vm(R_CS, new_cs);
2655
    env->eip = new_eip;
2656
    if (env->eflags & VM_MASK)
2657
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2658
    else
2659
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2660
    if (shift == 0)
2661
        eflags_mask &= 0xffff;
2662
    load_eflags(new_eflags, eflags_mask);
2663
    env->hflags2 &= ~HF2_NMI_MASK;
2664
}
2665

    
2666
static inline void validate_seg(int seg_reg, int cpl)
2667
{
2668
    int dpl;
2669
    uint32_t e2;
2670

    
2671
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2672
       they may still contain a valid base. I would be interested to
2673
       know how a real x86_64 CPU behaves */
2674
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2675
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2676
        return;
2677

    
2678
    e2 = env->segs[seg_reg].flags;
2679
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2680
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2681
        /* data or non conforming code segment */
2682
        if (dpl < cpl) {
2683
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2684
        }
2685
    }
2686
}
2687

    
2688
/* protected mode iret */
2689
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2690
{
2691
    uint32_t new_cs, new_eflags, new_ss;
2692
    uint32_t new_es, new_ds, new_fs, new_gs;
2693
    uint32_t e1, e2, ss_e1, ss_e2;
2694
    int cpl, dpl, rpl, eflags_mask, iopl;
2695
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2696

    
2697
#ifdef TARGET_X86_64
2698
    if (shift == 2)
2699
        sp_mask = -1;
2700
    else
2701
#endif
2702
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2703
    sp = ESP;
2704
    ssp = env->segs[R_SS].base;
2705
    new_eflags = 0; /* avoid warning */
2706
#ifdef TARGET_X86_64
2707
    if (shift == 2) {
2708
        POPQ(sp, new_eip);
2709
        POPQ(sp, new_cs);
2710
        new_cs &= 0xffff;
2711
        if (is_iret) {
2712
            POPQ(sp, new_eflags);
2713
        }
2714
    } else
2715
#endif
2716
    if (shift == 1) {
2717
        /* 32 bits */
2718
        POPL(ssp, sp, sp_mask, new_eip);
2719
        POPL(ssp, sp, sp_mask, new_cs);
2720
        new_cs &= 0xffff;
2721
        if (is_iret) {
2722
            POPL(ssp, sp, sp_mask, new_eflags);
2723
            if (new_eflags & VM_MASK)
2724
                goto return_to_vm86;
2725
        }
2726
    } else {
2727
        /* 16 bits */
2728
        POPW(ssp, sp, sp_mask, new_eip);
2729
        POPW(ssp, sp, sp_mask, new_cs);
2730
        if (is_iret)
2731
            POPW(ssp, sp, sp_mask, new_eflags);
2732
    }
2733
#ifdef DEBUG_PCALL
2734
    if (loglevel & CPU_LOG_PCALL) {
2735
        fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2736
                new_cs, new_eip, shift, addend);
2737
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2738
    }
2739
#endif
2740
    if ((new_cs & 0xfffc) == 0)
2741
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2742
    if (load_segment(&e1, &e2, new_cs) != 0)
2743
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2744
    if (!(e2 & DESC_S_MASK) ||
2745
        !(e2 & DESC_CS_MASK))
2746
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2747
    cpl = env->hflags & HF_CPL_MASK;
2748
    rpl = new_cs & 3;
2749
    if (rpl < cpl)
2750
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2751
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2752
    if (e2 & DESC_C_MASK) {
2753
        if (dpl > rpl)
2754
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2755
    } else {
2756
        if (dpl != rpl)
2757
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2758
    }
2759
    if (!(e2 & DESC_P_MASK))
2760
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2761

    
2762
    sp += addend;
2763
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2764
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2765
        /* return to same privilege level */
2766
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2767
                       get_seg_base(e1, e2),
2768
                       get_seg_limit(e1, e2),
2769
                       e2);
2770
    } else {
2771
        /* return to different privilege level */
2772
#ifdef TARGET_X86_64
2773
        if (shift == 2) {
2774
            POPQ(sp, new_esp);
2775
            POPQ(sp, new_ss);
2776
            new_ss &= 0xffff;
2777
        } else
2778
#endif
2779
        if (shift == 1) {
2780
            /* 32 bits */
2781
            POPL(ssp, sp, sp_mask, new_esp);
2782
            POPL(ssp, sp, sp_mask, new_ss);
2783
            new_ss &= 0xffff;
2784
        } else {
2785
            /* 16 bits */
2786
            POPW(ssp, sp, sp_mask, new_esp);
2787
            POPW(ssp, sp, sp_mask, new_ss);
2788
        }
2789
#ifdef DEBUG_PCALL
2790
        if (loglevel & CPU_LOG_PCALL) {
2791
            fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
2792
                    new_ss, new_esp);
2793
        }
2794
#endif
2795
        if ((new_ss & 0xfffc) == 0) {
2796
#ifdef TARGET_X86_64
2797
            /* NULL ss is allowed in long mode if cpl != 3*/
2798
            /* XXX: test CS64 ? */
2799
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2800
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2801
                                       0, 0xffffffff,
2802
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2803
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2804
                                       DESC_W_MASK | DESC_A_MASK);
2805
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2806
            } else
2807
#endif
2808
            {
2809
                raise_exception_err(EXCP0D_GPF, 0);
2810
            }
2811
        } else {
2812
            if ((new_ss & 3) != rpl)
2813
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2814
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2815
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2816
            if (!(ss_e2 & DESC_S_MASK) ||
2817
                (ss_e2 & DESC_CS_MASK) ||
2818
                !(ss_e2 & DESC_W_MASK))
2819
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2820
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2821
            if (dpl != rpl)
2822
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2823
            if (!(ss_e2 & DESC_P_MASK))
2824
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2825
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2826
                                   get_seg_base(ss_e1, ss_e2),
2827
                                   get_seg_limit(ss_e1, ss_e2),
2828
                                   ss_e2);
2829
        }
2830

    
2831
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2832
                       get_seg_base(e1, e2),
2833
                       get_seg_limit(e1, e2),
2834
                       e2);
2835
        cpu_x86_set_cpl(env, rpl);
2836
        sp = new_esp;
2837
#ifdef TARGET_X86_64
2838
        if (env->hflags & HF_CS64_MASK)
2839
            sp_mask = -1;
2840
        else
2841
#endif
2842
            sp_mask = get_sp_mask(ss_e2);
2843

    
2844
        /* validate data segments */
2845
        validate_seg(R_ES, rpl);
2846
        validate_seg(R_DS, rpl);
2847
        validate_seg(R_FS, rpl);
2848
        validate_seg(R_GS, rpl);
2849

    
2850
        sp += addend;
2851
    }
2852
    SET_ESP(sp, sp_mask);
2853
    env->eip = new_eip;
2854
    if (is_iret) {
2855
        /* NOTE: 'cpl' is the _old_ CPL */
2856
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2857
        if (cpl == 0)
2858
            eflags_mask |= IOPL_MASK;
2859
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2860
        if (cpl <= iopl)
2861
            eflags_mask |= IF_MASK;
2862
        if (shift == 0)
2863
            eflags_mask &= 0xffff;
2864
        load_eflags(new_eflags, eflags_mask);
2865
    }
2866
    return;
2867

    
2868
 return_to_vm86:
2869
    POPL(ssp, sp, sp_mask, new_esp);
2870
    POPL(ssp, sp, sp_mask, new_ss);
2871
    POPL(ssp, sp, sp_mask, new_es);
2872
    POPL(ssp, sp, sp_mask, new_ds);
2873
    POPL(ssp, sp, sp_mask, new_fs);
2874
    POPL(ssp, sp, sp_mask, new_gs);
2875

    
2876
    /* modify processor state */
2877
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2878
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2879
    load_seg_vm(R_CS, new_cs & 0xffff);
2880
    cpu_x86_set_cpl(env, 3);
2881
    load_seg_vm(R_SS, new_ss & 0xffff);
2882
    load_seg_vm(R_ES, new_es & 0xffff);
2883
    load_seg_vm(R_DS, new_ds & 0xffff);
2884
    load_seg_vm(R_FS, new_fs & 0xffff);
2885
    load_seg_vm(R_GS, new_gs & 0xffff);
2886

    
2887
    env->eip = new_eip & 0xffff;
2888
    ESP = new_esp;
2889
}
2890

    
2891
void helper_iret_protected(int shift, int next_eip)
2892
{
2893
    int tss_selector, type;
2894
    uint32_t e1, e2;
2895

    
2896
    /* specific case for TSS */
2897
    if (env->eflags & NT_MASK) {
2898
#ifdef TARGET_X86_64
2899
        if (env->hflags & HF_LMA_MASK)
2900
            raise_exception_err(EXCP0D_GPF, 0);
2901
#endif
2902
        tss_selector = lduw_kernel(env->tr.base + 0);
2903
        if (tss_selector & 4)
2904
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2905
        if (load_segment(&e1, &e2, tss_selector) != 0)
2906
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2907
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2908
        /* NOTE: we check both segment and busy TSS */
2909
        if (type != 3)
2910
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2911
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2912
    } else {
2913
        helper_ret_protected(shift, 1, 0);
2914
    }
2915
    env->hflags2 &= ~HF2_NMI_MASK;
2916
#ifdef USE_KQEMU
2917
    if (kqemu_is_ok(env)) {
2918
        CC_OP = CC_OP_EFLAGS;
2919
        env->exception_index = -1;
2920
        cpu_loop_exit();
2921
    }
2922
#endif
2923
}
2924

    
2925
void helper_lret_protected(int shift, int addend)
2926
{
2927
    helper_ret_protected(shift, 0, addend);
2928
#ifdef USE_KQEMU
2929
    if (kqemu_is_ok(env)) {
2930
        env->exception_index = -1;
2931
        cpu_loop_exit();
2932
    }
2933
#endif
2934
}
2935

    
2936
void helper_sysenter(void)
2937
{
2938
    if (env->sysenter_cs == 0) {
2939
        raise_exception_err(EXCP0D_GPF, 0);
2940
    }
2941
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2942
    cpu_x86_set_cpl(env, 0);
2943

    
2944
#ifdef TARGET_X86_64
2945
    if (env->hflags & HF_LMA_MASK) {
2946
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2947
                               0, 0xffffffff,
2948
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2949
                               DESC_S_MASK |
2950
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2951
    } else
2952
#endif
2953
    {
2954
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2955
                               0, 0xffffffff,
2956
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2957
                               DESC_S_MASK |
2958
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2959
    }
2960
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2961
                           0, 0xffffffff,
2962
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2963
                           DESC_S_MASK |
2964
                           DESC_W_MASK | DESC_A_MASK);
2965
    ESP = env->sysenter_esp;
2966
    EIP = env->sysenter_eip;
2967
}
2968

    
2969
void helper_sysexit(int dflag)
2970
{
2971
    int cpl;
2972

    
2973
    cpl = env->hflags & HF_CPL_MASK;
2974
    if (env->sysenter_cs == 0 || cpl != 0) {
2975
        raise_exception_err(EXCP0D_GPF, 0);
2976
    }
2977
    cpu_x86_set_cpl(env, 3);
2978
#ifdef TARGET_X86_64
2979
    if (dflag == 2) {
2980
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3,
2981
                               0, 0xffffffff,
2982
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2983
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2984
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2985
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3,
2986
                               0, 0xffffffff,
2987
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2988
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2989
                               DESC_W_MASK | DESC_A_MASK);
2990
    } else
2991
#endif
2992
    {
2993
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2994
                               0, 0xffffffff,
2995
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2996
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2997
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2998
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2999
                               0, 0xffffffff,
3000
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3001
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3002
                               DESC_W_MASK | DESC_A_MASK);
3003
    }
3004
    ESP = ECX;
3005
    EIP = EDX;
3006
#ifdef USE_KQEMU
3007
    if (kqemu_is_ok(env)) {
3008
        env->exception_index = -1;
3009
        cpu_loop_exit();
3010
    }
3011
#endif
3012
}
3013

    
3014
#if defined(CONFIG_USER_ONLY)
3015
target_ulong helper_read_crN(int reg)
3016
{
3017
    return 0;
3018
}
3019

    
3020
void helper_write_crN(int reg, target_ulong t0)
3021
{
3022
}
3023
#else
3024
target_ulong helper_read_crN(int reg)
3025
{
3026
    target_ulong val;
3027

    
3028
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
3029
    switch(reg) {
3030
    default:
3031
        val = env->cr[reg];
3032
        break;
3033
    case 8:
3034
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
3035
            val = cpu_get_apic_tpr(env);
3036
        } else {
3037
            val = env->v_tpr;
3038
        }
3039
        break;
3040
    }
3041
    return val;
3042
}
3043

    
3044
void helper_write_crN(int reg, target_ulong t0)
3045
{
3046
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
3047
    switch(reg) {
3048
    case 0:
3049
        cpu_x86_update_cr0(env, t0);
3050
        break;
3051
    case 3:
3052
        cpu_x86_update_cr3(env, t0);
3053
        break;
3054
    case 4:
3055
        cpu_x86_update_cr4(env, t0);
3056
        break;
3057
    case 8:
3058
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
3059
            cpu_set_apic_tpr(env, t0);
3060
        }
3061
        env->v_tpr = t0 & 0x0f;
3062
        break;
3063
    default:
3064
        env->cr[reg] = t0;
3065
        break;
3066
    }
3067
}
3068
#endif
3069

    
3070
void helper_lmsw(target_ulong t0)
3071
{
3072
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
3073
       if already set to one. */
3074
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
3075
    helper_write_crN(0, t0);
3076
}
3077

    
3078
void helper_clts(void)
3079
{
3080
    env->cr[0] &= ~CR0_TS_MASK;
3081
    env->hflags &= ~HF_TS_MASK;
3082
}
3083

    
3084
/* XXX: do more */
3085
void helper_movl_drN_T0(int reg, target_ulong t0)
3086
{
3087
    env->dr[reg] = t0;
3088
}
3089

    
3090
void helper_invlpg(target_ulong addr)
3091
{
3092
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
3093
    tlb_flush_page(env, addr);
3094
}
3095

    
3096
void helper_rdtsc(void)
3097
{
3098
    uint64_t val;
3099

    
3100
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3101
        raise_exception(EXCP0D_GPF);
3102
    }
3103
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
3104

    
3105
    val = cpu_get_tsc(env) + env->tsc_offset;
3106
    EAX = (uint32_t)(val);
3107
    EDX = (uint32_t)(val >> 32);
3108
}
3109

    
3110
void helper_rdpmc(void)
3111
{
3112
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3113
        raise_exception(EXCP0D_GPF);
3114
    }
3115
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3116
    
3117
    /* currently unimplemented */
3118
    raise_exception_err(EXCP06_ILLOP, 0);
3119
}
3120

    
3121
#if defined(CONFIG_USER_ONLY)
3122
void helper_wrmsr(void)
3123
{
3124
}
3125

    
3126
void helper_rdmsr(void)
3127
{
3128
}
3129
#else
3130
void helper_wrmsr(void)
3131
{
3132
    uint64_t val;
3133

    
3134
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3135

    
3136
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3137

    
3138
    switch((uint32_t)ECX) {
3139
    case MSR_IA32_SYSENTER_CS:
3140
        env->sysenter_cs = val & 0xffff;
3141
        break;
3142
    case MSR_IA32_SYSENTER_ESP:
3143
        env->sysenter_esp = val;
3144
        break;
3145
    case MSR_IA32_SYSENTER_EIP:
3146
        env->sysenter_eip = val;
3147
        break;
3148
    case MSR_IA32_APICBASE:
3149
        cpu_set_apic_base(env, val);
3150
        break;
3151
    case MSR_EFER:
3152
        {
3153
            uint64_t update_mask;
3154
            update_mask = 0;
3155
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3156
                update_mask |= MSR_EFER_SCE;
3157
            if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3158
                update_mask |= MSR_EFER_LME;
3159
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3160
                update_mask |= MSR_EFER_FFXSR;
3161
            if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3162
                update_mask |= MSR_EFER_NXE;
3163
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3164
                update_mask |= MSR_EFER_SVME;
3165
            cpu_load_efer(env, (env->efer & ~update_mask) |
3166
                          (val & update_mask));
3167
        }
3168
        break;
3169
    case MSR_STAR:
3170
        env->star = val;
3171
        break;
3172
    case MSR_PAT:
3173
        env->pat = val;
3174
        break;
3175
    case MSR_VM_HSAVE_PA:
3176
        env->vm_hsave = val;
3177
        break;
3178
#ifdef TARGET_X86_64
3179
    case MSR_LSTAR:
3180
        env->lstar = val;
3181
        break;
3182
    case MSR_CSTAR:
3183
        env->cstar = val;
3184
        break;
3185
    case MSR_FMASK:
3186
        env->fmask = val;
3187
        break;
3188
    case MSR_FSBASE:
3189
        env->segs[R_FS].base = val;
3190
        break;
3191
    case MSR_GSBASE:
3192
        env->segs[R_GS].base = val;
3193
        break;
3194
    case MSR_KERNELGSBASE:
3195
        env->kernelgsbase = val;
3196
        break;
3197
#endif
3198
    default:
3199
        /* XXX: exception ? */
3200
        break;
3201
    }
3202
}
3203

    
3204
void helper_rdmsr(void)
3205
{
3206
    uint64_t val;
3207

    
3208
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3209

    
3210
    switch((uint32_t)ECX) {
3211
    case MSR_IA32_SYSENTER_CS:
3212
        val = env->sysenter_cs;
3213
        break;
3214
    case MSR_IA32_SYSENTER_ESP:
3215
        val = env->sysenter_esp;
3216
        break;
3217
    case MSR_IA32_SYSENTER_EIP:
3218
        val = env->sysenter_eip;
3219
        break;
3220
    case MSR_IA32_APICBASE:
3221
        val = cpu_get_apic_base(env);
3222
        break;
3223
    case MSR_EFER:
3224
        val = env->efer;
3225
        break;
3226
    case MSR_STAR:
3227
        val = env->star;
3228
        break;
3229
    case MSR_PAT:
3230
        val = env->pat;
3231
        break;
3232
    case MSR_VM_HSAVE_PA:
3233
        val = env->vm_hsave;
3234
        break;
3235
    case MSR_IA32_PERF_STATUS:
3236
        /* tsc_increment_by_tick */
3237
        val = 1000ULL;
3238
        /* CPU multiplier */
3239
        val |= (((uint64_t)4ULL) << 40);
3240
        break;
3241
#ifdef TARGET_X86_64
3242
    case MSR_LSTAR:
3243
        val = env->lstar;
3244
        break;
3245
    case MSR_CSTAR:
3246
        val = env->cstar;
3247
        break;
3248
    case MSR_FMASK:
3249
        val = env->fmask;
3250
        break;
3251
    case MSR_FSBASE:
3252
        val = env->segs[R_FS].base;
3253
        break;
3254
    case MSR_GSBASE:
3255
        val = env->segs[R_GS].base;
3256
        break;
3257
    case MSR_KERNELGSBASE:
3258
        val = env->kernelgsbase;
3259
        break;
3260
#endif
3261
#ifdef USE_KQEMU
3262
    case MSR_QPI_COMMBASE:
3263
        if (env->kqemu_enabled) {
3264
            val = kqemu_comm_base;
3265
        } else {
3266
            val = 0;
3267
        }
3268
        break;
3269
#endif
3270
    default:
3271
        /* XXX: exception ? */
3272
        val = 0;
3273
        break;
3274
    }
3275
    EAX = (uint32_t)(val);
3276
    EDX = (uint32_t)(val >> 32);
3277
}
3278
#endif
3279

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

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

    
3323
target_ulong helper_lar(target_ulong selector1)
3324
{
3325
    uint32_t e1, e2, eflags, selector;
3326
    int rpl, dpl, cpl, type;
3327

    
3328
    selector = selector1 & 0xffff;
3329
    eflags = cc_table[CC_OP].compute_all();
3330
    if ((selector & 0xfffc) == 0)
3331
        goto fail;
3332
    if (load_segment(&e1, &e2, selector) != 0)
3333
        goto fail;
3334
    rpl = selector & 3;
3335
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3336
    cpl = env->hflags & HF_CPL_MASK;
3337
    if (e2 & DESC_S_MASK) {
3338
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3339
            /* conforming */
3340
        } else {
3341
            if (dpl < cpl || dpl < rpl)
3342
                goto fail;
3343
        }
3344
    } else {
3345
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3346
        switch(type) {
3347
        case 1:
3348
        case 2:
3349
        case 3:
3350
        case 4:
3351
        case 5:
3352
        case 9:
3353
        case 11:
3354
        case 12:
3355
            break;
3356
        default:
3357
            goto fail;
3358
        }
3359
        if (dpl < cpl || dpl < rpl) {
3360
        fail:
3361
            CC_SRC = eflags & ~CC_Z;
3362
            return 0;
3363
        }
3364
    }
3365
    CC_SRC = eflags | CC_Z;
3366
    return e2 & 0x00f0ff00;
3367
}
3368

    
3369
void helper_verr(target_ulong selector1)
3370
{
3371
    uint32_t e1, e2, eflags, selector;
3372
    int rpl, dpl, cpl;
3373

    
3374
    selector = selector1 & 0xffff;
3375
    eflags = cc_table[CC_OP].compute_all();
3376
    if ((selector & 0xfffc) == 0)
3377
        goto fail;
3378
    if (load_segment(&e1, &e2, selector) != 0)
3379
        goto fail;
3380
    if (!(e2 & DESC_S_MASK))
3381
        goto fail;
3382
    rpl = selector & 3;
3383
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3384
    cpl = env->hflags & HF_CPL_MASK;
3385
    if (e2 & DESC_CS_MASK) {
3386
        if (!(e2 & DESC_R_MASK))
3387
            goto fail;
3388
        if (!(e2 & DESC_C_MASK)) {
3389
            if (dpl < cpl || dpl < rpl)
3390
                goto fail;
3391
        }
3392
    } else {
3393
        if (dpl < cpl || dpl < rpl) {
3394
        fail:
3395
            CC_SRC = eflags & ~CC_Z;
3396
            return;
3397
        }
3398
    }
3399
    CC_SRC = eflags | CC_Z;
3400
}
3401

    
3402
void helper_verw(target_ulong selector1)
3403
{
3404
    uint32_t e1, e2, eflags, selector;
3405
    int rpl, dpl, cpl;
3406

    
3407
    selector = selector1 & 0xffff;
3408
    eflags = cc_table[CC_OP].compute_all();
3409
    if ((selector & 0xfffc) == 0)
3410
        goto fail;
3411
    if (load_segment(&e1, &e2, selector) != 0)
3412
        goto fail;
3413
    if (!(e2 & DESC_S_MASK))
3414
        goto fail;
3415
    rpl = selector & 3;
3416
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3417
    cpl = env->hflags & HF_CPL_MASK;
3418
    if (e2 & DESC_CS_MASK) {
3419
        goto fail;
3420
    } else {
3421
        if (dpl < cpl || dpl < rpl)
3422
            goto fail;
3423
        if (!(e2 & DESC_W_MASK)) {
3424
        fail:
3425
            CC_SRC = eflags & ~CC_Z;
3426
            return;
3427
        }
3428
    }
3429
    CC_SRC = eflags | CC_Z;
3430
}
3431

    
3432
/* x87 FPU helpers */
3433

    
3434
static void fpu_set_exception(int mask)
3435
{
3436
    env->fpus |= mask;
3437
    if (env->fpus & (~env->fpuc & FPUC_EM))
3438
        env->fpus |= FPUS_SE | FPUS_B;
3439
}
3440

    
3441
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3442
{
3443
    if (b == 0.0)
3444
        fpu_set_exception(FPUS_ZE);
3445
    return a / b;
3446
}
3447

    
3448
void fpu_raise_exception(void)
3449
{
3450
    if (env->cr[0] & CR0_NE_MASK) {
3451
        raise_exception(EXCP10_COPR);
3452
    }
3453
#if !defined(CONFIG_USER_ONLY)
3454
    else {
3455
        cpu_set_ferr(env);
3456
    }
3457
#endif
3458
}
3459

    
3460
void helper_flds_FT0(uint32_t val)
3461
{
3462
    union {
3463
        float32 f;
3464
        uint32_t i;
3465
    } u;
3466
    u.i = val;
3467
    FT0 = float32_to_floatx(u.f, &env->fp_status);
3468
}
3469

    
3470
void helper_fldl_FT0(uint64_t val)
3471
{
3472
    union {
3473
        float64 f;
3474
        uint64_t i;
3475
    } u;
3476
    u.i = val;
3477
    FT0 = float64_to_floatx(u.f, &env->fp_status);
3478
}
3479

    
3480
void helper_fildl_FT0(int32_t val)
3481
{
3482
    FT0 = int32_to_floatx(val, &env->fp_status);
3483
}
3484

    
3485
void helper_flds_ST0(uint32_t val)
3486
{
3487
    int new_fpstt;
3488
    union {
3489
        float32 f;
3490
        uint32_t i;
3491
    } u;
3492
    new_fpstt = (env->fpstt - 1) & 7;
3493
    u.i = val;
3494
    env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3495
    env->fpstt = new_fpstt;
3496
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3497
}
3498

    
3499
void helper_fldl_ST0(uint64_t val)
3500
{
3501
    int new_fpstt;
3502
    union {
3503
        float64 f;
3504
        uint64_t i;
3505
    } u;
3506
    new_fpstt = (env->fpstt - 1) & 7;
3507
    u.i = val;
3508
    env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3509
    env->fpstt = new_fpstt;
3510
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3511
}
3512

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

    
3522
void helper_fildll_ST0(int64_t val)
3523
{
3524
    int new_fpstt;
3525
    new_fpstt = (env->fpstt - 1) & 7;
3526
    env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3527
    env->fpstt = new_fpstt;
3528
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3529
}
3530

    
3531
uint32_t helper_fsts_ST0(void)
3532
{
3533
    union {
3534
        float32 f;
3535
        uint32_t i;
3536
    } u;
3537
    u.f = floatx_to_float32(ST0, &env->fp_status);
3538
    return u.i;
3539
}
3540

    
3541
uint64_t helper_fstl_ST0(void)
3542
{
3543
    union {
3544
        float64 f;
3545
        uint64_t i;
3546
    } u;
3547
    u.f = floatx_to_float64(ST0, &env->fp_status);
3548
    return u.i;
3549
}
3550

    
3551
int32_t helper_fist_ST0(void)
3552
{
3553
    int32_t val;
3554
    val = floatx_to_int32(ST0, &env->fp_status);
3555
    if (val != (int16_t)val)
3556
        val = -32768;
3557
    return val;
3558
}
3559

    
3560
int32_t helper_fistl_ST0(void)
3561
{
3562
    int32_t val;
3563
    val = floatx_to_int32(ST0, &env->fp_status);
3564
    return val;
3565
}
3566

    
3567
int64_t helper_fistll_ST0(void)
3568
{
3569
    int64_t val;
3570
    val = floatx_to_int64(ST0, &env->fp_status);
3571
    return val;
3572
}
3573

    
3574
int32_t helper_fistt_ST0(void)
3575
{
3576
    int32_t val;
3577
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3578
    if (val != (int16_t)val)
3579
        val = -32768;
3580
    return val;
3581
}
3582

    
3583
int32_t helper_fisttl_ST0(void)
3584
{
3585
    int32_t val;
3586
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3587
    return val;
3588
}
3589

    
3590
int64_t helper_fisttll_ST0(void)
3591
{
3592
    int64_t val;
3593
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3594
    return val;
3595
}
3596

    
3597
void helper_fldt_ST0(target_ulong ptr)
3598
{
3599
    int new_fpstt;
3600
    new_fpstt = (env->fpstt - 1) & 7;
3601
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3602
    env->fpstt = new_fpstt;
3603
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3604
}
3605

    
3606
void helper_fstt_ST0(target_ulong ptr)
3607
{
3608
    helper_fstt(ST0, ptr);
3609
}
3610

    
3611
void helper_fpush(void)
3612
{
3613
    fpush();
3614
}
3615

    
3616
void helper_fpop(void)
3617
{
3618
    fpop();
3619
}
3620

    
3621
void helper_fdecstp(void)
3622
{
3623
    env->fpstt = (env->fpstt - 1) & 7;
3624
    env->fpus &= (~0x4700);
3625
}
3626

    
3627
void helper_fincstp(void)
3628
{
3629
    env->fpstt = (env->fpstt + 1) & 7;
3630
    env->fpus &= (~0x4700);
3631
}
3632

    
3633
/* FPU move */
3634

    
3635
void helper_ffree_STN(int st_index)
3636
{
3637
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3638
}
3639

    
3640
void helper_fmov_ST0_FT0(void)
3641
{
3642
    ST0 = FT0;
3643
}
3644

    
3645
void helper_fmov_FT0_STN(int st_index)
3646
{
3647
    FT0 = ST(st_index);
3648
}
3649

    
3650
void helper_fmov_ST0_STN(int st_index)
3651
{
3652
    ST0 = ST(st_index);
3653
}
3654

    
3655
void helper_fmov_STN_ST0(int st_index)
3656
{
3657
    ST(st_index) = ST0;
3658
}
3659

    
3660
void helper_fxchg_ST0_STN(int st_index)
3661
{
3662
    CPU86_LDouble tmp;
3663
    tmp = ST(st_index);
3664
    ST(st_index) = ST0;
3665
    ST0 = tmp;
3666
}
3667

    
3668
/* FPU operations */
3669

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

    
3672
void helper_fcom_ST0_FT0(void)
3673
{
3674
    int ret;
3675

    
3676
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3677
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3678
    FORCE_RET();
3679
}
3680

    
3681
void helper_fucom_ST0_FT0(void)
3682
{
3683
    int ret;
3684

    
3685
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3686
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3687
    FORCE_RET();
3688
}
3689

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

    
3692
void helper_fcomi_ST0_FT0(void)
3693
{
3694
    int eflags;
3695
    int ret;
3696

    
3697
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3698
    eflags = cc_table[CC_OP].compute_all();
3699
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3700
    CC_SRC = eflags;
3701
    FORCE_RET();
3702
}
3703

    
3704
void helper_fucomi_ST0_FT0(void)
3705
{
3706
    int eflags;
3707
    int ret;
3708

    
3709
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3710
    eflags = cc_table[CC_OP].compute_all();
3711
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3712
    CC_SRC = eflags;
3713
    FORCE_RET();
3714
}
3715

    
3716
void helper_fadd_ST0_FT0(void)
3717
{
3718
    ST0 += FT0;
3719
}
3720

    
3721
void helper_fmul_ST0_FT0(void)
3722
{
3723
    ST0 *= FT0;
3724
}
3725

    
3726
void helper_fsub_ST0_FT0(void)
3727
{
3728
    ST0 -= FT0;
3729
}
3730

    
3731
void helper_fsubr_ST0_FT0(void)
3732
{
3733
    ST0 = FT0 - ST0;
3734
}
3735

    
3736
void helper_fdiv_ST0_FT0(void)
3737
{
3738
    ST0 = helper_fdiv(ST0, FT0);
3739
}
3740

    
3741
void helper_fdivr_ST0_FT0(void)
3742
{
3743
    ST0 = helper_fdiv(FT0, ST0);
3744
}
3745

    
3746
/* fp operations between STN and ST0 */
3747

    
3748
void helper_fadd_STN_ST0(int st_index)
3749
{
3750
    ST(st_index) += ST0;
3751
}
3752

    
3753
void helper_fmul_STN_ST0(int st_index)
3754
{
3755
    ST(st_index) *= ST0;
3756
}
3757

    
3758
void helper_fsub_STN_ST0(int st_index)
3759
{
3760
    ST(st_index) -= ST0;
3761
}
3762

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

    
3770
void helper_fdiv_STN_ST0(int st_index)
3771
{
3772
    CPU86_LDouble *p;
3773
    p = &ST(st_index);
3774
    *p = helper_fdiv(*p, ST0);
3775
}
3776

    
3777
void helper_fdivr_STN_ST0(int st_index)
3778
{
3779
    CPU86_LDouble *p;
3780
    p = &ST(st_index);
3781
    *p = helper_fdiv(ST0, *p);
3782
}
3783

    
3784
/* misc FPU operations */
3785
void helper_fchs_ST0(void)
3786
{
3787
    ST0 = floatx_chs(ST0);
3788
}
3789

    
3790
void helper_fabs_ST0(void)
3791
{
3792
    ST0 = floatx_abs(ST0);
3793
}
3794

    
3795
void helper_fld1_ST0(void)
3796
{
3797
    ST0 = f15rk[1];
3798
}
3799

    
3800
void helper_fldl2t_ST0(void)
3801
{
3802
    ST0 = f15rk[6];
3803
}
3804

    
3805
void helper_fldl2e_ST0(void)
3806
{
3807
    ST0 = f15rk[5];
3808
}
3809

    
3810
void helper_fldpi_ST0(void)
3811
{
3812
    ST0 = f15rk[2];
3813
}
3814

    
3815
void helper_fldlg2_ST0(void)
3816
{
3817
    ST0 = f15rk[3];
3818
}
3819

    
3820
void helper_fldln2_ST0(void)
3821
{
3822
    ST0 = f15rk[4];
3823
}
3824

    
3825
void helper_fldz_ST0(void)
3826
{
3827
    ST0 = f15rk[0];
3828
}
3829

    
3830
void helper_fldz_FT0(void)
3831
{
3832
    FT0 = f15rk[0];
3833
}
3834

    
3835
uint32_t helper_fnstsw(void)
3836
{
3837
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3838
}
3839

    
3840
uint32_t helper_fnstcw(void)
3841
{
3842
    return env->fpuc;
3843
}
3844

    
3845
static void update_fp_status(void)
3846
{
3847
    int rnd_type;
3848

    
3849
    /* set rounding mode */
3850
    switch(env->fpuc & RC_MASK) {
3851
    default:
3852
    case RC_NEAR:
3853
        rnd_type = float_round_nearest_even;
3854
        break;
3855
    case RC_DOWN:
3856
        rnd_type = float_round_down;
3857
        break;
3858
    case RC_UP:
3859
        rnd_type = float_round_up;
3860
        break;
3861
    case RC_CHOP:
3862
        rnd_type = float_round_to_zero;
3863
        break;
3864
    }
3865
    set_float_rounding_mode(rnd_type, &env->fp_status);
3866
#ifdef FLOATX80
3867
    switch((env->fpuc >> 8) & 3) {
3868
    case 0:
3869
        rnd_type = 32;
3870
        break;
3871
    case 2:
3872
        rnd_type = 64;
3873
        break;
3874
    case 3:
3875
    default:
3876
        rnd_type = 80;
3877
        break;
3878
    }
3879
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3880
#endif
3881
}
3882

    
3883
void helper_fldcw(uint32_t val)
3884
{
3885
    env->fpuc = val;
3886
    update_fp_status();
3887
}
3888

    
3889
void helper_fclex(void)
3890
{
3891
    env->fpus &= 0x7f00;
3892
}
3893

    
3894
void helper_fwait(void)
3895
{
3896
    if (env->fpus & FPUS_SE)
3897
        fpu_raise_exception();
3898
    FORCE_RET();
3899
}
3900

    
3901
void helper_fninit(void)
3902
{
3903
    env->fpus = 0;
3904
    env->fpstt = 0;
3905
    env->fpuc = 0x37f;
3906
    env->fptags[0] = 1;
3907
    env->fptags[1] = 1;
3908
    env->fptags[2] = 1;
3909
    env->fptags[3] = 1;
3910
    env->fptags[4] = 1;
3911
    env->fptags[5] = 1;
3912
    env->fptags[6] = 1;
3913
    env->fptags[7] = 1;
3914
}
3915

    
3916
/* BCD ops */
3917

    
3918
void helper_fbld_ST0(target_ulong ptr)
3919
{
3920
    CPU86_LDouble tmp;
3921
    uint64_t val;
3922
    unsigned int v;
3923
    int i;
3924

    
3925
    val = 0;
3926
    for(i = 8; i >= 0; i--) {
3927
        v = ldub(ptr + i);
3928
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3929
    }
3930
    tmp = val;
3931
    if (ldub(ptr + 9) & 0x80)
3932
        tmp = -tmp;
3933
    fpush();
3934
    ST0 = tmp;
3935
}
3936

    
3937
void helper_fbst_ST0(target_ulong ptr)
3938
{
3939
    int v;
3940
    target_ulong mem_ref, mem_end;
3941
    int64_t val;
3942

    
3943
    val = floatx_to_int64(ST0, &env->fp_status);
3944
    mem_ref = ptr;
3945
    mem_end = mem_ref + 9;
3946
    if (val < 0) {
3947
        stb(mem_end, 0x80);
3948
        val = -val;
3949
    } else {
3950
        stb(mem_end, 0x00);
3951
    }
3952
    while (mem_ref < mem_end) {
3953
        if (val == 0)
3954
            break;
3955
        v = val % 100;
3956
        val = val / 100;
3957
        v = ((v / 10) << 4) | (v % 10);
3958
        stb(mem_ref++, v);
3959
    }
3960
    while (mem_ref < mem_end) {
3961
        stb(mem_ref++, 0);
3962
    }
3963
}
3964

    
3965
void helper_f2xm1(void)
3966
{
3967
    ST0 = pow(2.0,ST0) - 1.0;
3968
}
3969

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

    
3974
    fptemp = ST0;
3975
    if (fptemp>0.0){
3976
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
3977
        ST1 *= fptemp;
3978
        fpop();
3979
    } else {
3980
        env->fpus &= (~0x4700);
3981
        env->fpus |= 0x400;
3982
    }
3983
}
3984

    
3985
void helper_fptan(void)
3986
{
3987
    CPU86_LDouble fptemp;
3988

    
3989
    fptemp = ST0;
3990
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3991
        env->fpus |= 0x400;
3992
    } else {
3993
        ST0 = tan(fptemp);
3994
        fpush();
3995
        ST0 = 1.0;
3996
        env->fpus &= (~0x400);  /* C2 <-- 0 */
3997
        /* the above code is for  |arg| < 2**52 only */
3998
    }
3999
}
4000

    
4001
void helper_fpatan(void)
4002
{
4003
    CPU86_LDouble fptemp, fpsrcop;
4004

    
4005
    fpsrcop = ST1;
4006
    fptemp = ST0;
4007
    ST1 = atan2(fpsrcop,fptemp);
4008
    fpop();
4009
}
4010

    
4011
void helper_fxtract(void)
4012
{
4013
    CPU86_LDoubleU temp;
4014
    unsigned int expdif;
4015

    
4016
    temp.d = ST0;
4017
    expdif = EXPD(temp) - EXPBIAS;
4018
    /*DP exponent bias*/
4019
    ST0 = expdif;
4020
    fpush();
4021
    BIASEXPONENT(temp);
4022
    ST0 = temp.d;
4023
}
4024

    
4025
void helper_fprem1(void)
4026
{
4027
    CPU86_LDouble dblq, fpsrcop, fptemp;
4028
    CPU86_LDoubleU fpsrcop1, fptemp1;
4029
    int expdif;
4030
    signed long long int q;
4031

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

    
4038
    fpsrcop = ST0;
4039
    fptemp = ST1;
4040
    fpsrcop1.d = fpsrcop;
4041
    fptemp1.d = fptemp;
4042
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4043

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

    
4051
    if (expdif < 53) {
4052
        dblq = fpsrcop / fptemp;
4053
        /* round dblq towards nearest integer */
4054
        dblq = rint(dblq);
4055
        ST0 = fpsrcop - fptemp * dblq;
4056

    
4057
        /* convert dblq to q by truncating towards zero */
4058
        if (dblq < 0.0)
4059
           q = (signed long long int)(-dblq);
4060
        else
4061
           q = (signed long long int)dblq;
4062

    
4063
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4064
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4065
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4066
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4067
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4068
    } else {
4069
        env->fpus |= 0x400;  /* C2 <-- 1 */
4070
        fptemp = pow(2.0, expdif - 50);
4071
        fpsrcop = (ST0 / ST1) / fptemp;
4072
        /* fpsrcop = integer obtained by chopping */
4073
        fpsrcop = (fpsrcop < 0.0) ?
4074
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4075
        ST0 -= (ST1 * fpsrcop * fptemp);
4076
    }
4077
}
4078

    
4079
void helper_fprem(void)
4080
{
4081
    CPU86_LDouble dblq, fpsrcop, fptemp;
4082
    CPU86_LDoubleU fpsrcop1, fptemp1;
4083
    int expdif;
4084
    signed long long int q;
4085

    
4086
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
4087
       ST0 = 0.0 / 0.0; /* NaN */
4088
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4089
       return;
4090
    }
4091

    
4092
    fpsrcop = (CPU86_LDouble)ST0;
4093
    fptemp = (CPU86_LDouble)ST1;
4094
    fpsrcop1.d = fpsrcop;
4095
    fptemp1.d = fptemp;
4096
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4097

    
4098
    if (expdif < 0) {
4099
        /* optimisation? taken from the AMD docs */
4100
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4101
        /* ST0 is unchanged */
4102
        return;
4103
    }
4104

    
4105
    if ( expdif < 53 ) {
4106
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4107
        /* round dblq towards zero */
4108
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4109
        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
4110

    
4111
        /* convert dblq to q by truncating towards zero */
4112
        if (dblq < 0.0)
4113
           q = (signed long long int)(-dblq);
4114
        else
4115
           q = (signed long long int)dblq;
4116

    
4117
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4118
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4119
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4120
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4121
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4122
    } else {
4123
        int N = 32 + (expdif % 32); /* as per AMD docs */
4124
        env->fpus |= 0x400;  /* C2 <-- 1 */
4125
        fptemp = pow(2.0, (double)(expdif - N));
4126
        fpsrcop = (ST0 / ST1) / fptemp;
4127
        /* fpsrcop = integer obtained by chopping */
4128
        fpsrcop = (fpsrcop < 0.0) ?
4129
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4130
        ST0 -= (ST1 * fpsrcop * fptemp);
4131
    }
4132
}
4133

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

    
4138
    fptemp = ST0;
4139
    if ((fptemp+1.0)>0.0) {
4140
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4141
        ST1 *= fptemp;
4142
        fpop();
4143
    } else {
4144
        env->fpus &= (~0x4700);
4145
        env->fpus |= 0x400;
4146
    }
4147
}
4148

    
4149
void helper_fsqrt(void)
4150
{
4151
    CPU86_LDouble fptemp;
4152

    
4153
    fptemp = ST0;
4154
    if (fptemp<0.0) {
4155
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4156
        env->fpus |= 0x400;
4157
    }
4158
    ST0 = sqrt(fptemp);
4159
}
4160

    
4161
void helper_fsincos(void)
4162
{
4163
    CPU86_LDouble fptemp;
4164

    
4165
    fptemp = ST0;
4166
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4167
        env->fpus |= 0x400;
4168
    } else {
4169
        ST0 = sin(fptemp);
4170
        fpush();
4171
        ST0 = cos(fptemp);
4172
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4173
        /* the above code is for  |arg| < 2**63 only */
4174
    }
4175
}
4176

    
4177
void helper_frndint(void)
4178
{
4179
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4180
}
4181

    
4182
void helper_fscale(void)
4183
{
4184
    ST0 = ldexp (ST0, (int)(ST1));
4185
}
4186

    
4187
void helper_fsin(void)
4188
{
4189
    CPU86_LDouble fptemp;
4190

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

    
4201
void helper_fcos(void)
4202
{
4203
    CPU86_LDouble fptemp;
4204

    
4205
    fptemp = ST0;
4206
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4207
        env->fpus |= 0x400;
4208
    } else {
4209
        ST0 = cos(fptemp);
4210
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4211
        /* the above code is for  |arg5 < 2**63 only */
4212
    }
4213
}
4214

    
4215
void helper_fxam_ST0(void)
4216
{
4217
    CPU86_LDoubleU temp;
4218
    int expdif;
4219

    
4220
    temp.d = ST0;
4221

    
4222
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4223
    if (SIGND(temp))
4224
        env->fpus |= 0x200; /* C1 <-- 1 */
4225

    
4226
    /* XXX: test fptags too */
4227
    expdif = EXPD(temp);
4228
    if (expdif == MAXEXPD) {
4229
#ifdef USE_X86LDOUBLE
4230
        if (MANTD(temp) == 0x8000000000000000ULL)
4231
#else
4232
        if (MANTD(temp) == 0)
4233
#endif
4234
            env->fpus |=  0x500 /*Infinity*/;
4235
        else
4236
            env->fpus |=  0x100 /*NaN*/;
4237
    } else if (expdif == 0) {
4238
        if (MANTD(temp) == 0)
4239
            env->fpus |=  0x4000 /*Zero*/;
4240
        else
4241
            env->fpus |= 0x4400 /*Denormal*/;
4242
    } else {
4243
        env->fpus |= 0x400;
4244
    }
4245
}
4246

    
4247
void helper_fstenv(target_ulong ptr, int data32)
4248
{
4249
    int fpus, fptag, exp, i;
4250
    uint64_t mant;
4251
    CPU86_LDoubleU tmp;
4252

    
4253
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4254
    fptag = 0;
4255
    for (i=7; i>=0; i--) {
4256
        fptag <<= 2;
4257
        if (env->fptags[i]) {
4258
            fptag |= 3;
4259
        } else {
4260
            tmp.d = env->fpregs[i].d;
4261
            exp = EXPD(tmp);
4262
            mant = MANTD(tmp);
4263
            if (exp == 0 && mant == 0) {
4264
                /* zero */
4265
                fptag |= 1;
4266
            } else if (exp == 0 || exp == MAXEXPD
4267
#ifdef USE_X86LDOUBLE
4268
                       || (mant & (1LL << 63)) == 0
4269
#endif
4270
                       ) {
4271
                /* NaNs, infinity, denormal */
4272
                fptag |= 2;
4273
            }
4274
        }
4275
    }
4276
    if (data32) {
4277
        /* 32 bit */
4278
        stl(ptr, env->fpuc);
4279
        stl(ptr + 4, fpus);
4280
        stl(ptr + 8, fptag);
4281
        stl(ptr + 12, 0); /* fpip */
4282
        stl(ptr + 16, 0); /* fpcs */
4283
        stl(ptr + 20, 0); /* fpoo */
4284
        stl(ptr + 24, 0); /* fpos */
4285
    } else {
4286
        /* 16 bit */
4287
        stw(ptr, env->fpuc);
4288
        stw(ptr + 2, fpus);
4289
        stw(ptr + 4, fptag);
4290
        stw(ptr + 6, 0);
4291
        stw(ptr + 8, 0);
4292
        stw(ptr + 10, 0);
4293
        stw(ptr + 12, 0);
4294
    }
4295
}
4296

    
4297
void helper_fldenv(target_ulong ptr, int data32)
4298
{
4299
    int i, fpus, fptag;
4300

    
4301
    if (data32) {
4302
        env->fpuc = lduw(ptr);
4303
        fpus = lduw(ptr + 4);
4304
        fptag = lduw(ptr + 8);
4305
    }
4306
    else {
4307
        env->fpuc = lduw(ptr);
4308
        fpus = lduw(ptr + 2);
4309
        fptag = lduw(ptr + 4);
4310
    }
4311
    env->fpstt = (fpus >> 11) & 7;
4312
    env->fpus = fpus & ~0x3800;
4313
    for(i = 0;i < 8; i++) {
4314
        env->fptags[i] = ((fptag & 3) == 3);
4315
        fptag >>= 2;
4316
    }
4317
}
4318

    
4319
void helper_fsave(target_ulong ptr, int data32)
4320
{
4321
    CPU86_LDouble tmp;
4322
    int i;
4323

    
4324
    helper_fstenv(ptr, data32);
4325

    
4326
    ptr += (14 << data32);
4327
    for(i = 0;i < 8; i++) {
4328
        tmp = ST(i);
4329
        helper_fstt(tmp, ptr);
4330
        ptr += 10;
4331
    }
4332

    
4333
    /* fninit */
4334
    env->fpus = 0;
4335
    env->fpstt = 0;
4336
    env->fpuc = 0x37f;
4337
    env->fptags[0] = 1;
4338
    env->fptags[1] = 1;
4339
    env->fptags[2] = 1;
4340
    env->fptags[3] = 1;
4341
    env->fptags[4] = 1;
4342
    env->fptags[5] = 1;
4343
    env->fptags[6] = 1;
4344
    env->fptags[7] = 1;
4345
}
4346

    
4347
void helper_frstor(target_ulong ptr, int data32)
4348
{
4349
    CPU86_LDouble tmp;
4350
    int i;
4351

    
4352
    helper_fldenv(ptr, data32);
4353
    ptr += (14 << data32);
4354

    
4355
    for(i = 0;i < 8; i++) {
4356
        tmp = helper_fldt(ptr);
4357
        ST(i) = tmp;
4358
        ptr += 10;
4359
    }
4360
}
4361

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

    
4368
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4369
    fptag = 0;
4370
    for(i = 0; i < 8; i++) {
4371
        fptag |= (env->fptags[i] << i);
4372
    }
4373
    stw(ptr, env->fpuc);
4374
    stw(ptr + 2, fpus);
4375
    stw(ptr + 4, fptag ^ 0xff);
4376
#ifdef TARGET_X86_64
4377
    if (data64) {
4378
        stq(ptr + 0x08, 0); /* rip */
4379
        stq(ptr + 0x10, 0); /* rdp */
4380
    } else 
4381
#endif
4382
    {
4383
        stl(ptr + 0x08, 0); /* eip */
4384
        stl(ptr + 0x0c, 0); /* sel  */
4385
        stl(ptr + 0x10, 0); /* dp */
4386
        stl(ptr + 0x14, 0); /* sel  */
4387
    }
4388

    
4389
    addr = ptr + 0x20;
4390
    for(i = 0;i < 8; i++) {
4391
        tmp = ST(i);
4392
        helper_fstt(tmp, addr);
4393
        addr += 16;
4394
    }
4395

    
4396
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4397
        /* XXX: finish it */
4398
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4399
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4400
        if (env->hflags & HF_CS64_MASK)
4401
            nb_xmm_regs = 16;
4402
        else
4403
            nb_xmm_regs = 8;
4404
        addr = ptr + 0xa0;
4405
        for(i = 0; i < nb_xmm_regs; i++) {
4406
            stq(addr, env->xmm_regs[i].XMM_Q(0));
4407
            stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4408
            addr += 16;
4409
        }
4410
    }
4411
}
4412

    
4413
void helper_fxrstor(target_ulong ptr, int data64)
4414
{
4415
    int i, fpus, fptag, nb_xmm_regs;
4416
    CPU86_LDouble tmp;
4417
    target_ulong addr;
4418

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

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

    
4436
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4437
        /* XXX: finish it */
4438
        env->mxcsr = ldl(ptr + 0x18);
4439
        //ldl(ptr + 0x1c);
4440
        if (env->hflags & HF_CS64_MASK)
4441
            nb_xmm_regs = 16;
4442
        else
4443
            nb_xmm_regs = 8;
4444
        addr = ptr + 0xa0;
4445
        for(i = 0; i < nb_xmm_regs; i++) {
4446
            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4447
            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4448
            addr += 16;
4449
        }
4450
    }
4451
}
4452

    
4453
#ifndef USE_X86LDOUBLE
4454

    
4455
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4456
{
4457
    CPU86_LDoubleU temp;
4458
    int e;
4459

    
4460
    temp.d = f;
4461
    /* mantissa */
4462
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4463
    /* exponent + sign */
4464
    e = EXPD(temp) - EXPBIAS + 16383;
4465
    e |= SIGND(temp) >> 16;
4466
    *pexp = e;
4467
}
4468

    
4469
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4470
{
4471
    CPU86_LDoubleU temp;
4472
    int e;
4473
    uint64_t ll;
4474

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

    
4488
#else
4489

    
4490
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4491
{
4492
    CPU86_LDoubleU temp;
4493

    
4494
    temp.d = f;
4495
    *pmant = temp.l.lower;
4496
    *pexp = temp.l.upper;
4497
}
4498

    
4499
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4500
{
4501
    CPU86_LDoubleU temp;
4502

    
4503
    temp.l.upper = upper;
4504
    temp.l.lower = mant;
4505
    return temp.d;
4506
}
4507
#endif
4508

    
4509
#ifdef TARGET_X86_64
4510

    
4511
//#define DEBUG_MULDIV
4512

    
4513
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4514
{
4515
    *plow += a;
4516
    /* carry test */
4517
    if (*plow < a)
4518
        (*phigh)++;
4519
    *phigh += b;
4520
}
4521

    
4522
static void neg128(uint64_t *plow, uint64_t *phigh)
4523
{
4524
    *plow = ~ *plow;
4525
    *phigh = ~ *phigh;
4526
    add128(plow, phigh, 1, 0);
4527
}
4528

    
4529
/* return TRUE if overflow */
4530
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4531
{
4532
    uint64_t q, r, a1, a0;
4533
    int i, qb, ab;
4534

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

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

    
4592
void helper_mulq_EAX_T0(target_ulong t0)
4593
{
4594
    uint64_t r0, r1;
4595

    
4596
    mulu64(&r0, &r1, EAX, t0);
4597
    EAX = r0;
4598
    EDX = r1;
4599
    CC_DST = r0;
4600
    CC_SRC = r1;
4601
}
4602

    
4603
void helper_imulq_EAX_T0(target_ulong t0)
4604
{
4605
    uint64_t r0, r1;
4606

    
4607
    muls64(&r0, &r1, EAX, t0);
4608
    EAX = r0;
4609
    EDX = r1;
4610
    CC_DST = r0;
4611
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4612
}
4613

    
4614
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4615
{
4616
    uint64_t r0, r1;
4617

    
4618
    muls64(&r0, &r1, t0, t1);
4619
    CC_DST = r0;
4620
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4621
    return r0;
4622
}
4623

    
4624
void helper_divq_EAX(target_ulong t0)
4625
{
4626
    uint64_t r0, r1;
4627
    if (t0 == 0) {
4628
        raise_exception(EXCP00_DIVZ);
4629
    }
4630
    r0 = EAX;
4631
    r1 = EDX;
4632
    if (div64(&r0, &r1, t0))
4633
        raise_exception(EXCP00_DIVZ);
4634
    EAX = r0;
4635
    EDX = r1;
4636
}
4637

    
4638
void helper_idivq_EAX(target_ulong t0)
4639
{
4640
    uint64_t r0, r1;
4641
    if (t0 == 0) {
4642
        raise_exception(EXCP00_DIVZ);
4643
    }
4644
    r0 = EAX;
4645
    r1 = EDX;
4646
    if (idiv64(&r0, &r1, t0))
4647
        raise_exception(EXCP00_DIVZ);
4648
    EAX = r0;
4649
    EDX = r1;
4650
}
4651
#endif
4652

    
4653
static void do_hlt(void)
4654
{
4655
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4656
    env->halted = 1;
4657
    env->exception_index = EXCP_HLT;
4658
    cpu_loop_exit();
4659
}
4660

    
4661
void helper_hlt(int next_eip_addend)
4662
{
4663
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4664
    EIP += next_eip_addend;
4665
    
4666
    do_hlt();
4667
}
4668

    
4669
void helper_monitor(target_ulong ptr)
4670
{
4671
    if ((uint32_t)ECX != 0)
4672
        raise_exception(EXCP0D_GPF);
4673
    /* XXX: store address ? */
4674
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4675
}
4676

    
4677
void helper_mwait(int next_eip_addend)
4678
{
4679
    if ((uint32_t)ECX != 0)
4680
        raise_exception(EXCP0D_GPF);
4681
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4682
    EIP += next_eip_addend;
4683

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

    
4693
void helper_debug(void)
4694
{
4695
    env->exception_index = EXCP_DEBUG;
4696
    cpu_loop_exit();
4697
}
4698

    
4699
void helper_raise_interrupt(int intno, int next_eip_addend)
4700
{
4701
    raise_interrupt(intno, 1, 0, next_eip_addend);
4702
}
4703

    
4704
void helper_raise_exception(int exception_index)
4705
{
4706
    raise_exception(exception_index);
4707
}
4708

    
4709
void helper_cli(void)
4710
{
4711
    env->eflags &= ~IF_MASK;
4712
}
4713

    
4714
void helper_sti(void)
4715
{
4716
    env->eflags |= IF_MASK;
4717
}
4718

    
4719
#if 0
4720
/* vm86plus instructions */
4721
void helper_cli_vm(void)
4722
{
4723
    env->eflags &= ~VIF_MASK;
4724
}
4725

4726
void helper_sti_vm(void)
4727
{
4728
    env->eflags |= VIF_MASK;
4729
    if (env->eflags & VIP_MASK) {
4730
        raise_exception(EXCP0D_GPF);
4731
    }
4732
}
4733
#endif
4734

    
4735
void helper_set_inhibit_irq(void)
4736
{
4737
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4738
}
4739

    
4740
void helper_reset_inhibit_irq(void)
4741
{
4742
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4743
}
4744

    
4745
void helper_boundw(target_ulong a0, int v)
4746
{
4747
    int low, high;
4748
    low = ldsw(a0);
4749
    high = ldsw(a0 + 2);
4750
    v = (int16_t)v;
4751
    if (v < low || v > high) {
4752
        raise_exception(EXCP05_BOUND);
4753
    }
4754
    FORCE_RET();
4755
}
4756

    
4757
void helper_boundl(target_ulong a0, int v)
4758
{
4759
    int low, high;
4760
    low = ldl(a0);
4761
    high = ldl(a0 + 4);
4762
    if (v < low || v > high) {
4763
        raise_exception(EXCP05_BOUND);
4764
    }
4765
    FORCE_RET();
4766
}
4767

    
4768
static float approx_rsqrt(float a)
4769
{
4770
    return 1.0 / sqrt(a);
4771
}
4772

    
4773
static float approx_rcp(float a)
4774
{
4775
    return 1.0 / a;
4776
}
4777

    
4778
#if !defined(CONFIG_USER_ONLY)
4779

    
4780
#define MMUSUFFIX _mmu
4781

    
4782
#define SHIFT 0
4783
#include "softmmu_template.h"
4784

    
4785
#define SHIFT 1
4786
#include "softmmu_template.h"
4787

    
4788
#define SHIFT 2
4789
#include "softmmu_template.h"
4790

    
4791
#define SHIFT 3
4792
#include "softmmu_template.h"
4793

    
4794
#endif
4795

    
4796
/* try to fill the TLB and return an exception if error. If retaddr is
4797
   NULL, it means that the function was called in C code (i.e. not
4798
   from generated code or from helper.c) */
4799
/* XXX: fix it to restore all registers */
4800
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4801
{
4802
    TranslationBlock *tb;
4803
    int ret;
4804
    unsigned long pc;
4805
    CPUX86State *saved_env;
4806

    
4807
    /* XXX: hack to restore env in all cases, even if not called from
4808
       generated code */
4809
    saved_env = env;
4810
    env = cpu_single_env;
4811

    
4812
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4813
    if (ret) {
4814
        if (retaddr) {
4815
            /* now we have a real cpu fault */
4816
            pc = (unsigned long)retaddr;
4817
            tb = tb_find_pc(pc);
4818
            if (tb) {
4819
                /* the PC is inside the translated code. It means that we have
4820
                   a virtual CPU fault */
4821
                cpu_restore_state(tb, env, pc, NULL);
4822
            }
4823
        }
4824
        raise_exception_err(env->exception_index, env->error_code);
4825
    }
4826
    env = saved_env;
4827
}
4828

    
4829

    
4830
/* Secure Virtual Machine helpers */
4831

    
4832
#if defined(CONFIG_USER_ONLY)
4833

    
4834
void helper_vmrun(int aflag, int next_eip_addend)
4835
{ 
4836
}
4837
void helper_vmmcall(void) 
4838
{ 
4839
}
4840
void helper_vmload(int aflag)
4841
{ 
4842
}
4843
void helper_vmsave(int aflag)
4844
{ 
4845
}
4846
void helper_stgi(void)
4847
{
4848
}
4849
void helper_clgi(void)
4850
{
4851
}
4852
void helper_skinit(void) 
4853
{ 
4854
}
4855
void helper_invlpga(int aflag)
4856
{ 
4857
}
4858
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4859
{ 
4860
}
4861
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4862
{
4863
}
4864

    
4865
void helper_svm_check_io(uint32_t port, uint32_t param, 
4866
                         uint32_t next_eip_addend)
4867
{
4868
}
4869
#else
4870

    
4871
static inline void svm_save_seg(target_phys_addr_t addr,
4872
                                const SegmentCache *sc)
4873
{
4874
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4875
             sc->selector);
4876
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4877
             sc->base);
4878
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4879
             sc->limit);
4880
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4881
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4882
}
4883
                                
4884
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4885
{
4886
    unsigned int flags;
4887

    
4888
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4889
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4890
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4891
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4892
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4893
}
4894

    
4895
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4896
                                      CPUState *env, int seg_reg)
4897
{
4898
    SegmentCache sc1, *sc = &sc1;
4899
    svm_load_seg(addr, sc);
4900
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4901
                           sc->base, sc->limit, sc->flags);
4902
}
4903

    
4904
void helper_vmrun(int aflag, int next_eip_addend)
4905
{
4906
    target_ulong addr;
4907
    uint32_t event_inj;
4908
    uint32_t int_ctl;
4909

    
4910
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4911

    
4912
    if (aflag == 2)
4913
        addr = EAX;
4914
    else
4915
        addr = (uint32_t)EAX;
4916

    
4917
    if (loglevel & CPU_LOG_TB_IN_ASM)
4918
        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4919

    
4920
    env->vm_vmcb = addr;
4921

    
4922
    /* save the current CPU state in the hsave page */
4923
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4924
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4925

    
4926
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4927
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4928

    
4929
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4930
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4931
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4932
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4933
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4934
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4935

    
4936
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4937
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4938

    
4939
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4940
                  &env->segs[R_ES]);
4941
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4942
                 &env->segs[R_CS]);
4943
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4944
                 &env->segs[R_SS]);
4945
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4946
                 &env->segs[R_DS]);
4947

    
4948
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
4949
             EIP + next_eip_addend);
4950
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4951
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4952

    
4953
    /* load the interception bitmaps so we do not need to access the
4954
       vmcb in svm mode */
4955
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4956
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4957
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4958
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4959
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4960
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4961

    
4962
    /* enable intercepts */
4963
    env->hflags |= HF_SVMI_MASK;
4964

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

    
4967
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4968
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4969

    
4970
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4971
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4972

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

    
4976
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4977
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4978
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4979
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4980
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4981
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4982
    if (int_ctl & V_INTR_MASKING_MASK) {
4983
        env->v_tpr = int_ctl & V_TPR_MASK;
4984
        env->hflags2 |= HF2_VINTR_MASK;
4985
        if (env->eflags & IF_MASK)
4986
            env->hflags2 |= HF2_HIF_MASK;
4987
    }
4988

    
4989
    cpu_load_efer(env, 
4990
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4991
    env->eflags = 0;
4992
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4993
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4994
    CC_OP = CC_OP_EFLAGS;
4995

    
4996
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4997
                       env, R_ES);
4998
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4999
                       env, R_CS);
5000
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
5001
                       env, R_SS);
5002
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
5003
                       env, R_DS);
5004

    
5005
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
5006
    env->eip = EIP;
5007
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
5008
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
5009
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
5010
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
5011
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
5012

    
5013
    /* FIXME: guest state consistency checks */
5014

    
5015
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
5016
        case TLB_CONTROL_DO_NOTHING:
5017
            break;
5018
        case TLB_CONTROL_FLUSH_ALL_ASID:
5019
            /* FIXME: this is not 100% correct but should work for now */
5020
            tlb_flush(env, 1);
5021
        break;
5022
    }
5023

    
5024
    env->hflags2 |= HF2_GIF_MASK;
5025

    
5026
    if (int_ctl & V_IRQ_MASK) {
5027
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
5028
    }
5029

    
5030
    /* maybe we need to inject an event */
5031
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
5032
    if (event_inj & SVM_EVTINJ_VALID) {
5033
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
5034
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
5035
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
5036
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
5037

    
5038
        if (loglevel & CPU_LOG_TB_IN_ASM)
5039
            fprintf(logfile, "Injecting(%#hx): ", valid_err);
5040
        /* FIXME: need to implement valid_err */
5041
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
5042
        case SVM_EVTINJ_TYPE_INTR:
5043
                env->exception_index = vector;
5044
                env->error_code = event_inj_err;
5045
                env->exception_is_int = 0;
5046
                env->exception_next_eip = -1;
5047
                if (loglevel & CPU_LOG_TB_IN_ASM)
5048
                    fprintf(logfile, "INTR");
5049
                /* XXX: is it always correct ? */
5050
                do_interrupt(vector, 0, 0, 0, 1);
5051
                break;
5052
        case SVM_EVTINJ_TYPE_NMI:
5053
                env->exception_index = EXCP02_NMI;
5054
                env->error_code = event_inj_err;
5055
                env->exception_is_int = 0;
5056
                env->exception_next_eip = EIP;
5057
                if (loglevel & CPU_LOG_TB_IN_ASM)
5058
                    fprintf(logfile, "NMI");
5059
                cpu_loop_exit();
5060
                break;
5061
        case SVM_EVTINJ_TYPE_EXEPT:
5062
                env->exception_index = vector;