Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ eb38c52c

History | View | Annotate | Download (152.3 kB)

1
/*
2
 *  i386 helpers
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, 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
/* XXX: add a is_user flag to have proper security support */
594
#define PUSHW(ssp, sp, sp_mask, val)\
595
{\
596
    sp -= 2;\
597
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
598
}
599

    
600
#define PUSHL(ssp, sp, sp_mask, val)\
601
{\
602
    sp -= 4;\
603
    stl_kernel((ssp) + (sp & (sp_mask)), (val));\
604
}
605

    
606
#define POPW(ssp, sp, sp_mask, val)\
607
{\
608
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
609
    sp += 2;\
610
}
611

    
612
#define POPL(ssp, sp, sp_mask, val)\
613
{\
614
    val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
615
    sp += 4;\
616
}
617

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

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

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

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

    
750
    shift = type >> 3;
751

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

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

    
808
    selector = (selector & ~3) | dpl;
809
    cpu_x86_load_seg_cache(env, R_CS, selector,
810
                   get_seg_base(e1, e2),
811
                   get_seg_limit(e1, e2),
812
                   e2);
813
    cpu_x86_set_cpl(env, dpl);
814
    env->eip = offset;
815

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

    
823
#ifdef TARGET_X86_64
824

    
825
#define PUSHQ(sp, val)\
826
{\
827
    sp -= 8;\
828
    stq_kernel(sp, (val));\
829
}
830

    
831
#define POPQ(sp, val)\
832
{\
833
    val = ldq_kernel(sp);\
834
    sp += 8;\
835
}
836

    
837
static inline target_ulong get_rsp_from_tss(int level)
838
{
839
    int index;
840

    
841
#if 0
842
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
843
           env->tr.base, env->tr.limit);
844
#endif
845

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

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

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

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

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

    
952
    PUSHQ(esp, env->segs[R_SS].selector);
953
    PUSHQ(esp, ESP);
954
    PUSHQ(esp, compute_eflags());
955
    PUSHQ(esp, env->segs[R_CS].selector);
956
    PUSHQ(esp, old_eip);
957
    if (has_error_code) {
958
        PUSHQ(esp, error_code);
959
    }
960

    
961
    if (new_stack) {
962
        ss = 0 | dpl;
963
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
964
    }
965
    ESP = esp;
966

    
967
    selector = (selector & ~3) | dpl;
968
    cpu_x86_load_seg_cache(env, R_CS, selector,
969
                   get_seg_base(e1, e2),
970
                   get_seg_limit(e1, e2),
971
                   e2);
972
    cpu_x86_set_cpl(env, dpl);
973
    env->eip = offset;
974

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

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

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

    
1003
        ECX = env->eip + next_eip_addend;
1004
        env->regs[11] = compute_eflags();
1005

    
1006
        code64 = env->hflags & HF_CS64_MASK;
1007

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

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

    
1047
void helper_sysret(int dflag)
1048
{
1049
    int cpl, selector;
1050

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

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

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

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

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

    
1158
    dt = &env->idt;
1159
    if (env->hflags & HF_LMA_MASK) {
1160
        shift = 4;
1161
    } else {
1162
        shift = 3;
1163
    }
1164
    ptr = dt->base + (intno << shift);
1165
    e2 = ldl_kernel(ptr + 4);
1166

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

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

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

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

    
1246
    if (loglevel & CPU_LOG_INT)
1247
        fprintf(logfile, "check_exception old: 0x%x new 0x%x\n",
1248
                env->old_exception, intno);
1249

    
1250
    if (env->old_exception == EXCP08_DBLE)
1251
        cpu_abort(env, "triple fault");
1252

    
1253
    if ((first_contributory && second_contributory)
1254
        || (env->old_exception == EXCP0E_PAGE &&
1255
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1256
        intno = EXCP08_DBLE;
1257
        *error_code = 0;
1258
    }
1259

    
1260
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1261
        (intno == EXCP08_DBLE))
1262
        env->old_exception = intno;
1263

    
1264
    return intno;
1265
}
1266

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

    
1283
    env->exception_index = intno;
1284
    env->error_code = error_code;
1285
    env->exception_is_int = is_int;
1286
    env->exception_next_eip = env->eip + next_eip_addend;
1287
    cpu_loop_exit();
1288
}
1289

    
1290
/* shortcuts to generate exceptions */
1291

    
1292
void (raise_exception_err)(int exception_index, int error_code)
1293
{
1294
    raise_interrupt(exception_index, 0, error_code, 0);
1295
}
1296

    
1297
void raise_exception(int exception_index)
1298
{
1299
    raise_interrupt(exception_index, 0, 0, 0);
1300
}
1301

    
1302
/* SMM support */
1303

    
1304
#if defined(CONFIG_USER_ONLY)
1305

    
1306
void do_smm_enter(void)
1307
{
1308
}
1309

    
1310
void helper_rsm(void)
1311
{
1312
}
1313

    
1314
#else
1315

    
1316
#ifdef TARGET_X86_64
1317
#define SMM_REVISION_ID 0x00020064
1318
#else
1319
#define SMM_REVISION_ID 0x00020000
1320
#endif
1321

    
1322
void do_smm_enter(void)
1323
{
1324
    target_ulong sm_state;
1325
    SegmentCache *dt;
1326
    int i, offset;
1327

    
1328
    if (loglevel & CPU_LOG_INT) {
1329
        fprintf(logfile, "SMM: enter\n");
1330
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1331
    }
1332

    
1333
    env->hflags |= HF_SMM_MASK;
1334
    cpu_smm_update(env);
1335

    
1336
    sm_state = env->smbase + 0x8000;
1337

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

    
1348
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1349
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1350

    
1351
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1352
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1353
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1354
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1355

    
1356
    stq_phys(sm_state + 0x7e88, env->idt.base);
1357
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1358

    
1359
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1360
    stq_phys(sm_state + 0x7e98, env->tr.base);
1361
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1362
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1363

    
1364
    stq_phys(sm_state + 0x7ed0, env->efer);
1365

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

    
1381
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1382
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1383
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1384

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

    
1403
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1404
    stl_phys(sm_state + 0x7f64, env->tr.base);
1405
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1406
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1407

    
1408
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1409
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1410
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1411
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1412

    
1413
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1414
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1415

    
1416
    stl_phys(sm_state + 0x7f58, env->idt.base);
1417
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1418

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

    
1432
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1433
    stl_phys(sm_state + 0x7ef8, env->smbase);
1434
#endif
1435
    /* init SMM cpu state */
1436

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

    
1450
    cpu_x86_update_cr0(env,
1451
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1452
    cpu_x86_update_cr4(env, 0);
1453
    env->dr[7] = 0x00000400;
1454
    CC_OP = CC_OP_EFLAGS;
1455
}
1456

    
1457
void helper_rsm(void)
1458
{
1459
    target_ulong sm_state;
1460
    int i, offset;
1461
    uint32_t val;
1462

    
1463
    sm_state = env->smbase + 0x8000;
1464
#ifdef TARGET_X86_64
1465
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1466

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

    
1476
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1477
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1478

    
1479
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1480
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1481
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1482
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1483

    
1484
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1485
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1486

    
1487
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1488
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1489
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1490
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1491

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

    
1508
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1509
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1510
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1511

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

    
1533
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1534
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1535
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1536
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1537

    
1538
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1539
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1540
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1541
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1542

    
1543
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1544
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1545

    
1546
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1547
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1548

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

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

    
1571
    if (loglevel & CPU_LOG_INT) {
1572
        fprintf(logfile, "SMM: after RSM\n");
1573
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1574
    }
1575
}
1576

    
1577
#endif /* !CONFIG_USER_ONLY */
1578

    
1579

    
1580
/* division, flags are undefined */
1581

    
1582
void helper_divb_AL(target_ulong t0)
1583
{
1584
    unsigned int num, den, q, r;
1585

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

    
1599
void helper_idivb_AL(target_ulong t0)
1600
{
1601
    int num, den, q, r;
1602

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

    
1616
void helper_divw_AX(target_ulong t0)
1617
{
1618
    unsigned int num, den, q, r;
1619

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

    
1634
void helper_idivw_AX(target_ulong t0)
1635
{
1636
    int num, den, q, r;
1637

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

    
1652
void helper_divl_EAX(target_ulong t0)
1653
{
1654
    unsigned int den, r;
1655
    uint64_t num, q;
1656

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

    
1670
void helper_idivl_EAX(target_ulong t0)
1671
{
1672
    int den, r;
1673
    int64_t num, q;
1674

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

    
1688
/* bcd */
1689

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

    
1701
void helper_aad(int base)
1702
{
1703
    int al, ah;
1704
    al = EAX & 0xff;
1705
    ah = (EAX >> 8) & 0xff;
1706
    al = ((ah * base) + al) & 0xff;
1707
    EAX = (EAX & ~0xffff) | al;
1708
    CC_DST = al;
1709
}
1710

    
1711
void helper_aaa(void)
1712
{
1713
    int icarry;
1714
    int al, ah, af;
1715
    int eflags;
1716

    
1717
    eflags = cc_table[CC_OP].compute_all();
1718
    af = eflags & CC_A;
1719
    al = EAX & 0xff;
1720
    ah = (EAX >> 8) & 0xff;
1721

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

    
1736
void helper_aas(void)
1737
{
1738
    int icarry;
1739
    int al, ah, af;
1740
    int eflags;
1741

    
1742
    eflags = cc_table[CC_OP].compute_all();
1743
    af = eflags & CC_A;
1744
    al = EAX & 0xff;
1745
    ah = (EAX >> 8) & 0xff;
1746

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

    
1761
void helper_daa(void)
1762
{
1763
    int al, af, cf;
1764
    int eflags;
1765

    
1766
    eflags = cc_table[CC_OP].compute_all();
1767
    cf = eflags & CC_C;
1768
    af = eflags & CC_A;
1769
    al = EAX & 0xff;
1770

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

    
1789
void helper_das(void)
1790
{
1791
    int al, al1, af, cf;
1792
    int eflags;
1793

    
1794
    eflags = cc_table[CC_OP].compute_all();
1795
    cf = eflags & CC_C;
1796
    af = eflags & CC_A;
1797
    al = EAX & 0xff;
1798

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

    
1820
void helper_into(int next_eip_addend)
1821
{
1822
    int eflags;
1823
    eflags = cc_table[CC_OP].compute_all();
1824
    if (eflags & CC_O) {
1825
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1826
    }
1827
}
1828

    
1829
void helper_cmpxchg8b(target_ulong a0)
1830
{
1831
    uint64_t d;
1832
    int eflags;
1833

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

    
1849
#ifdef TARGET_X86_64
1850
void helper_cmpxchg16b(target_ulong a0)
1851
{
1852
    uint64_t d0, d1;
1853
    int eflags;
1854

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

    
1876
void helper_single_step(void)
1877
{
1878
    env->dr[6] |= 0x4000;
1879
    raise_exception(EXCP01_SSTP);
1880
}
1881

    
1882
void helper_cpuid(void)
1883
{
1884
    uint32_t index;
1885

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

    
1898
    switch(index) {
1899
    case 0:
1900
        EAX = env->cpuid_level;
1901
        EBX = env->cpuid_vendor1;
1902
        EDX = env->cpuid_vendor2;
1903
        ECX = env->cpuid_vendor3;
1904
        break;
1905
    case 1:
1906
        EAX = env->cpuid_version;
1907
        EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1908
        ECX = env->cpuid_ext_features;
1909
        EDX = env->cpuid_features;
1910
        break;
1911
    case 2:
1912
        /* cache info: needed for Pentium Pro compatibility */
1913
        EAX = 1;
1914
        EBX = 0;
1915
        ECX = 0;
1916
        EDX = 0x2c307d;
1917
        break;
1918
    case 0x80000000:
1919
        EAX = env->cpuid_xlevel;
1920
        EBX = env->cpuid_vendor1;
1921
        EDX = env->cpuid_vendor2;
1922
        ECX = env->cpuid_vendor3;
1923
        break;
1924
    case 0x80000001:
1925
        EAX = env->cpuid_features;
1926
        EBX = 0;
1927
        ECX = env->cpuid_ext3_features;
1928
        EDX = env->cpuid_ext2_features;
1929
        break;
1930
    case 0x80000002:
1931
    case 0x80000003:
1932
    case 0x80000004:
1933
        EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1934
        EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1935
        ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1936
        EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1937
        break;
1938
    case 0x80000005:
1939
        /* cache info (L1 cache) */
1940
        EAX = 0x01ff01ff;
1941
        EBX = 0x01ff01ff;
1942
        ECX = 0x40020140;
1943
        EDX = 0x40020140;
1944
        break;
1945
    case 0x80000006:
1946
        /* cache info (L2 cache) */
1947
        EAX = 0;
1948
        EBX = 0x42004200;
1949
        ECX = 0x02008140;
1950
        EDX = 0;
1951
        break;
1952
    case 0x80000008:
1953
        /* virtual & phys address size in low 2 bytes. */
1954
/* XXX: This value must match the one used in the MMU code. */ 
1955
        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
1956
            /* 64 bit processor */
1957
#if defined(USE_KQEMU)
1958
            EAX = 0x00003020;        /* 48 bits virtual, 32 bits physical */
1959
#else
1960
/* XXX: The physical address space is limited to 42 bits in exec.c. */
1961
            EAX = 0x00003028;        /* 48 bits virtual, 40 bits physical */
1962
#endif
1963
        } else {
1964
#if defined(USE_KQEMU)
1965
            EAX = 0x00000020;        /* 32 bits physical */
1966
#else
1967
            EAX = 0x00000024;        /* 36 bits physical */
1968
#endif
1969
        }
1970
        EBX = 0;
1971
        ECX = 0;
1972
        EDX = 0;
1973
        break;
1974
    case 0x8000000A:
1975
        EAX = 0x00000001;
1976
        EBX = 0;
1977
        ECX = 0;
1978
        EDX = 0;
1979
        break;
1980
    default:
1981
        /* reserved values: zero */
1982
        EAX = 0;
1983
        EBX = 0;
1984
        ECX = 0;
1985
        EDX = 0;
1986
        break;
1987
    }
1988
}
1989

    
1990
void helper_enter_level(int level, int data32, target_ulong t1)
1991
{
1992
    target_ulong ssp;
1993
    uint32_t esp_mask, esp, ebp;
1994

    
1995
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1996
    ssp = env->segs[R_SS].base;
1997
    ebp = EBP;
1998
    esp = ESP;
1999
    if (data32) {
2000
        /* 32 bit */
2001
        esp -= 4;
2002
        while (--level) {
2003
            esp -= 4;
2004
            ebp -= 4;
2005
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
2006
        }
2007
        esp -= 4;
2008
        stl(ssp + (esp & esp_mask), t1);
2009
    } else {
2010
        /* 16 bit */
2011
        esp -= 2;
2012
        while (--level) {
2013
            esp -= 2;
2014
            ebp -= 2;
2015
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
2016
        }
2017
        esp -= 2;
2018
        stw(ssp + (esp & esp_mask), t1);
2019
    }
2020
}
2021

    
2022
#ifdef TARGET_X86_64
2023
void helper_enter64_level(int level, int data64, target_ulong t1)
2024
{
2025
    target_ulong esp, ebp;
2026
    ebp = EBP;
2027
    esp = ESP;
2028

    
2029
    if (data64) {
2030
        /* 64 bit */
2031
        esp -= 8;
2032
        while (--level) {
2033
            esp -= 8;
2034
            ebp -= 8;
2035
            stq(esp, ldq(ebp));
2036
        }
2037
        esp -= 8;
2038
        stq(esp, t1);
2039
    } else {
2040
        /* 16 bit */
2041
        esp -= 2;
2042
        while (--level) {
2043
            esp -= 2;
2044
            ebp -= 2;
2045
            stw(esp, lduw(ebp));
2046
        }
2047
        esp -= 2;
2048
        stw(esp, t1);
2049
    }
2050
}
2051
#endif
2052

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

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

    
2100
void helper_ltr(int selector)
2101
{
2102
    SegmentCache *dt;
2103
    uint32_t e1, e2;
2104
    int index, type, entry_limit;
2105
    target_ulong ptr;
2106

    
2107
    selector &= 0xffff;
2108
    if ((selector & 0xfffc) == 0) {
2109
        /* NULL selector case: invalid TR */
2110
        env->tr.base = 0;
2111
        env->tr.limit = 0;
2112
        env->tr.flags = 0;
2113
    } else {
2114
        if (selector & 0x4)
2115
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2116
        dt = &env->gdt;
2117
        index = selector & ~7;
2118
#ifdef TARGET_X86_64
2119
        if (env->hflags & HF_LMA_MASK)
2120
            entry_limit = 15;
2121
        else
2122
#endif
2123
            entry_limit = 7;
2124
        if ((index + entry_limit) > dt->limit)
2125
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2126
        ptr = dt->base + index;
2127
        e1 = ldl_kernel(ptr);
2128
        e2 = ldl_kernel(ptr + 4);
2129
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2130
        if ((e2 & DESC_S_MASK) ||
2131
            (type != 1 && type != 9))
2132
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2133
        if (!(e2 & DESC_P_MASK))
2134
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2135
#ifdef TARGET_X86_64
2136
        if (env->hflags & HF_LMA_MASK) {
2137
            uint32_t e3, e4;
2138
            e3 = ldl_kernel(ptr + 8);
2139
            e4 = ldl_kernel(ptr + 12);
2140
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2141
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2142
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2143
            env->tr.base |= (target_ulong)e3 << 32;
2144
        } else
2145
#endif
2146
        {
2147
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2148
        }
2149
        e2 |= DESC_TSS_BUSY_MASK;
2150
        stl_kernel(ptr + 4, e2);
2151
    }
2152
    env->tr.selector = selector;
2153
}
2154

    
2155
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2156
void helper_load_seg(int seg_reg, int selector)
2157
{
2158
    uint32_t e1, e2;
2159
    int cpl, dpl, rpl;
2160
    SegmentCache *dt;
2161
    int index;
2162
    target_ulong ptr;
2163

    
2164
    selector &= 0xffff;
2165
    cpl = env->hflags & HF_CPL_MASK;
2166
    if ((selector & 0xfffc) == 0) {
2167
        /* null selector case */
2168
        if (seg_reg == R_SS
2169
#ifdef TARGET_X86_64
2170
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2171
#endif
2172
            )
2173
            raise_exception_err(EXCP0D_GPF, 0);
2174
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2175
    } else {
2176

    
2177
        if (selector & 0x4)
2178
            dt = &env->ldt;
2179
        else
2180
            dt = &env->gdt;
2181
        index = selector & ~7;
2182
        if ((index + 7) > dt->limit)
2183
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2184
        ptr = dt->base + index;
2185
        e1 = ldl_kernel(ptr);
2186
        e2 = ldl_kernel(ptr + 4);
2187

    
2188
        if (!(e2 & DESC_S_MASK))
2189
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2190
        rpl = selector & 3;
2191
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2192
        if (seg_reg == R_SS) {
2193
            /* must be writable segment */
2194
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2195
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2196
            if (rpl != cpl || dpl != cpl)
2197
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2198
        } else {
2199
            /* must be readable segment */
2200
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2201
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2202

    
2203
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2204
                /* if not conforming code, test rights */
2205
                if (dpl < cpl || dpl < rpl)
2206
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2207
            }
2208
        }
2209

    
2210
        if (!(e2 & DESC_P_MASK)) {
2211
            if (seg_reg == R_SS)
2212
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2213
            else
2214
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2215
        }
2216

    
2217
        /* set the access bit if not already set */
2218
        if (!(e2 & DESC_A_MASK)) {
2219
            e2 |= DESC_A_MASK;
2220
            stl_kernel(ptr + 4, e2);
2221
        }
2222

    
2223
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2224
                       get_seg_base(e1, e2),
2225
                       get_seg_limit(e1, e2),
2226
                       e2);
2227
#if 0
2228
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2229
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2230
#endif
2231
    }
2232
}
2233

    
2234
/* protected mode jump */
2235
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2236
                           int next_eip_addend)
2237
{
2238
    int gate_cs, type;
2239
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2240
    target_ulong next_eip;
2241

    
2242
    if ((new_cs & 0xfffc) == 0)
2243
        raise_exception_err(EXCP0D_GPF, 0);
2244
    if (load_segment(&e1, &e2, new_cs) != 0)
2245
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2246
    cpl = env->hflags & HF_CPL_MASK;
2247
    if (e2 & DESC_S_MASK) {
2248
        if (!(e2 & DESC_CS_MASK))
2249
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2250
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2251
        if (e2 & DESC_C_MASK) {
2252
            /* conforming code segment */
2253
            if (dpl > cpl)
2254
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2255
        } else {
2256
            /* non conforming code segment */
2257
            rpl = new_cs & 3;
2258
            if (rpl > cpl)
2259
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2260
            if (dpl != cpl)
2261
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2262
        }
2263
        if (!(e2 & DESC_P_MASK))
2264
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2265
        limit = get_seg_limit(e1, e2);
2266
        if (new_eip > limit &&
2267
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2268
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2269
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2270
                       get_seg_base(e1, e2), limit, e2);
2271
        EIP = new_eip;
2272
    } else {
2273
        /* jump to call or task gate */
2274
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2275
        rpl = new_cs & 3;
2276
        cpl = env->hflags & HF_CPL_MASK;
2277
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2278
        switch(type) {
2279
        case 1: /* 286 TSS */
2280
        case 9: /* 386 TSS */
2281
        case 5: /* task gate */
2282
            if (dpl < cpl || dpl < rpl)
2283
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2284
            next_eip = env->eip + next_eip_addend;
2285
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2286
            CC_OP = CC_OP_EFLAGS;
2287
            break;
2288
        case 4: /* 286 call gate */
2289
        case 12: /* 386 call gate */
2290
            if ((dpl < cpl) || (dpl < rpl))
2291
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2292
            if (!(e2 & DESC_P_MASK))
2293
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2294
            gate_cs = e1 >> 16;
2295
            new_eip = (e1 & 0xffff);
2296
            if (type == 12)
2297
                new_eip |= (e2 & 0xffff0000);
2298
            if (load_segment(&e1, &e2, gate_cs) != 0)
2299
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2300
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2301
            /* must be code segment */
2302
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2303
                 (DESC_S_MASK | DESC_CS_MASK)))
2304
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2305
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2306
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2307
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2308
            if (!(e2 & DESC_P_MASK))
2309
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2310
            limit = get_seg_limit(e1, e2);
2311
            if (new_eip > limit)
2312
                raise_exception_err(EXCP0D_GPF, 0);
2313
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2314
                                   get_seg_base(e1, e2), limit, e2);
2315
            EIP = new_eip;
2316
            break;
2317
        default:
2318
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2319
            break;
2320
        }
2321
    }
2322
}
2323

    
2324
/* real mode call */
2325
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2326
                       int shift, int next_eip)
2327
{
2328
    int new_eip;
2329
    uint32_t esp, esp_mask;
2330
    target_ulong ssp;
2331

    
2332
    new_eip = new_eip1;
2333
    esp = ESP;
2334
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2335
    ssp = env->segs[R_SS].base;
2336
    if (shift) {
2337
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2338
        PUSHL(ssp, esp, esp_mask, next_eip);
2339
    } else {
2340
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2341
        PUSHW(ssp, esp, esp_mask, next_eip);
2342
    }
2343

    
2344
    SET_ESP(esp, esp_mask);
2345
    env->eip = new_eip;
2346
    env->segs[R_CS].selector = new_cs;
2347
    env->segs[R_CS].base = (new_cs << 4);
2348
}
2349

    
2350
/* protected mode call */
2351
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2352
                            int shift, int next_eip_addend)
2353
{
2354
    int new_stack, i;
2355
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2356
    uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
2357
    uint32_t val, limit, old_sp_mask;
2358
    target_ulong ssp, old_ssp, next_eip;
2359

    
2360
    next_eip = env->eip + next_eip_addend;
2361
#ifdef DEBUG_PCALL
2362
    if (loglevel & CPU_LOG_PCALL) {
2363
        fprintf(logfile, "lcall %04x:%08x s=%d\n",
2364
                new_cs, (uint32_t)new_eip, shift);
2365
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2366
    }
2367
#endif
2368
    if ((new_cs & 0xfffc) == 0)
2369
        raise_exception_err(EXCP0D_GPF, 0);
2370
    if (load_segment(&e1, &e2, new_cs) != 0)
2371
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2372
    cpl = env->hflags & HF_CPL_MASK;
2373
#ifdef DEBUG_PCALL
2374
    if (loglevel & CPU_LOG_PCALL) {
2375
        fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
2376
    }
2377
#endif
2378
    if (e2 & DESC_S_MASK) {
2379
        if (!(e2 & DESC_CS_MASK))
2380
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2381
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2382
        if (e2 & DESC_C_MASK) {
2383
            /* conforming code segment */
2384
            if (dpl > cpl)
2385
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2386
        } else {
2387
            /* non conforming code segment */
2388
            rpl = new_cs & 3;
2389
            if (rpl > cpl)
2390
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2391
            if (dpl != cpl)
2392
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2393
        }
2394
        if (!(e2 & DESC_P_MASK))
2395
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2396

    
2397
#ifdef TARGET_X86_64
2398
        /* XXX: check 16/32 bit cases in long mode */
2399
        if (shift == 2) {
2400
            target_ulong rsp;
2401
            /* 64 bit case */
2402
            rsp = ESP;
2403
            PUSHQ(rsp, env->segs[R_CS].selector);
2404
            PUSHQ(rsp, next_eip);
2405
            /* from this point, not restartable */
2406
            ESP = rsp;
2407
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2408
                                   get_seg_base(e1, e2),
2409
                                   get_seg_limit(e1, e2), e2);
2410
            EIP = new_eip;
2411
        } else
2412
#endif
2413
        {
2414
            sp = ESP;
2415
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2416
            ssp = env->segs[R_SS].base;
2417
            if (shift) {
2418
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2419
                PUSHL(ssp, sp, sp_mask, next_eip);
2420
            } else {
2421
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2422
                PUSHW(ssp, sp, sp_mask, next_eip);
2423
            }
2424

    
2425
            limit = get_seg_limit(e1, e2);
2426
            if (new_eip > limit)
2427
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2428
            /* from this point, not restartable */
2429
            SET_ESP(sp, sp_mask);
2430
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2431
                                   get_seg_base(e1, e2), limit, e2);
2432
            EIP = new_eip;
2433
        }
2434
    } else {
2435
        /* check gate type */
2436
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2437
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2438
        rpl = new_cs & 3;
2439
        switch(type) {
2440
        case 1: /* available 286 TSS */
2441
        case 9: /* available 386 TSS */
2442
        case 5: /* task gate */
2443
            if (dpl < cpl || dpl < rpl)
2444
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2445
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2446
            CC_OP = CC_OP_EFLAGS;
2447
            return;
2448
        case 4: /* 286 call gate */
2449
        case 12: /* 386 call gate */
2450
            break;
2451
        default:
2452
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2453
            break;
2454
        }
2455
        shift = type >> 3;
2456

    
2457
        if (dpl < cpl || dpl < rpl)
2458
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2459
        /* check valid bit */
2460
        if (!(e2 & DESC_P_MASK))
2461
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2462
        selector = e1 >> 16;
2463
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2464
        param_count = e2 & 0x1f;
2465
        if ((selector & 0xfffc) == 0)
2466
            raise_exception_err(EXCP0D_GPF, 0);
2467

    
2468
        if (load_segment(&e1, &e2, selector) != 0)
2469
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2470
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2471
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2472
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2473
        if (dpl > cpl)
2474
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2475
        if (!(e2 & DESC_P_MASK))
2476
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2477

    
2478
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2479
            /* to inner privilege */
2480
            get_ss_esp_from_tss(&ss, &sp, dpl);
2481
#ifdef DEBUG_PCALL
2482
            if (loglevel & CPU_LOG_PCALL)
2483
                fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2484
                        ss, sp, param_count, ESP);
2485
#endif
2486
            if ((ss & 0xfffc) == 0)
2487
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2488
            if ((ss & 3) != dpl)
2489
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2490
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2491
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2492
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2493
            if (ss_dpl != dpl)
2494
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2495
            if (!(ss_e2 & DESC_S_MASK) ||
2496
                (ss_e2 & DESC_CS_MASK) ||
2497
                !(ss_e2 & DESC_W_MASK))
2498
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2499
            if (!(ss_e2 & DESC_P_MASK))
2500
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2501

    
2502
            //            push_size = ((param_count * 2) + 8) << shift;
2503

    
2504
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2505
            old_ssp = env->segs[R_SS].base;
2506

    
2507
            sp_mask = get_sp_mask(ss_e2);
2508
            ssp = get_seg_base(ss_e1, ss_e2);
2509
            if (shift) {
2510
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2511
                PUSHL(ssp, sp, sp_mask, ESP);
2512
                for(i = param_count - 1; i >= 0; i--) {
2513
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2514
                    PUSHL(ssp, sp, sp_mask, val);
2515
                }
2516
            } else {
2517
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2518
                PUSHW(ssp, sp, sp_mask, ESP);
2519
                for(i = param_count - 1; i >= 0; i--) {
2520
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2521
                    PUSHW(ssp, sp, sp_mask, val);
2522
                }
2523
            }
2524
            new_stack = 1;
2525
        } else {
2526
            /* to same privilege */
2527
            sp = ESP;
2528
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2529
            ssp = env->segs[R_SS].base;
2530
            //            push_size = (4 << shift);
2531
            new_stack = 0;
2532
        }
2533

    
2534
        if (shift) {
2535
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2536
            PUSHL(ssp, sp, sp_mask, next_eip);
2537
        } else {
2538
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2539
            PUSHW(ssp, sp, sp_mask, next_eip);
2540
        }
2541

    
2542
        /* from this point, not restartable */
2543

    
2544
        if (new_stack) {
2545
            ss = (ss & ~3) | dpl;
2546
            cpu_x86_load_seg_cache(env, R_SS, ss,
2547
                                   ssp,
2548
                                   get_seg_limit(ss_e1, ss_e2),
2549
                                   ss_e2);
2550
        }
2551

    
2552
        selector = (selector & ~3) | dpl;
2553
        cpu_x86_load_seg_cache(env, R_CS, selector,
2554
                       get_seg_base(e1, e2),
2555
                       get_seg_limit(e1, e2),
2556
                       e2);
2557
        cpu_x86_set_cpl(env, dpl);
2558
        SET_ESP(sp, sp_mask);
2559
        EIP = offset;
2560
    }
2561
#ifdef USE_KQEMU
2562
    if (kqemu_is_ok(env)) {
2563
        env->exception_index = -1;
2564
        cpu_loop_exit();
2565
    }
2566
#endif
2567
}
2568

    
2569
/* real and vm86 mode iret */
2570
void helper_iret_real(int shift)
2571
{
2572
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2573
    target_ulong ssp;
2574
    int eflags_mask;
2575

    
2576
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2577
    sp = ESP;
2578
    ssp = env->segs[R_SS].base;
2579
    if (shift == 1) {
2580
        /* 32 bits */
2581
        POPL(ssp, sp, sp_mask, new_eip);
2582
        POPL(ssp, sp, sp_mask, new_cs);
2583
        new_cs &= 0xffff;
2584
        POPL(ssp, sp, sp_mask, new_eflags);
2585
    } else {
2586
        /* 16 bits */
2587
        POPW(ssp, sp, sp_mask, new_eip);
2588
        POPW(ssp, sp, sp_mask, new_cs);
2589
        POPW(ssp, sp, sp_mask, new_eflags);
2590
    }
2591
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2592
    load_seg_vm(R_CS, new_cs);
2593
    env->eip = new_eip;
2594
    if (env->eflags & VM_MASK)
2595
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2596
    else
2597
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2598
    if (shift == 0)
2599
        eflags_mask &= 0xffff;
2600
    load_eflags(new_eflags, eflags_mask);
2601
    env->hflags2 &= ~HF2_NMI_MASK;
2602
}
2603

    
2604
static inline void validate_seg(int seg_reg, int cpl)
2605
{
2606
    int dpl;
2607
    uint32_t e2;
2608

    
2609
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2610
       they may still contain a valid base. I would be interested to
2611
       know how a real x86_64 CPU behaves */
2612
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2613
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2614
        return;
2615

    
2616
    e2 = env->segs[seg_reg].flags;
2617
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2618
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2619
        /* data or non conforming code segment */
2620
        if (dpl < cpl) {
2621
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2622
        }
2623
    }
2624
}
2625

    
2626
/* protected mode iret */
2627
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2628
{
2629
    uint32_t new_cs, new_eflags, new_ss;
2630
    uint32_t new_es, new_ds, new_fs, new_gs;
2631
    uint32_t e1, e2, ss_e1, ss_e2;
2632
    int cpl, dpl, rpl, eflags_mask, iopl;
2633
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2634

    
2635
#ifdef TARGET_X86_64
2636
    if (shift == 2)
2637
        sp_mask = -1;
2638
    else
2639
#endif
2640
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2641
    sp = ESP;
2642
    ssp = env->segs[R_SS].base;
2643
    new_eflags = 0; /* avoid warning */
2644
#ifdef TARGET_X86_64
2645
    if (shift == 2) {
2646
        POPQ(sp, new_eip);
2647
        POPQ(sp, new_cs);
2648
        new_cs &= 0xffff;
2649
        if (is_iret) {
2650
            POPQ(sp, new_eflags);
2651
        }
2652
    } else
2653
#endif
2654
    if (shift == 1) {
2655
        /* 32 bits */
2656
        POPL(ssp, sp, sp_mask, new_eip);
2657
        POPL(ssp, sp, sp_mask, new_cs);
2658
        new_cs &= 0xffff;
2659
        if (is_iret) {
2660
            POPL(ssp, sp, sp_mask, new_eflags);
2661
            if (new_eflags & VM_MASK)
2662
                goto return_to_vm86;
2663
        }
2664
    } else {
2665
        /* 16 bits */
2666
        POPW(ssp, sp, sp_mask, new_eip);
2667
        POPW(ssp, sp, sp_mask, new_cs);
2668
        if (is_iret)
2669
            POPW(ssp, sp, sp_mask, new_eflags);
2670
    }
2671
#ifdef DEBUG_PCALL
2672
    if (loglevel & CPU_LOG_PCALL) {
2673
        fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2674
                new_cs, new_eip, shift, addend);
2675
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2676
    }
2677
#endif
2678
    if ((new_cs & 0xfffc) == 0)
2679
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2680
    if (load_segment(&e1, &e2, new_cs) != 0)
2681
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2682
    if (!(e2 & DESC_S_MASK) ||
2683
        !(e2 & DESC_CS_MASK))
2684
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2685
    cpl = env->hflags & HF_CPL_MASK;
2686
    rpl = new_cs & 3;
2687
    if (rpl < cpl)
2688
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2689
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2690
    if (e2 & DESC_C_MASK) {
2691
        if (dpl > rpl)
2692
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2693
    } else {
2694
        if (dpl != rpl)
2695
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2696
    }
2697
    if (!(e2 & DESC_P_MASK))
2698
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2699

    
2700
    sp += addend;
2701
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2702
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2703
        /* return to same privilege level */
2704
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2705
                       get_seg_base(e1, e2),
2706
                       get_seg_limit(e1, e2),
2707
                       e2);
2708
    } else {
2709
        /* return to different privilege level */
2710
#ifdef TARGET_X86_64
2711
        if (shift == 2) {
2712
            POPQ(sp, new_esp);
2713
            POPQ(sp, new_ss);
2714
            new_ss &= 0xffff;
2715
        } else
2716
#endif
2717
        if (shift == 1) {
2718
            /* 32 bits */
2719
            POPL(ssp, sp, sp_mask, new_esp);
2720
            POPL(ssp, sp, sp_mask, new_ss);
2721
            new_ss &= 0xffff;
2722
        } else {
2723
            /* 16 bits */
2724
            POPW(ssp, sp, sp_mask, new_esp);
2725
            POPW(ssp, sp, sp_mask, new_ss);
2726
        }
2727
#ifdef DEBUG_PCALL
2728
        if (loglevel & CPU_LOG_PCALL) {
2729
            fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
2730
                    new_ss, new_esp);
2731
        }
2732
#endif
2733
        if ((new_ss & 0xfffc) == 0) {
2734
#ifdef TARGET_X86_64
2735
            /* NULL ss is allowed in long mode if cpl != 3*/
2736
            /* XXX: test CS64 ? */
2737
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2738
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2739
                                       0, 0xffffffff,
2740
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2741
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2742
                                       DESC_W_MASK | DESC_A_MASK);
2743
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2744
            } else
2745
#endif
2746
            {
2747
                raise_exception_err(EXCP0D_GPF, 0);
2748
            }
2749
        } else {
2750
            if ((new_ss & 3) != rpl)
2751
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2752
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2753
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2754
            if (!(ss_e2 & DESC_S_MASK) ||
2755
                (ss_e2 & DESC_CS_MASK) ||
2756
                !(ss_e2 & DESC_W_MASK))
2757
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2758
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2759
            if (dpl != rpl)
2760
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2761
            if (!(ss_e2 & DESC_P_MASK))
2762
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2763
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2764
                                   get_seg_base(ss_e1, ss_e2),
2765
                                   get_seg_limit(ss_e1, ss_e2),
2766
                                   ss_e2);
2767
        }
2768

    
2769
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2770
                       get_seg_base(e1, e2),
2771
                       get_seg_limit(e1, e2),
2772
                       e2);
2773
        cpu_x86_set_cpl(env, rpl);
2774
        sp = new_esp;
2775
#ifdef TARGET_X86_64
2776
        if (env->hflags & HF_CS64_MASK)
2777
            sp_mask = -1;
2778
        else
2779
#endif
2780
            sp_mask = get_sp_mask(ss_e2);
2781

    
2782
        /* validate data segments */
2783
        validate_seg(R_ES, rpl);
2784
        validate_seg(R_DS, rpl);
2785
        validate_seg(R_FS, rpl);
2786
        validate_seg(R_GS, rpl);
2787

    
2788
        sp += addend;
2789
    }
2790
    SET_ESP(sp, sp_mask);
2791
    env->eip = new_eip;
2792
    if (is_iret) {
2793
        /* NOTE: 'cpl' is the _old_ CPL */
2794
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2795
        if (cpl == 0)
2796
            eflags_mask |= IOPL_MASK;
2797
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2798
        if (cpl <= iopl)
2799
            eflags_mask |= IF_MASK;
2800
        if (shift == 0)
2801
            eflags_mask &= 0xffff;
2802
        load_eflags(new_eflags, eflags_mask);
2803
    }
2804
    return;
2805

    
2806
 return_to_vm86:
2807
    POPL(ssp, sp, sp_mask, new_esp);
2808
    POPL(ssp, sp, sp_mask, new_ss);
2809
    POPL(ssp, sp, sp_mask, new_es);
2810
    POPL(ssp, sp, sp_mask, new_ds);
2811
    POPL(ssp, sp, sp_mask, new_fs);
2812
    POPL(ssp, sp, sp_mask, new_gs);
2813

    
2814
    /* modify processor state */
2815
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2816
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2817
    load_seg_vm(R_CS, new_cs & 0xffff);
2818
    cpu_x86_set_cpl(env, 3);
2819
    load_seg_vm(R_SS, new_ss & 0xffff);
2820
    load_seg_vm(R_ES, new_es & 0xffff);
2821
    load_seg_vm(R_DS, new_ds & 0xffff);
2822
    load_seg_vm(R_FS, new_fs & 0xffff);
2823
    load_seg_vm(R_GS, new_gs & 0xffff);
2824

    
2825
    env->eip = new_eip & 0xffff;
2826
    ESP = new_esp;
2827
}
2828

    
2829
void helper_iret_protected(int shift, int next_eip)
2830
{
2831
    int tss_selector, type;
2832
    uint32_t e1, e2;
2833

    
2834
    /* specific case for TSS */
2835
    if (env->eflags & NT_MASK) {
2836
#ifdef TARGET_X86_64
2837
        if (env->hflags & HF_LMA_MASK)
2838
            raise_exception_err(EXCP0D_GPF, 0);
2839
#endif
2840
        tss_selector = lduw_kernel(env->tr.base + 0);
2841
        if (tss_selector & 4)
2842
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2843
        if (load_segment(&e1, &e2, tss_selector) != 0)
2844
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2845
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2846
        /* NOTE: we check both segment and busy TSS */
2847
        if (type != 3)
2848
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2849
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2850
    } else {
2851
        helper_ret_protected(shift, 1, 0);
2852
    }
2853
    env->hflags2 &= ~HF2_NMI_MASK;
2854
#ifdef USE_KQEMU
2855
    if (kqemu_is_ok(env)) {
2856
        CC_OP = CC_OP_EFLAGS;
2857
        env->exception_index = -1;
2858
        cpu_loop_exit();
2859
    }
2860
#endif
2861
}
2862

    
2863
void helper_lret_protected(int shift, int addend)
2864
{
2865
    helper_ret_protected(shift, 0, addend);
2866
#ifdef USE_KQEMU
2867
    if (kqemu_is_ok(env)) {
2868
        env->exception_index = -1;
2869
        cpu_loop_exit();
2870
    }
2871
#endif
2872
}
2873

    
2874
void helper_sysenter(void)
2875
{
2876
    if (env->sysenter_cs == 0) {
2877
        raise_exception_err(EXCP0D_GPF, 0);
2878
    }
2879
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2880
    cpu_x86_set_cpl(env, 0);
2881
    cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2882
                           0, 0xffffffff,
2883
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2884
                           DESC_S_MASK |
2885
                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2886
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2887
                           0, 0xffffffff,
2888
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2889
                           DESC_S_MASK |
2890
                           DESC_W_MASK | DESC_A_MASK);
2891
    ESP = env->sysenter_esp;
2892
    EIP = env->sysenter_eip;
2893
}
2894

    
2895
void helper_sysexit(void)
2896
{
2897
    int cpl;
2898

    
2899
    cpl = env->hflags & HF_CPL_MASK;
2900
    if (env->sysenter_cs == 0 || cpl != 0) {
2901
        raise_exception_err(EXCP0D_GPF, 0);
2902
    }
2903
    cpu_x86_set_cpl(env, 3);
2904
    cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2905
                           0, 0xffffffff,
2906
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2907
                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2908
                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2909
    cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2910
                           0, 0xffffffff,
2911
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2912
                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2913
                           DESC_W_MASK | DESC_A_MASK);
2914
    ESP = ECX;
2915
    EIP = EDX;
2916
#ifdef USE_KQEMU
2917
    if (kqemu_is_ok(env)) {
2918
        env->exception_index = -1;
2919
        cpu_loop_exit();
2920
    }
2921
#endif
2922
}
2923

    
2924
#if defined(CONFIG_USER_ONLY)
2925
target_ulong helper_read_crN(int reg)
2926
{
2927
    return 0;
2928
}
2929

    
2930
void helper_write_crN(int reg, target_ulong t0)
2931
{
2932
}
2933
#else
2934
target_ulong helper_read_crN(int reg)
2935
{
2936
    target_ulong val;
2937

    
2938
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
2939
    switch(reg) {
2940
    default:
2941
        val = env->cr[reg];
2942
        break;
2943
    case 8:
2944
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2945
            val = cpu_get_apic_tpr(env);
2946
        } else {
2947
            val = env->v_tpr;
2948
        }
2949
        break;
2950
    }
2951
    return val;
2952
}
2953

    
2954
void helper_write_crN(int reg, target_ulong t0)
2955
{
2956
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
2957
    switch(reg) {
2958
    case 0:
2959
        cpu_x86_update_cr0(env, t0);
2960
        break;
2961
    case 3:
2962
        cpu_x86_update_cr3(env, t0);
2963
        break;
2964
    case 4:
2965
        cpu_x86_update_cr4(env, t0);
2966
        break;
2967
    case 8:
2968
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2969
            cpu_set_apic_tpr(env, t0);
2970
        }
2971
        env->v_tpr = t0 & 0x0f;
2972
        break;
2973
    default:
2974
        env->cr[reg] = t0;
2975
        break;
2976
    }
2977
}
2978
#endif
2979

    
2980
void helper_lmsw(target_ulong t0)
2981
{
2982
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2983
       if already set to one. */
2984
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2985
    helper_write_crN(0, t0);
2986
}
2987

    
2988
void helper_clts(void)
2989
{
2990
    env->cr[0] &= ~CR0_TS_MASK;
2991
    env->hflags &= ~HF_TS_MASK;
2992
}
2993

    
2994
/* XXX: do more */
2995
void helper_movl_drN_T0(int reg, target_ulong t0)
2996
{
2997
    env->dr[reg] = t0;
2998
}
2999

    
3000
void helper_invlpg(target_ulong addr)
3001
{
3002
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
3003
    tlb_flush_page(env, addr);
3004
}
3005

    
3006
void helper_rdtsc(void)
3007
{
3008
    uint64_t val;
3009

    
3010
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3011
        raise_exception(EXCP0D_GPF);
3012
    }
3013
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
3014

    
3015
    val = cpu_get_tsc(env) + env->tsc_offset;
3016
    EAX = (uint32_t)(val);
3017
    EDX = (uint32_t)(val >> 32);
3018
}
3019

    
3020
void helper_rdpmc(void)
3021
{
3022
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3023
        raise_exception(EXCP0D_GPF);
3024
    }
3025
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3026
    
3027
    /* currently unimplemented */
3028
    raise_exception_err(EXCP06_ILLOP, 0);
3029
}
3030

    
3031
#if defined(CONFIG_USER_ONLY)
3032
void helper_wrmsr(void)
3033
{
3034
}
3035

    
3036
void helper_rdmsr(void)
3037
{
3038
}
3039
#else
3040
void helper_wrmsr(void)
3041
{
3042
    uint64_t val;
3043

    
3044
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3045

    
3046
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3047

    
3048
    switch((uint32_t)ECX) {
3049
    case MSR_IA32_SYSENTER_CS:
3050
        env->sysenter_cs = val & 0xffff;
3051
        break;
3052
    case MSR_IA32_SYSENTER_ESP:
3053
        env->sysenter_esp = val;
3054
        break;
3055
    case MSR_IA32_SYSENTER_EIP:
3056
        env->sysenter_eip = val;
3057
        break;
3058
    case MSR_IA32_APICBASE:
3059
        cpu_set_apic_base(env, val);
3060
        break;
3061
    case MSR_EFER:
3062
        {
3063
            uint64_t update_mask;
3064
            update_mask = 0;
3065
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3066
                update_mask |= MSR_EFER_SCE;
3067
            if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3068
                update_mask |= MSR_EFER_LME;
3069
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3070
                update_mask |= MSR_EFER_FFXSR;
3071
            if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3072
                update_mask |= MSR_EFER_NXE;
3073
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3074
                update_mask |= MSR_EFER_SVME;
3075
            cpu_load_efer(env, (env->efer & ~update_mask) |
3076
                          (val & update_mask));
3077
        }
3078
        break;
3079
    case MSR_STAR:
3080
        env->star = val;
3081
        break;
3082
    case MSR_PAT:
3083
        env->pat = val;
3084
        break;
3085
    case MSR_VM_HSAVE_PA:
3086
        env->vm_hsave = val;
3087
        break;
3088
#ifdef TARGET_X86_64
3089
    case MSR_LSTAR:
3090
        env->lstar = val;
3091
        break;
3092
    case MSR_CSTAR:
3093
        env->cstar = val;
3094
        break;
3095
    case MSR_FMASK:
3096
        env->fmask = val;
3097
        break;
3098
    case MSR_FSBASE:
3099
        env->segs[R_FS].base = val;
3100
        break;
3101
    case MSR_GSBASE:
3102
        env->segs[R_GS].base = val;
3103
        break;
3104
    case MSR_KERNELGSBASE:
3105
        env->kernelgsbase = val;
3106
        break;
3107
#endif
3108
    default:
3109
        /* XXX: exception ? */
3110
        break;
3111
    }
3112
}
3113

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

    
3118
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3119

    
3120
    switch((uint32_t)ECX) {
3121
    case MSR_IA32_SYSENTER_CS:
3122
        val = env->sysenter_cs;
3123
        break;
3124
    case MSR_IA32_SYSENTER_ESP:
3125
        val = env->sysenter_esp;
3126
        break;
3127
    case MSR_IA32_SYSENTER_EIP:
3128
        val = env->sysenter_eip;
3129
        break;
3130
    case MSR_IA32_APICBASE:
3131
        val = cpu_get_apic_base(env);
3132
        break;
3133
    case MSR_EFER:
3134
        val = env->efer;
3135
        break;
3136
    case MSR_STAR:
3137
        val = env->star;
3138
        break;
3139
    case MSR_PAT:
3140
        val = env->pat;
3141
        break;
3142
    case MSR_VM_HSAVE_PA:
3143
        val = env->vm_hsave;
3144
        break;
3145
#ifdef TARGET_X86_64
3146
    case MSR_LSTAR:
3147
        val = env->lstar;
3148
        break;
3149
    case MSR_CSTAR:
3150
        val = env->cstar;
3151
        break;
3152
    case MSR_FMASK:
3153
        val = env->fmask;
3154
        break;
3155
    case MSR_FSBASE:
3156
        val = env->segs[R_FS].base;
3157
        break;
3158
    case MSR_GSBASE:
3159
        val = env->segs[R_GS].base;
3160
        break;
3161
    case MSR_KERNELGSBASE:
3162
        val = env->kernelgsbase;
3163
        break;
3164
#endif
3165
#ifdef USE_KQEMU
3166
    case MSR_QPI_COMMBASE:
3167
        if (env->kqemu_enabled) {
3168
            val = kqemu_comm_base;
3169
        } else {
3170
            val = 0;
3171
        }
3172
        break;
3173
#endif
3174
    default:
3175
        /* XXX: exception ? */
3176
        val = 0;
3177
        break;
3178
    }
3179
    EAX = (uint32_t)(val);
3180
    EDX = (uint32_t)(val >> 32);
3181
}
3182
#endif
3183

    
3184
target_ulong helper_lsl(target_ulong selector1)
3185
{
3186
    unsigned int limit;
3187
    uint32_t e1, e2, eflags, selector;
3188
    int rpl, dpl, cpl, type;
3189

    
3190
    selector = selector1 & 0xffff;
3191
    eflags = cc_table[CC_OP].compute_all();
3192
    if (load_segment(&e1, &e2, selector) != 0)
3193
        goto fail;
3194
    rpl = selector & 3;
3195
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3196
    cpl = env->hflags & HF_CPL_MASK;
3197
    if (e2 & DESC_S_MASK) {
3198
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3199
            /* conforming */
3200
        } else {
3201
            if (dpl < cpl || dpl < rpl)
3202
                goto fail;
3203
        }
3204
    } else {
3205
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3206
        switch(type) {
3207
        case 1:
3208
        case 2:
3209
        case 3:
3210
        case 9:
3211
        case 11:
3212
            break;
3213
        default:
3214
            goto fail;
3215
        }
3216
        if (dpl < cpl || dpl < rpl) {
3217
        fail:
3218
            CC_SRC = eflags & ~CC_Z;
3219
            return 0;
3220
        }
3221
    }
3222
    limit = get_seg_limit(e1, e2);
3223
    CC_SRC = eflags | CC_Z;
3224
    return limit;
3225
}
3226

    
3227
target_ulong helper_lar(target_ulong selector1)
3228
{
3229
    uint32_t e1, e2, eflags, selector;
3230
    int rpl, dpl, cpl, type;
3231

    
3232
    selector = selector1 & 0xffff;
3233
    eflags = cc_table[CC_OP].compute_all();
3234
    if ((selector & 0xfffc) == 0)
3235
        goto fail;
3236
    if (load_segment(&e1, &e2, selector) != 0)
3237
        goto fail;
3238
    rpl = selector & 3;
3239
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3240
    cpl = env->hflags & HF_CPL_MASK;
3241
    if (e2 & DESC_S_MASK) {
3242
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3243
            /* conforming */
3244
        } else {
3245
            if (dpl < cpl || dpl < rpl)
3246
                goto fail;
3247
        }
3248
    } else {
3249
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3250
        switch(type) {
3251
        case 1:
3252
        case 2:
3253
        case 3:
3254
        case 4:
3255
        case 5:
3256
        case 9:
3257
        case 11:
3258
        case 12:
3259
            break;
3260
        default:
3261
            goto fail;
3262
        }
3263
        if (dpl < cpl || dpl < rpl) {
3264
        fail:
3265
            CC_SRC = eflags & ~CC_Z;
3266
            return 0;
3267
        }
3268
    }
3269
    CC_SRC = eflags | CC_Z;
3270
    return e2 & 0x00f0ff00;
3271
}
3272

    
3273
void helper_verr(target_ulong selector1)
3274
{
3275
    uint32_t e1, e2, eflags, selector;
3276
    int rpl, dpl, cpl;
3277

    
3278
    selector = selector1 & 0xffff;
3279
    eflags = cc_table[CC_OP].compute_all();
3280
    if ((selector & 0xfffc) == 0)
3281
        goto fail;
3282
    if (load_segment(&e1, &e2, selector) != 0)
3283
        goto fail;
3284
    if (!(e2 & DESC_S_MASK))
3285
        goto fail;
3286
    rpl = selector & 3;
3287
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3288
    cpl = env->hflags & HF_CPL_MASK;
3289
    if (e2 & DESC_CS_MASK) {
3290
        if (!(e2 & DESC_R_MASK))
3291
            goto fail;
3292
        if (!(e2 & DESC_C_MASK)) {
3293
            if (dpl < cpl || dpl < rpl)
3294
                goto fail;
3295
        }
3296
    } else {
3297
        if (dpl < cpl || dpl < rpl) {
3298
        fail:
3299
            CC_SRC = eflags & ~CC_Z;
3300
            return;
3301
        }
3302
    }
3303
    CC_SRC = eflags | CC_Z;
3304
}
3305

    
3306
void helper_verw(target_ulong selector1)
3307
{
3308
    uint32_t e1, e2, eflags, selector;
3309
    int rpl, dpl, cpl;
3310

    
3311
    selector = selector1 & 0xffff;
3312
    eflags = cc_table[CC_OP].compute_all();
3313
    if ((selector & 0xfffc) == 0)
3314
        goto fail;
3315
    if (load_segment(&e1, &e2, selector) != 0)
3316
        goto fail;
3317
    if (!(e2 & DESC_S_MASK))
3318
        goto fail;
3319
    rpl = selector & 3;
3320
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3321
    cpl = env->hflags & HF_CPL_MASK;
3322
    if (e2 & DESC_CS_MASK) {
3323
        goto fail;
3324
    } else {
3325
        if (dpl < cpl || dpl < rpl)
3326
            goto fail;
3327
        if (!(e2 & DESC_W_MASK)) {
3328
        fail:
3329
            CC_SRC = eflags & ~CC_Z;
3330
            return;
3331
        }
3332
    }
3333
    CC_SRC = eflags | CC_Z;
3334
}
3335

    
3336
/* x87 FPU helpers */
3337

    
3338
static void fpu_set_exception(int mask)
3339
{
3340
    env->fpus |= mask;
3341
    if (env->fpus & (~env->fpuc & FPUC_EM))
3342
        env->fpus |= FPUS_SE | FPUS_B;
3343
}
3344

    
3345
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3346
{
3347
    if (b == 0.0)
3348
        fpu_set_exception(FPUS_ZE);
3349
    return a / b;
3350
}
3351

    
3352
void fpu_raise_exception(void)
3353
{
3354
    if (env->cr[0] & CR0_NE_MASK) {
3355
        raise_exception(EXCP10_COPR);
3356
    }
3357
#if !defined(CONFIG_USER_ONLY)
3358
    else {
3359
        cpu_set_ferr(env);
3360
    }
3361
#endif
3362
}
3363

    
3364
void helper_flds_FT0(uint32_t val)
3365
{
3366
    union {
3367
        float32 f;
3368
        uint32_t i;
3369
    } u;
3370
    u.i = val;
3371
    FT0 = float32_to_floatx(u.f, &env->fp_status);
3372
}
3373

    
3374
void helper_fldl_FT0(uint64_t val)
3375
{
3376
    union {
3377
        float64 f;
3378
        uint64_t i;
3379
    } u;
3380
    u.i = val;
3381
    FT0 = float64_to_floatx(u.f, &env->fp_status);
3382
}
3383

    
3384
void helper_fildl_FT0(int32_t val)
3385
{
3386
    FT0 = int32_to_floatx(val, &env->fp_status);
3387
}
3388

    
3389
void helper_flds_ST0(uint32_t val)
3390
{
3391
    int new_fpstt;
3392
    union {
3393
        float32 f;
3394
        uint32_t i;
3395
    } u;
3396
    new_fpstt = (env->fpstt - 1) & 7;
3397
    u.i = val;
3398
    env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3399
    env->fpstt = new_fpstt;
3400
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3401
}
3402

    
3403
void helper_fldl_ST0(uint64_t val)
3404
{
3405
    int new_fpstt;
3406
    union {
3407
        float64 f;
3408
        uint64_t i;
3409
    } u;
3410
    new_fpstt = (env->fpstt - 1) & 7;
3411
    u.i = val;
3412
    env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3413
    env->fpstt = new_fpstt;
3414
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3415
}
3416

    
3417
void helper_fildl_ST0(int32_t val)
3418
{
3419
    int new_fpstt;
3420
    new_fpstt = (env->fpstt - 1) & 7;
3421
    env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3422
    env->fpstt = new_fpstt;
3423
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3424
}
3425

    
3426
void helper_fildll_ST0(int64_t val)
3427
{
3428
    int new_fpstt;
3429
    new_fpstt = (env->fpstt - 1) & 7;
3430
    env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3431
    env->fpstt = new_fpstt;
3432
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3433
}
3434

    
3435
uint32_t helper_fsts_ST0(void)
3436
{
3437
    union {
3438
        float32 f;
3439
        uint32_t i;
3440
    } u;
3441
    u.f = floatx_to_float32(ST0, &env->fp_status);
3442
    return u.i;
3443
}
3444

    
3445
uint64_t helper_fstl_ST0(void)
3446
{
3447
    union {
3448
        float64 f;
3449
        uint64_t i;
3450
    } u;
3451
    u.f = floatx_to_float64(ST0, &env->fp_status);
3452
    return u.i;
3453
}
3454

    
3455
int32_t helper_fist_ST0(void)
3456
{
3457
    int32_t val;
3458
    val = floatx_to_int32(ST0, &env->fp_status);
3459
    if (val != (int16_t)val)
3460
        val = -32768;
3461
    return val;
3462
}
3463

    
3464
int32_t helper_fistl_ST0(void)
3465
{
3466
    int32_t val;
3467
    val = floatx_to_int32(ST0, &env->fp_status);
3468
    return val;
3469
}
3470

    
3471
int64_t helper_fistll_ST0(void)
3472
{
3473
    int64_t val;
3474
    val = floatx_to_int64(ST0, &env->fp_status);
3475
    return val;
3476
}
3477

    
3478
int32_t helper_fistt_ST0(void)
3479
{
3480
    int32_t val;
3481
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3482
    if (val != (int16_t)val)
3483
        val = -32768;
3484
    return val;
3485
}
3486

    
3487
int32_t helper_fisttl_ST0(void)
3488
{
3489
    int32_t val;
3490
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3491
    return val;
3492
}
3493

    
3494
int64_t helper_fisttll_ST0(void)
3495
{
3496
    int64_t val;
3497
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3498
    return val;
3499
}
3500

    
3501
void helper_fldt_ST0(target_ulong ptr)
3502
{
3503
    int new_fpstt;
3504
    new_fpstt = (env->fpstt - 1) & 7;
3505
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3506
    env->fpstt = new_fpstt;
3507
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3508
}
3509

    
3510
void helper_fstt_ST0(target_ulong ptr)
3511
{
3512
    helper_fstt(ST0, ptr);
3513
}
3514

    
3515
void helper_fpush(void)
3516
{
3517
    fpush();
3518
}
3519

    
3520
void helper_fpop(void)
3521
{
3522
    fpop();
3523
}
3524

    
3525
void helper_fdecstp(void)
3526
{
3527
    env->fpstt = (env->fpstt - 1) & 7;
3528
    env->fpus &= (~0x4700);
3529
}
3530

    
3531
void helper_fincstp(void)
3532
{
3533
    env->fpstt = (env->fpstt + 1) & 7;
3534
    env->fpus &= (~0x4700);
3535
}
3536

    
3537
/* FPU move */
3538

    
3539
void helper_ffree_STN(int st_index)
3540
{
3541
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3542
}
3543

    
3544
void helper_fmov_ST0_FT0(void)
3545
{
3546
    ST0 = FT0;
3547
}
3548

    
3549
void helper_fmov_FT0_STN(int st_index)
3550
{
3551
    FT0 = ST(st_index);
3552
}
3553

    
3554
void helper_fmov_ST0_STN(int st_index)
3555
{
3556
    ST0 = ST(st_index);
3557
}
3558

    
3559
void helper_fmov_STN_ST0(int st_index)
3560
{
3561
    ST(st_index) = ST0;
3562
}
3563

    
3564
void helper_fxchg_ST0_STN(int st_index)
3565
{
3566
    CPU86_LDouble tmp;
3567
    tmp = ST(st_index);
3568
    ST(st_index) = ST0;
3569
    ST0 = tmp;
3570
}
3571

    
3572
/* FPU operations */
3573

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

    
3576
void helper_fcom_ST0_FT0(void)
3577
{
3578
    int ret;
3579

    
3580
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3581
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3582
    FORCE_RET();
3583
}
3584

    
3585
void helper_fucom_ST0_FT0(void)
3586
{
3587
    int ret;
3588

    
3589
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3590
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3591
    FORCE_RET();
3592
}
3593

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

    
3596
void helper_fcomi_ST0_FT0(void)
3597
{
3598
    int eflags;
3599
    int ret;
3600

    
3601
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3602
    eflags = cc_table[CC_OP].compute_all();
3603
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3604
    CC_SRC = eflags;
3605
    FORCE_RET();
3606
}
3607

    
3608
void helper_fucomi_ST0_FT0(void)
3609
{
3610
    int eflags;
3611
    int ret;
3612

    
3613
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3614
    eflags = cc_table[CC_OP].compute_all();
3615
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3616
    CC_SRC = eflags;
3617
    FORCE_RET();
3618
}
3619

    
3620
void helper_fadd_ST0_FT0(void)
3621
{
3622
    ST0 += FT0;
3623
}
3624

    
3625
void helper_fmul_ST0_FT0(void)
3626
{
3627
    ST0 *= FT0;
3628
}
3629

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

    
3635
void helper_fsubr_ST0_FT0(void)
3636
{
3637
    ST0 = FT0 - ST0;
3638
}
3639

    
3640
void helper_fdiv_ST0_FT0(void)
3641
{
3642
    ST0 = helper_fdiv(ST0, FT0);
3643
}
3644

    
3645
void helper_fdivr_ST0_FT0(void)
3646
{
3647
    ST0 = helper_fdiv(FT0, ST0);
3648
}
3649

    
3650
/* fp operations between STN and ST0 */
3651

    
3652
void helper_fadd_STN_ST0(int st_index)
3653
{
3654
    ST(st_index) += ST0;
3655
}
3656

    
3657
void helper_fmul_STN_ST0(int st_index)
3658
{
3659
    ST(st_index) *= ST0;
3660
}
3661

    
3662
void helper_fsub_STN_ST0(int st_index)
3663
{
3664
    ST(st_index) -= ST0;
3665
}
3666

    
3667
void helper_fsubr_STN_ST0(int st_index)
3668
{
3669
    CPU86_LDouble *p;
3670
    p = &ST(st_index);
3671
    *p = ST0 - *p;
3672
}
3673

    
3674
void helper_fdiv_STN_ST0(int st_index)
3675
{
3676
    CPU86_LDouble *p;
3677
    p = &ST(st_index);
3678
    *p = helper_fdiv(*p, ST0);
3679
}
3680

    
3681
void helper_fdivr_STN_ST0(int st_index)
3682
{
3683
    CPU86_LDouble *p;
3684
    p = &ST(st_index);
3685
    *p = helper_fdiv(ST0, *p);
3686
}
3687

    
3688
/* misc FPU operations */
3689
void helper_fchs_ST0(void)
3690
{
3691
    ST0 = floatx_chs(ST0);
3692
}
3693

    
3694
void helper_fabs_ST0(void)
3695
{
3696
    ST0 = floatx_abs(ST0);
3697
}
3698

    
3699
void helper_fld1_ST0(void)
3700
{
3701
    ST0 = f15rk[1];
3702
}
3703

    
3704
void helper_fldl2t_ST0(void)
3705
{
3706
    ST0 = f15rk[6];
3707
}
3708

    
3709
void helper_fldl2e_ST0(void)
3710
{
3711
    ST0 = f15rk[5];
3712
}
3713

    
3714
void helper_fldpi_ST0(void)
3715
{
3716
    ST0 = f15rk[2];
3717
}
3718

    
3719
void helper_fldlg2_ST0(void)
3720
{
3721
    ST0 = f15rk[3];
3722
}
3723

    
3724
void helper_fldln2_ST0(void)
3725
{
3726
    ST0 = f15rk[4];
3727
}
3728

    
3729
void helper_fldz_ST0(void)
3730
{
3731
    ST0 = f15rk[0];
3732
}
3733

    
3734
void helper_fldz_FT0(void)
3735
{
3736
    FT0 = f15rk[0];
3737
}
3738

    
3739
uint32_t helper_fnstsw(void)
3740
{
3741
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3742
}
3743

    
3744
uint32_t helper_fnstcw(void)
3745
{
3746
    return env->fpuc;
3747
}
3748

    
3749
static void update_fp_status(void)
3750
{
3751
    int rnd_type;
3752

    
3753
    /* set rounding mode */
3754
    switch(env->fpuc & RC_MASK) {
3755
    default:
3756
    case RC_NEAR:
3757
        rnd_type = float_round_nearest_even;
3758
        break;
3759
    case RC_DOWN:
3760
        rnd_type = float_round_down;
3761
        break;
3762
    case RC_UP:
3763
        rnd_type = float_round_up;
3764
        break;
3765
    case RC_CHOP:
3766
        rnd_type = float_round_to_zero;
3767
        break;
3768
    }
3769
    set_float_rounding_mode(rnd_type, &env->fp_status);
3770
#ifdef FLOATX80
3771
    switch((env->fpuc >> 8) & 3) {
3772
    case 0:
3773
        rnd_type = 32;
3774
        break;
3775
    case 2:
3776
        rnd_type = 64;
3777
        break;
3778
    case 3:
3779
    default:
3780
        rnd_type = 80;
3781
        break;
3782
    }
3783
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3784
#endif
3785
}
3786

    
3787
void helper_fldcw(uint32_t val)
3788
{
3789
    env->fpuc = val;
3790
    update_fp_status();
3791
}
3792

    
3793
void helper_fclex(void)
3794
{
3795
    env->fpus &= 0x7f00;
3796
}
3797

    
3798
void helper_fwait(void)
3799
{
3800
    if (env->fpus & FPUS_SE)
3801
        fpu_raise_exception();
3802
    FORCE_RET();
3803
}
3804

    
3805
void helper_fninit(void)
3806
{
3807
    env->fpus = 0;
3808
    env->fpstt = 0;
3809
    env->fpuc = 0x37f;
3810
    env->fptags[0] = 1;
3811
    env->fptags[1] = 1;
3812
    env->fptags[2] = 1;
3813
    env->fptags[3] = 1;
3814
    env->fptags[4] = 1;
3815
    env->fptags[5] = 1;
3816
    env->fptags[6] = 1;
3817
    env->fptags[7] = 1;
3818
}
3819

    
3820
/* BCD ops */
3821

    
3822
void helper_fbld_ST0(target_ulong ptr)
3823
{
3824
    CPU86_LDouble tmp;
3825
    uint64_t val;
3826
    unsigned int v;
3827
    int i;
3828

    
3829
    val = 0;
3830
    for(i = 8; i >= 0; i--) {
3831
        v = ldub(ptr + i);
3832
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3833
    }
3834
    tmp = val;
3835
    if (ldub(ptr + 9) & 0x80)
3836
        tmp = -tmp;
3837
    fpush();
3838
    ST0 = tmp;
3839
}
3840

    
3841
void helper_fbst_ST0(target_ulong ptr)
3842
{
3843
    int v;
3844
    target_ulong mem_ref, mem_end;
3845
    int64_t val;
3846

    
3847
    val = floatx_to_int64(ST0, &env->fp_status);
3848
    mem_ref = ptr;
3849
    mem_end = mem_ref + 9;
3850
    if (val < 0) {
3851
        stb(mem_end, 0x80);
3852
        val = -val;
3853
    } else {
3854
        stb(mem_end, 0x00);
3855
    }
3856
    while (mem_ref < mem_end) {
3857
        if (val == 0)
3858
            break;
3859
        v = val % 100;
3860
        val = val / 100;
3861
        v = ((v / 10) << 4) | (v % 10);
3862
        stb(mem_ref++, v);
3863
    }
3864
    while (mem_ref < mem_end) {
3865
        stb(mem_ref++, 0);
3866
    }
3867
}
3868

    
3869
void helper_f2xm1(void)
3870
{
3871
    ST0 = pow(2.0,ST0) - 1.0;
3872
}
3873

    
3874
void helper_fyl2x(void)
3875
{
3876
    CPU86_LDouble fptemp;
3877

    
3878
    fptemp = ST0;
3879
    if (fptemp>0.0){
3880
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
3881
        ST1 *= fptemp;
3882
        fpop();
3883
    } else {
3884
        env->fpus &= (~0x4700);
3885
        env->fpus |= 0x400;
3886
    }
3887
}
3888

    
3889
void helper_fptan(void)
3890
{
3891
    CPU86_LDouble fptemp;
3892

    
3893
    fptemp = ST0;
3894
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3895
        env->fpus |= 0x400;
3896
    } else {
3897
        ST0 = tan(fptemp);
3898
        fpush();
3899
        ST0 = 1.0;
3900
        env->fpus &= (~0x400);  /* C2 <-- 0 */
3901
        /* the above code is for  |arg| < 2**52 only */
3902
    }
3903
}
3904

    
3905
void helper_fpatan(void)
3906
{
3907
    CPU86_LDouble fptemp, fpsrcop;
3908

    
3909
    fpsrcop = ST1;
3910
    fptemp = ST0;
3911
    ST1 = atan2(fpsrcop,fptemp);
3912
    fpop();
3913
}
3914

    
3915
void helper_fxtract(void)
3916
{
3917
    CPU86_LDoubleU temp;
3918
    unsigned int expdif;
3919

    
3920
    temp.d = ST0;
3921
    expdif = EXPD(temp) - EXPBIAS;
3922
    /*DP exponent bias*/
3923
    ST0 = expdif;
3924
    fpush();
3925
    BIASEXPONENT(temp);
3926
    ST0 = temp.d;
3927
}
3928

    
3929
void helper_fprem1(void)
3930
{
3931
    CPU86_LDouble dblq, fpsrcop, fptemp;
3932
    CPU86_LDoubleU fpsrcop1, fptemp1;
3933
    int expdif;
3934
    signed long long int q;
3935

    
3936
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3937
        ST0 = 0.0 / 0.0; /* NaN */
3938
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3939
        return;
3940
    }
3941

    
3942
    fpsrcop = ST0;
3943
    fptemp = ST1;
3944
    fpsrcop1.d = fpsrcop;
3945
    fptemp1.d = fptemp;
3946
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3947

    
3948
    if (expdif < 0) {
3949
        /* optimisation? taken from the AMD docs */
3950
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3951
        /* ST0 is unchanged */
3952
        return;
3953
    }
3954

    
3955
    if (expdif < 53) {
3956
        dblq = fpsrcop / fptemp;
3957
        /* round dblq towards nearest integer */
3958
        dblq = rint(dblq);
3959
        ST0 = fpsrcop - fptemp * dblq;
3960

    
3961
        /* convert dblq to q by truncating towards zero */
3962
        if (dblq < 0.0)
3963
           q = (signed long long int)(-dblq);
3964
        else
3965
           q = (signed long long int)dblq;
3966

    
3967
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3968
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
3969
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
3970
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
3971
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
3972
    } else {
3973
        env->fpus |= 0x400;  /* C2 <-- 1 */
3974
        fptemp = pow(2.0, expdif - 50);
3975
        fpsrcop = (ST0 / ST1) / fptemp;
3976
        /* fpsrcop = integer obtained by chopping */
3977
        fpsrcop = (fpsrcop < 0.0) ?
3978
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
3979
        ST0 -= (ST1 * fpsrcop * fptemp);
3980
    }
3981
}
3982

    
3983
void helper_fprem(void)
3984
{
3985
    CPU86_LDouble dblq, fpsrcop, fptemp;
3986
    CPU86_LDoubleU fpsrcop1, fptemp1;
3987
    int expdif;
3988
    signed long long int q;
3989

    
3990
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3991
       ST0 = 0.0 / 0.0; /* NaN */
3992
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3993
       return;
3994
    }
3995

    
3996
    fpsrcop = (CPU86_LDouble)ST0;
3997
    fptemp = (CPU86_LDouble)ST1;
3998
    fpsrcop1.d = fpsrcop;
3999
    fptemp1.d = fptemp;
4000
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4001

    
4002
    if (expdif < 0) {
4003
        /* optimisation? taken from the AMD docs */
4004
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4005
        /* ST0 is unchanged */
4006
        return;
4007
    }
4008

    
4009
    if ( expdif < 53 ) {
4010
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4011
        /* round dblq towards zero */
4012
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4013
        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
4014

    
4015
        /* convert dblq to q by truncating towards zero */
4016
        if (dblq < 0.0)
4017
           q = (signed long long int)(-dblq);
4018
        else
4019
           q = (signed long long int)dblq;
4020

    
4021
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4022
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4023
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4024
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4025
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4026
    } else {
4027
        int N = 32 + (expdif % 32); /* as per AMD docs */
4028
        env->fpus |= 0x400;  /* C2 <-- 1 */
4029
        fptemp = pow(2.0, (double)(expdif - N));
4030
        fpsrcop = (ST0 / ST1) / fptemp;
4031
        /* fpsrcop = integer obtained by chopping */
4032
        fpsrcop = (fpsrcop < 0.0) ?
4033
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4034
        ST0 -= (ST1 * fpsrcop * fptemp);
4035
    }
4036
}
4037

    
4038
void helper_fyl2xp1(void)
4039
{
4040
    CPU86_LDouble fptemp;
4041

    
4042
    fptemp = ST0;
4043
    if ((fptemp+1.0)>0.0) {
4044
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4045
        ST1 *= fptemp;
4046
        fpop();
4047
    } else {
4048
        env->fpus &= (~0x4700);
4049
        env->fpus |= 0x400;
4050
    }
4051
}
4052

    
4053
void helper_fsqrt(void)
4054
{
4055
    CPU86_LDouble fptemp;
4056

    
4057
    fptemp = ST0;
4058
    if (fptemp<0.0) {
4059
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4060
        env->fpus |= 0x400;
4061
    }
4062
    ST0 = sqrt(fptemp);
4063
}
4064

    
4065
void helper_fsincos(void)
4066
{
4067
    CPU86_LDouble fptemp;
4068

    
4069
    fptemp = ST0;
4070
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4071
        env->fpus |= 0x400;
4072
    } else {
4073
        ST0 = sin(fptemp);
4074
        fpush();
4075
        ST0 = cos(fptemp);
4076
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4077
        /* the above code is for  |arg| < 2**63 only */
4078
    }
4079
}
4080

    
4081
void helper_frndint(void)
4082
{
4083
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4084
}
4085

    
4086
void helper_fscale(void)
4087
{
4088
    ST0 = ldexp (ST0, (int)(ST1));
4089
}
4090

    
4091
void helper_fsin(void)
4092
{
4093
    CPU86_LDouble fptemp;
4094

    
4095
    fptemp = ST0;
4096
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4097
        env->fpus |= 0x400;
4098
    } else {
4099
        ST0 = sin(fptemp);
4100
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4101
        /* the above code is for  |arg| < 2**53 only */
4102
    }
4103
}
4104

    
4105
void helper_fcos(void)
4106
{
4107
    CPU86_LDouble fptemp;
4108

    
4109
    fptemp = ST0;
4110
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4111
        env->fpus |= 0x400;
4112
    } else {
4113
        ST0 = cos(fptemp);
4114
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4115
        /* the above code is for  |arg5 < 2**63 only */
4116
    }
4117
}
4118

    
4119
void helper_fxam_ST0(void)
4120
{
4121
    CPU86_LDoubleU temp;
4122
    int expdif;
4123

    
4124
    temp.d = ST0;
4125

    
4126
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4127
    if (SIGND(temp))
4128
        env->fpus |= 0x200; /* C1 <-- 1 */
4129

    
4130
    /* XXX: test fptags too */
4131
    expdif = EXPD(temp);
4132
    if (expdif == MAXEXPD) {
4133
#ifdef USE_X86LDOUBLE
4134
        if (MANTD(temp) == 0x8000000000000000ULL)
4135
#else
4136
        if (MANTD(temp) == 0)
4137
#endif
4138
            env->fpus |=  0x500 /*Infinity*/;
4139
        else
4140
            env->fpus |=  0x100 /*NaN*/;
4141
    } else if (expdif == 0) {
4142
        if (MANTD(temp) == 0)
4143
            env->fpus |=  0x4000 /*Zero*/;
4144
        else
4145
            env->fpus |= 0x4400 /*Denormal*/;
4146
    } else {
4147
        env->fpus |= 0x400;
4148
    }
4149
}
4150

    
4151
void helper_fstenv(target_ulong ptr, int data32)
4152
{
4153
    int fpus, fptag, exp, i;
4154
    uint64_t mant;
4155
    CPU86_LDoubleU tmp;
4156

    
4157
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4158
    fptag = 0;
4159
    for (i=7; i>=0; i--) {
4160
        fptag <<= 2;
4161
        if (env->fptags[i]) {
4162
            fptag |= 3;
4163
        } else {
4164
            tmp.d = env->fpregs[i].d;
4165
            exp = EXPD(tmp);
4166
            mant = MANTD(tmp);
4167
            if (exp == 0 && mant == 0) {
4168
                /* zero */
4169
                fptag |= 1;
4170
            } else if (exp == 0 || exp == MAXEXPD
4171
#ifdef USE_X86LDOUBLE
4172
                       || (mant & (1LL << 63)) == 0
4173
#endif
4174
                       ) {
4175
                /* NaNs, infinity, denormal */
4176
                fptag |= 2;
4177
            }
4178
        }
4179
    }
4180
    if (data32) {
4181
        /* 32 bit */
4182
        stl(ptr, env->fpuc);
4183
        stl(ptr + 4, fpus);
4184
        stl(ptr + 8, fptag);
4185
        stl(ptr + 12, 0); /* fpip */
4186
        stl(ptr + 16, 0); /* fpcs */
4187
        stl(ptr + 20, 0); /* fpoo */
4188
        stl(ptr + 24, 0); /* fpos */
4189
    } else {
4190
        /* 16 bit */
4191
        stw(ptr, env->fpuc);
4192
        stw(ptr + 2, fpus);
4193
        stw(ptr + 4, fptag);
4194
        stw(ptr + 6, 0);
4195
        stw(ptr + 8, 0);
4196
        stw(ptr + 10, 0);
4197
        stw(ptr + 12, 0);
4198
    }
4199
}
4200

    
4201
void helper_fldenv(target_ulong ptr, int data32)
4202
{
4203
    int i, fpus, fptag;
4204

    
4205
    if (data32) {
4206
        env->fpuc = lduw(ptr);
4207
        fpus = lduw(ptr + 4);
4208
        fptag = lduw(ptr + 8);
4209
    }
4210
    else {
4211
        env->fpuc = lduw(ptr);
4212
        fpus = lduw(ptr + 2);
4213
        fptag = lduw(ptr + 4);
4214
    }
4215
    env->fpstt = (fpus >> 11) & 7;
4216
    env->fpus = fpus & ~0x3800;
4217
    for(i = 0;i < 8; i++) {
4218
        env->fptags[i] = ((fptag & 3) == 3);
4219
        fptag >>= 2;
4220
    }
4221
}
4222

    
4223
void helper_fsave(target_ulong ptr, int data32)
4224
{
4225
    CPU86_LDouble tmp;
4226
    int i;
4227

    
4228
    helper_fstenv(ptr, data32);
4229

    
4230
    ptr += (14 << data32);
4231
    for(i = 0;i < 8; i++) {
4232
        tmp = ST(i);
4233
        helper_fstt(tmp, ptr);
4234
        ptr += 10;
4235
    }
4236

    
4237
    /* fninit */
4238
    env->fpus = 0;
4239
    env->fpstt = 0;
4240
    env->fpuc = 0x37f;
4241
    env->fptags[0] = 1;
4242
    env->fptags[1] = 1;
4243
    env->fptags[2] = 1;
4244
    env->fptags[3] = 1;
4245
    env->fptags[4] = 1;
4246
    env->fptags[5] = 1;
4247
    env->fptags[6] = 1;
4248
    env->fptags[7] = 1;
4249
}
4250

    
4251
void helper_frstor(target_ulong ptr, int data32)
4252
{
4253
    CPU86_LDouble tmp;
4254
    int i;
4255

    
4256
    helper_fldenv(ptr, data32);
4257
    ptr += (14 << data32);
4258

    
4259
    for(i = 0;i < 8; i++) {
4260
        tmp = helper_fldt(ptr);
4261
        ST(i) = tmp;
4262
        ptr += 10;
4263
    }
4264
}
4265

    
4266
void helper_fxsave(target_ulong ptr, int data64)
4267
{
4268
    int fpus, fptag, i, nb_xmm_regs;
4269
    CPU86_LDouble tmp;
4270
    target_ulong addr;
4271

    
4272
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4273
    fptag = 0;
4274
    for(i = 0; i < 8; i++) {
4275
        fptag |= (env->fptags[i] << i);
4276
    }
4277
    stw(ptr, env->fpuc);
4278
    stw(ptr + 2, fpus);
4279
    stw(ptr + 4, fptag ^ 0xff);
4280
#ifdef TARGET_X86_64
4281
    if (data64) {
4282
        stq(ptr + 0x08, 0); /* rip */
4283
        stq(ptr + 0x10, 0); /* rdp */
4284
    } else 
4285
#endif
4286
    {
4287
        stl(ptr + 0x08, 0); /* eip */
4288
        stl(ptr + 0x0c, 0); /* sel  */
4289
        stl(ptr + 0x10, 0); /* dp */
4290
        stl(ptr + 0x14, 0); /* sel  */
4291
    }
4292

    
4293
    addr = ptr + 0x20;
4294
    for(i = 0;i < 8; i++) {
4295
        tmp = ST(i);
4296
        helper_fstt(tmp, addr);
4297
        addr += 16;
4298
    }
4299

    
4300
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4301
        /* XXX: finish it */
4302
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4303
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4304
        if (env->hflags & HF_CS64_MASK)
4305
            nb_xmm_regs = 16;
4306
        else
4307
            nb_xmm_regs = 8;
4308
        addr = ptr + 0xa0;
4309
        for(i = 0; i < nb_xmm_regs; i++) {
4310
            stq(addr, env->xmm_regs[i].XMM_Q(0));
4311
            stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4312
            addr += 16;
4313
        }
4314
    }
4315
}
4316

    
4317
void helper_fxrstor(target_ulong ptr, int data64)
4318
{
4319
    int i, fpus, fptag, nb_xmm_regs;
4320
    CPU86_LDouble tmp;
4321
    target_ulong addr;
4322

    
4323
    env->fpuc = lduw(ptr);
4324
    fpus = lduw(ptr + 2);
4325
    fptag = lduw(ptr + 4);
4326
    env->fpstt = (fpus >> 11) & 7;
4327
    env->fpus = fpus & ~0x3800;
4328
    fptag ^= 0xff;
4329
    for(i = 0;i < 8; i++) {
4330
        env->fptags[i] = ((fptag >> i) & 1);
4331
    }
4332

    
4333
    addr = ptr + 0x20;
4334
    for(i = 0;i < 8; i++) {
4335
        tmp = helper_fldt(addr);
4336
        ST(i) = tmp;
4337
        addr += 16;
4338
    }
4339

    
4340
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4341
        /* XXX: finish it */
4342
        env->mxcsr = ldl(ptr + 0x18);
4343
        //ldl(ptr + 0x1c);
4344
        if (env->hflags & HF_CS64_MASK)
4345
            nb_xmm_regs = 16;
4346
        else
4347
            nb_xmm_regs = 8;
4348
        addr = ptr + 0xa0;
4349
        for(i = 0; i < nb_xmm_regs; i++) {
4350
            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4351
            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4352
            addr += 16;
4353
        }
4354
    }
4355
}
4356

    
4357
#ifndef USE_X86LDOUBLE
4358

    
4359
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4360
{
4361
    CPU86_LDoubleU temp;
4362
    int e;
4363

    
4364
    temp.d = f;
4365
    /* mantissa */
4366
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4367
    /* exponent + sign */
4368
    e = EXPD(temp) - EXPBIAS + 16383;
4369
    e |= SIGND(temp) >> 16;
4370
    *pexp = e;
4371
}
4372

    
4373
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4374
{
4375
    CPU86_LDoubleU temp;
4376
    int e;
4377
    uint64_t ll;
4378

    
4379
    /* XXX: handle overflow ? */
4380
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4381
    e |= (upper >> 4) & 0x800; /* sign */
4382
    ll = (mant >> 11) & ((1LL << 52) - 1);
4383
#ifdef __arm__
4384
    temp.l.upper = (e << 20) | (ll >> 32);
4385
    temp.l.lower = ll;
4386
#else
4387
    temp.ll = ll | ((uint64_t)e << 52);
4388
#endif
4389
    return temp.d;
4390
}
4391

    
4392
#else
4393

    
4394
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4395
{
4396
    CPU86_LDoubleU temp;
4397

    
4398
    temp.d = f;
4399
    *pmant = temp.l.lower;
4400
    *pexp = temp.l.upper;
4401
}
4402

    
4403
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4404
{
4405
    CPU86_LDoubleU temp;
4406

    
4407
    temp.l.upper = upper;
4408
    temp.l.lower = mant;
4409
    return temp.d;
4410
}
4411
#endif
4412

    
4413
#ifdef TARGET_X86_64
4414

    
4415
//#define DEBUG_MULDIV
4416

    
4417
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4418
{
4419
    *plow += a;
4420
    /* carry test */
4421
    if (*plow < a)
4422
        (*phigh)++;
4423
    *phigh += b;
4424
}
4425

    
4426
static void neg128(uint64_t *plow, uint64_t *phigh)
4427
{
4428
    *plow = ~ *plow;
4429
    *phigh = ~ *phigh;
4430
    add128(plow, phigh, 1, 0);
4431
}
4432

    
4433
/* return TRUE if overflow */
4434
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4435
{
4436
    uint64_t q, r, a1, a0;
4437
    int i, qb, ab;
4438

    
4439
    a0 = *plow;
4440
    a1 = *phigh;
4441
    if (a1 == 0) {
4442
        q = a0 / b;
4443
        r = a0 % b;
4444
        *plow = q;
4445
        *phigh = r;
4446
    } else {
4447
        if (a1 >= b)
4448
            return 1;
4449
        /* XXX: use a better algorithm */
4450
        for(i = 0; i < 64; i++) {
4451
            ab = a1 >> 63;
4452
            a1 = (a1 << 1) | (a0 >> 63);
4453
            if (ab || a1 >= b) {
4454
                a1 -= b;
4455
                qb = 1;
4456
            } else {
4457
                qb = 0;
4458
            }
4459
            a0 = (a0 << 1) | qb;
4460
        }
4461
#if defined(DEBUG_MULDIV)
4462
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4463
               *phigh, *plow, b, a0, a1);
4464
#endif
4465
        *plow = a0;
4466
        *phigh = a1;
4467
    }
4468
    return 0;
4469
}
4470

    
4471
/* return TRUE if overflow */
4472
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4473
{
4474
    int sa, sb;
4475
    sa = ((int64_t)*phigh < 0);
4476
    if (sa)
4477
        neg128(plow, phigh);
4478
    sb = (b < 0);
4479
    if (sb)
4480
        b = -b;
4481
    if (div64(plow, phigh, b) != 0)
4482
        return 1;
4483
    if (sa ^ sb) {
4484
        if (*plow > (1ULL << 63))
4485
            return 1;
4486
        *plow = - *plow;
4487
    } else {
4488
        if (*plow >= (1ULL << 63))
4489
            return 1;
4490
    }
4491
    if (sa)
4492
        *phigh = - *phigh;
4493
    return 0;
4494
}
4495

    
4496
void helper_mulq_EAX_T0(target_ulong t0)
4497
{
4498
    uint64_t r0, r1;
4499

    
4500
    mulu64(&r0, &r1, EAX, t0);
4501
    EAX = r0;
4502
    EDX = r1;
4503
    CC_DST = r0;
4504
    CC_SRC = r1;
4505
}
4506

    
4507
void helper_imulq_EAX_T0(target_ulong t0)
4508
{
4509
    uint64_t r0, r1;
4510

    
4511
    muls64(&r0, &r1, EAX, t0);
4512
    EAX = r0;
4513
    EDX = r1;
4514
    CC_DST = r0;
4515
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4516
}
4517

    
4518
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4519
{
4520
    uint64_t r0, r1;
4521

    
4522
    muls64(&r0, &r1, t0, t1);
4523
    CC_DST = r0;
4524
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4525
    return r0;
4526
}
4527

    
4528
void helper_divq_EAX(target_ulong t0)
4529
{
4530
    uint64_t r0, r1;
4531
    if (t0 == 0) {
4532
        raise_exception(EXCP00_DIVZ);
4533
    }
4534
    r0 = EAX;
4535
    r1 = EDX;
4536
    if (div64(&r0, &r1, t0))
4537
        raise_exception(EXCP00_DIVZ);
4538
    EAX = r0;
4539
    EDX = r1;
4540
}
4541

    
4542
void helper_idivq_EAX(target_ulong t0)
4543
{
4544
    uint64_t r0, r1;
4545
    if (t0 == 0) {
4546
        raise_exception(EXCP00_DIVZ);
4547
    }
4548
    r0 = EAX;
4549
    r1 = EDX;
4550
    if (idiv64(&r0, &r1, t0))
4551
        raise_exception(EXCP00_DIVZ);
4552
    EAX = r0;
4553
    EDX = r1;
4554
}
4555
#endif
4556

    
4557
static void do_hlt(void)
4558
{
4559
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4560
    env->halted = 1;
4561
    env->exception_index = EXCP_HLT;
4562
    cpu_loop_exit();
4563
}
4564

    
4565
void helper_hlt(int next_eip_addend)
4566
{
4567
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4568
    EIP += next_eip_addend;
4569
    
4570
    do_hlt();
4571
}
4572

    
4573
void helper_monitor(target_ulong ptr)
4574
{
4575
    if ((uint32_t)ECX != 0)
4576
        raise_exception(EXCP0D_GPF);
4577
    /* XXX: store address ? */
4578
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4579
}
4580

    
4581
void helper_mwait(int next_eip_addend)
4582
{
4583
    if ((uint32_t)ECX != 0)
4584
        raise_exception(EXCP0D_GPF);
4585
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4586
    EIP += next_eip_addend;
4587

    
4588
    /* XXX: not complete but not completely erroneous */
4589
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4590
        /* more than one CPU: do not sleep because another CPU may
4591
           wake this one */
4592
    } else {
4593
        do_hlt();
4594
    }
4595
}
4596

    
4597
void helper_debug(void)
4598
{
4599
    env->exception_index = EXCP_DEBUG;
4600
    cpu_loop_exit();
4601
}
4602

    
4603
void helper_raise_interrupt(int intno, int next_eip_addend)
4604
{
4605
    raise_interrupt(intno, 1, 0, next_eip_addend);
4606
}
4607

    
4608
void helper_raise_exception(int exception_index)
4609
{
4610
    raise_exception(exception_index);
4611
}
4612

    
4613
void helper_cli(void)
4614
{
4615
    env->eflags &= ~IF_MASK;
4616
}
4617

    
4618
void helper_sti(void)
4619
{
4620
    env->eflags |= IF_MASK;
4621
}
4622

    
4623
#if 0
4624
/* vm86plus instructions */
4625
void helper_cli_vm(void)
4626
{
4627
    env->eflags &= ~VIF_MASK;
4628
}
4629

4630
void helper_sti_vm(void)
4631
{
4632
    env->eflags |= VIF_MASK;
4633
    if (env->eflags & VIP_MASK) {
4634
        raise_exception(EXCP0D_GPF);
4635
    }
4636
}
4637
#endif
4638

    
4639
void helper_set_inhibit_irq(void)
4640
{
4641
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4642
}
4643

    
4644
void helper_reset_inhibit_irq(void)
4645
{
4646
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4647
}
4648

    
4649
void helper_boundw(target_ulong a0, int v)
4650
{
4651
    int low, high;
4652
    low = ldsw(a0);
4653
    high = ldsw(a0 + 2);
4654
    v = (int16_t)v;
4655
    if (v < low || v > high) {
4656
        raise_exception(EXCP05_BOUND);
4657
    }
4658
    FORCE_RET();
4659
}
4660

    
4661
void helper_boundl(target_ulong a0, int v)
4662
{
4663
    int low, high;
4664
    low = ldl(a0);
4665
    high = ldl(a0 + 4);
4666
    if (v < low || v > high) {
4667
        raise_exception(EXCP05_BOUND);
4668
    }
4669
    FORCE_RET();
4670
}
4671

    
4672
static float approx_rsqrt(float a)
4673
{
4674
    return 1.0 / sqrt(a);
4675
}
4676

    
4677
static float approx_rcp(float a)
4678
{
4679
    return 1.0 / a;
4680
}
4681

    
4682
#if !defined(CONFIG_USER_ONLY)
4683

    
4684
#define MMUSUFFIX _mmu
4685

    
4686
#define SHIFT 0
4687
#include "softmmu_template.h"
4688

    
4689
#define SHIFT 1
4690
#include "softmmu_template.h"
4691

    
4692
#define SHIFT 2
4693
#include "softmmu_template.h"
4694

    
4695
#define SHIFT 3
4696
#include "softmmu_template.h"
4697

    
4698
#endif
4699

    
4700
/* try to fill the TLB and return an exception if error. If retaddr is
4701
   NULL, it means that the function was called in C code (i.e. not
4702
   from generated code or from helper.c) */
4703
/* XXX: fix it to restore all registers */
4704
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4705
{
4706
    TranslationBlock *tb;
4707
    int ret;
4708
    unsigned long pc;
4709
    CPUX86State *saved_env;
4710

    
4711
    /* XXX: hack to restore env in all cases, even if not called from
4712
       generated code */
4713
    saved_env = env;
4714
    env = cpu_single_env;
4715

    
4716
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4717
    if (ret) {
4718
        if (retaddr) {
4719
            /* now we have a real cpu fault */
4720
            pc = (unsigned long)retaddr;
4721
            tb = tb_find_pc(pc);
4722
            if (tb) {
4723
                /* the PC is inside the translated code. It means that we have
4724
                   a virtual CPU fault */
4725
                cpu_restore_state(tb, env, pc, NULL);
4726
            }
4727
        }
4728
        raise_exception_err(env->exception_index, env->error_code);
4729
    }
4730
    env = saved_env;
4731
}
4732

    
4733

    
4734
/* Secure Virtual Machine helpers */
4735

    
4736
#if defined(CONFIG_USER_ONLY)
4737

    
4738
void helper_vmrun(int aflag, int next_eip_addend)
4739
{ 
4740
}
4741
void helper_vmmcall(void) 
4742
{ 
4743
}
4744
void helper_vmload(int aflag)
4745
{ 
4746
}
4747
void helper_vmsave(int aflag)
4748
{ 
4749
}
4750
void helper_stgi(void)
4751
{
4752
}
4753
void helper_clgi(void)
4754
{
4755
}
4756
void helper_skinit(void) 
4757
{ 
4758
}
4759
void helper_invlpga(int aflag)
4760
{ 
4761
}
4762
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4763
{ 
4764
}
4765
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4766
{
4767
}
4768

    
4769
void helper_svm_check_io(uint32_t port, uint32_t param, 
4770
                         uint32_t next_eip_addend)
4771
{
4772
}
4773
#else
4774

    
4775
static inline void svm_save_seg(target_phys_addr_t addr,
4776
                                const SegmentCache *sc)
4777
{
4778
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4779
             sc->selector);
4780
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4781
             sc->base);
4782
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4783
             sc->limit);
4784
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4785
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4786
}
4787
                                
4788
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4789
{
4790
    unsigned int flags;
4791

    
4792
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4793
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4794
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4795
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4796
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4797
}
4798

    
4799
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4800
                                      CPUState *env, int seg_reg)
4801
{
4802
    SegmentCache sc1, *sc = &sc1;
4803
    svm_load_seg(addr, sc);
4804
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4805
                           sc->base, sc->limit, sc->flags);
4806
}
4807

    
4808
void helper_vmrun(int aflag, int next_eip_addend)
4809
{
4810
    target_ulong addr;
4811
    uint32_t event_inj;
4812
    uint32_t int_ctl;
4813

    
4814
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4815

    
4816
    if (aflag == 2)
4817
        addr = EAX;
4818
    else
4819
        addr = (uint32_t)EAX;
4820

    
4821
    if (loglevel & CPU_LOG_TB_IN_ASM)
4822
        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4823

    
4824
    env->vm_vmcb = addr;
4825

    
4826
    /* save the current CPU state in the hsave page */
4827
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4828
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4829

    
4830
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4831
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4832

    
4833
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4834
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4835
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4836
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4837
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4838
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4839

    
4840
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4841
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4842

    
4843
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4844
                  &env->segs[R_ES]);
4845
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4846
                 &env->segs[R_CS]);
4847
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4848
                 &env->segs[R_SS]);
4849
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4850
                 &env->segs[R_DS]);
4851

    
4852
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
4853
             EIP + next_eip_addend);
4854
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4855
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4856

    
4857
    /* load the interception bitmaps so we do not need to access the
4858
       vmcb in svm mode */
4859
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4860
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4861
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4862
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4863
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4864
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4865

    
4866
    /* enable intercepts */
4867
    env->hflags |= HF_SVMI_MASK;
4868

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

    
4871
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4872
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4873

    
4874
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4875
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4876

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

    
4880
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4881
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4882
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4883
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4884
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4885
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4886
    if (int_ctl & V_INTR_MASKING_MASK) {
4887
        env->v_tpr = int_ctl & V_TPR_MASK;
4888
        env->hflags2 |= HF2_VINTR_MASK;
4889
        if (env->eflags & IF_MASK)
4890
            env->hflags2 |= HF2_HIF_MASK;
4891
    }
4892

    
4893
    cpu_load_efer(env, 
4894
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4895
    env->eflags = 0;
4896
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4897
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4898
    CC_OP = CC_OP_EFLAGS;
4899

    
4900
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4901
                       env, R_ES);
4902
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4903
                       env, R_CS);
4904
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4905
                       env, R_SS);
4906
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4907
                       env, R_DS);
4908

    
4909
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4910
    env->eip = EIP;
4911
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4912
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4913
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4914
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4915
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4916

    
4917
    /* FIXME: guest state consistency checks */
4918

    
4919
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4920
        case TLB_CONTROL_DO_NOTHING:
4921
            break;
4922
        case TLB_CONTROL_FLUSH_ALL_ASID:
4923
            /* FIXME: this is not 100% correct but should work for now */
4924
            tlb_flush(env, 1);
4925
        break;
4926
    }
4927

    
4928
    env->hflags2 |= HF2_GIF_MASK;
4929

    
4930
    if (int_ctl & V_IRQ_MASK) {
4931
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4932
    }
4933

    
4934
    /* maybe we need to inject an event */
4935
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4936
    if (event_inj & SVM_EVTINJ_VALID) {
4937
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4938
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4939
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4940
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4941

    
4942
        if (loglevel & CPU_LOG_TB_IN_ASM)
4943
            fprintf(logfile, "Injecting(%#hx): ", valid_err);
4944
        /* FIXME: need to implement valid_err */
4945
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4946
        case SVM_EVTINJ_TYPE_INTR:
4947
                env->exception_index = vector;
4948
                env->error_code = event_inj_err;
4949
                env->exception_is_int = 0;
4950
                env->exception_next_eip = -1;
4951
                if (loglevel & CPU_LOG_TB_IN_ASM)
4952
                    fprintf(logfile, "INTR");
4953
                /* XXX: is it always correct ? */
4954
                do_interrupt(vector, 0, 0, 0, 1);
4955
                break;
4956
        case SVM_EVTINJ_TYPE_NMI:
4957
                env->exception_index = EXCP02_NMI;
4958
                env->error_code = event_inj_err;
4959
                env->exception_is_int = 0;
4960
                env->exception_next_eip = EIP;
4961
                if (loglevel & CPU_LOG_TB_IN_ASM)
4962
                    fprintf(logfile, "NMI");
4963
                cpu_loop_exit();
4964
                break;
4965
        case SVM_EVTINJ_TYPE_EXEPT:
4966
                env->exception_index = vector;
4967
                env->error_code = event_inj_err;
4968
                env->exception_is_int = 0;
4969
                env->exception_next_eip = -1;
4970
                if (loglevel & CPU_LOG_TB_IN_ASM)
4971
                    fprintf(logfile, "EXEPT");
4972
                cpu_loop_exit();
4973
                break;
4974
        case SVM_EVTINJ_TYPE_SOFT:
4975
                env->exception_index = vector;
4976
                env->error_code = event_inj_err;
4977
                env->exception_is_int = 1;
4978
                env->exception_next_eip = EIP;
4979
                if (loglevel & CPU_LOG_TB_IN_ASM)
4980
                    fprintf(logfile, "SOFT");
4981
                cpu_loop_exit();
4982
                break;
4983
        }
4984
        if (loglevel & CPU_LOG_TB_IN_ASM)
4985
            fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
4986
    }
4987
}
4988

    
4989
void helper_vmmcall(void)
4990
{
4991
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
4992
    raise_exception(EXCP06_ILLOP);
4993
}
4994

    
4995
void helper_vmload(int aflag)
4996
{
4997
    target_ulong addr;
4998
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
4999

    
5000
    if (aflag == 2)
5001
        addr = EAX;
5002
    else
5003
        addr = (uint32_t)EAX;
5004

    
5005
    if (loglevel & CPU_LOG_TB_IN_ASM)
5006
        fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5007
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5008
                env->segs[R_FS].base);
5009

    
5010
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
5011
                       env, R_FS);
5012
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
5013
                       env, R_GS);
5014
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
5015
                 &env->tr);
5016
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
5017
                 &env->ldt);
5018

    
5019
#ifdef TARGET_X86_64
5020
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
5021
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
5022
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
5023
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
5024
#endif
5025
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
5026
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
5027
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
5028
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
5029
}
5030

    
5031
void helper_vmsave(int aflag)
5032
{
5033
    target_ulong addr;
5034
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5035

    
5036
    if (aflag == 2)
5037
        addr = EAX;
5038
    else
5039
        addr = (uint32_t)EAX;
5040

    
5041
    if (loglevel & CPU_LOG_TB_IN_ASM)
5042
        fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5043
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5044
                env->segs[R_FS].base);
5045

    
5046
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5047
                 &env->segs[R_FS]);
5048
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5049
                 &env->segs[R_GS]);
5050
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5051
                 &env->tr);
5052
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5053
                 &env->ldt);
5054

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

    
5067
void helper_stgi(void)
5068
{
5069
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5070
    env->hflags2 |= HF2_GIF_MASK;
5071
}
5072

    
5073
void helper_clgi(void)
5074
{
5075
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5076
    env->hflags2 &= ~HF2_GIF_MASK;
5077
}
5078

    
5079
void helper_skinit(void)
5080
{
5081
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5082
    /* XXX: not implemented */
5083
    raise_exception(EXCP06_ILLOP);
5084
}
5085

    
5086
void helper_invlpga(int aflag)
5087
{
5088
    target_ulong addr;
5089
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5090
    
5091
    if (aflag == 2)
5092
        addr = EAX;
5093
    else
5094
        addr = (uint32_t)EAX;
5095

    
5096
    /* XXX: could use the ASID to see if it is needed to do the
5097
       flush */
5098
    tlb_flush_page(env, addr);
5099
}
5100

    
5101
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5102
{
5103
    if (likely(!(env->hflags & HF_SVMI_MASK)))
5104
        return;
5105
    switch(type) {
5106
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5107
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5108
            helper_vmexit(type, param);
5109
        }
5110
        break;
5111
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5112
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
5113
            helper_vmexit(type, param);
5114
        }
5115
        break;
5116
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
5117
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
5118
            helper_vmexit(type, param);
5119
        }
5120
        break;
5121
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
5122
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
5123
            helper_vmexit(type, param);
5124
        }
5125
        break;
5126
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
5127
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
5128
            helper_vmexit(type, param);
5129
        }
5130
        break;
5131
    case SVM_EXIT_MSR:
5132
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5133
            /* FIXME: this should be read in at vmrun (faster this way?) */
5134
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5135
            uint32_t t0, t1;
5136
            switch((uint32_t)ECX) {
5137
            case 0 ... 0x1fff:
5138
                t0 = (ECX * 2) % 8;
5139
                t1 = ECX / 8;
5140
                break;
5141
            case 0xc0000000 ... 0xc0001fff:
5142
                t0 = (8192 + ECX - 0xc0000000) * 2;
5143
                t1 = (t0 / 8);
5144
                t0 %= 8;
5145
                break;
5146
            case 0xc0010000 ... 0xc0011fff:
5147
                t0 = (16384 + ECX - 0xc0010000) * 2;
5148
                t1 = (t0 / 8);
5149
                t0 %= 8;
5150
                break;
5151
            default:
5152
                helper_vmexit(type, param);
5153
                t0 = 0;
5154
                t1 = 0;
5155
                break;
5156
            }
5157
            if (ldub_phys(addr + t1) & ((1 << param) << t0))
5158
                helper_vmexit(type, param);
5159
        }
5160
        break;
5161
    default:
5162
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5163
            helper_vmexit(type, param);
5164
        }
5165
        break;
5166
    }
5167
}
5168

    
5169
void helper_svm_check_io(uint32_t port, uint32_t param, 
5170
                         uint32_t next_eip_addend)
5171
{
5172
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5173
        /* FIXME: this should be read in at vmrun (faster this way?) */
5174
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5175
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5176
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5177
            /* next EIP */
5178
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5179
                     env->eip + next_eip_addend);
5180
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5181
        }
5182
    }
5183
}
5184

    
5185
/* Note: currently only 32 bits of exit_code are used */
5186
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5187
{
5188
    uint32_t int_ctl;
5189

    
5190
    if (loglevel & CPU_LOG_TB_IN_ASM)
5191
        fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5192
                exit_code, exit_info_1,
5193
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5194
                EIP);
5195

    
5196
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5197
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5198
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5199
    } else {
5200
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5201
    }
5202

    
5203
    /* Save the VM state in the vmcb */
5204
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5205
                 &env->segs[R_ES]);
5206
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5207
                 &env->segs[R_CS]);
5208
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5209
                 &env->segs[R_SS]);
5210
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5211
                 &env->segs[R_DS]);
5212

    
5213
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5214
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5215

    
5216
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5217
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5218

    
5219
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5220
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5221
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5222
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5223
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5224

    
5225
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5226
    int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
5227
    int_ctl |= env->v_tpr & V_TPR_MASK;
5228
    if (env->interrupt_request & CPU_INTERRUPT_VIRQ)
5229
        int_ctl |= V_IRQ_MASK;
5230
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5231

    
5232
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5233
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5234
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5235
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5236
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5237
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5238
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5239

    
5240
    /* Reload the host state from vm_hsave */
5241
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5242
    env->hflags &= ~HF_SVMI_MASK;
5243
    env->intercept = 0;
5244
    env->intercept_exceptions = 0;
5245
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5246
    env->tsc_offset = 0;
5247

    
5248
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5249
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5250

    
5251
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5252
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5253

    
5254
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5255
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5256
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5257
    /* we need to set the efer after the crs so the hidden flags get
5258
       set properly */
5259
    cpu_load_efer(env, 
5260
                  ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
5261
    env->eflags = 0;
5262
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5263
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5264
    CC_OP = CC_OP_EFLAGS;
5265

    
5266
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5267
                       env, R_ES);
5268
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5269
                       env, R_CS);
5270
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5271
                       env, R_SS);
5272
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5273
                       env, R_DS);
5274

    
5275
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5276
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5277
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5278

    
5279
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5280
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5281

    
5282
    /* other setups */
5283
    cpu_x86_set_cpl(env, 0);
5284
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5285
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5286

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

    
5290
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5291

    
5292
    /* Clears the TSC_OFFSET inside the processor. */
5293

    
5294
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5295
       from the page table indicated the host's CR3. If the PDPEs contain
5296
       illegal state, the processor causes a shutdown. */
5297

    
5298
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5299
    env->cr[0] |= CR0_PE_MASK;
5300
    env->eflags &= ~VM_MASK;
5301

    
5302
    /* Disables all breakpoints in the host DR7 register. */
5303

    
5304
    /* Checks the reloaded host state for consistency. */
5305

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

    
5310
    /* remove any pending exception */
5311
    env->exception_index = -1;
5312
    env->error_code = 0;
5313
    env->old_exception = -1;
5314

    
5315
    cpu_loop_exit();
5316
}
5317

    
5318
#endif
5319

    
5320
/* MMX/SSE */
5321
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5322
void helper_enter_mmx(void)
5323
{
5324
    env->fpstt = 0;
5325
    *(uint32_t *)(env->fptags) = 0;
5326
    *(uint32_t *)(env->fptags + 4) = 0;
5327
}
5328

    
5329
void helper_emms(void)
5330
{
5331
    /* set to empty state */
5332
    *(uint32_t *)(env->fptags) = 0x01010101;
5333
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5334
}
5335

    
5336
/* XXX: suppress */
5337
void helper_movq(uint64_t *d, uint64_t *s)
5338
{
5339
    *d = *s;
5340
}
5341

    
5342
#define SHIFT 0
5343
#include "ops_sse.h"
5344

    
5345
#define SHIFT 1
5346
#include "ops_sse.h"
5347

    
5348
#define SHIFT 0
5349
#include "helper_template.h"
5350
#undef SHIFT
5351

    
5352
#define SHIFT 1
5353
#include "helper_template.h"
5354
#undef SHIFT
5355

    
5356
#define SHIFT 2
5357
#include "helper_template.h"
5358
#undef SHIFT
5359

    
5360
#ifdef TARGET_X86_64
5361

    
5362
#define SHIFT 3
5363
#include "helper_template.h"
5364
#undef SHIFT
5365

    
5366
#endif
5367

    
5368
/* bit operations */
5369
target_ulong helper_bsf(target_ulong t0)
5370
{
5371
    int count;
5372
    target_ulong res;
5373

    
5374
    res = t0;
5375
    count = 0;
5376
    while ((res & 1) == 0) {
5377
        count++;
5378
        res >>= 1;
5379
    }
5380
    return count;
5381
}
5382

    
5383
target_ulong helper_bsr(target_ulong t0)
5384
{
5385
    int count;
5386
    target_ulong res, mask;
5387
    
5388
    res = t0;
5389
    count = TARGET_LONG_BITS - 1;
5390
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5391
    while ((res & mask) == 0) {
5392
        count--;
5393
        res <<= 1;
5394
    }
5395
    return count;
5396
}
5397

    
5398

    
5399
static int compute_all_eflags(void)
5400
{
5401
    return CC_SRC;
5402
}
5403

    
5404
static int compute_c_eflags(void)
5405
{
5406
    return CC_SRC & CC_C;
5407
}
5408

    
5409
CCTable cc_table[CC_OP_NB] = {
5410
    [CC_OP_DYNAMIC] = { /* should never happen */ },
5411

    
5412
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
5413

    
5414
    [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
5415
    [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
5416
    [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
5417

    
5418
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
5419
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
5420
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
5421

    
5422
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
5423
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
5424
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
5425

    
5426
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
5427
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
5428
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
5429

    
5430
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
5431
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
5432
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
5433

    
5434
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
5435
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
5436
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
5437

    
5438
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
5439
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
5440
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
5441

    
5442
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
5443
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
5444
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
5445

    
5446
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
5447
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
5448
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
5449

    
5450
    [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
5451
    [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
5452
    [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
5453

    
5454
#ifdef TARGET_X86_64
5455
    [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
5456

    
5457
    [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq  },
5458

    
5459
    [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq  },
5460

    
5461
    [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq  },
5462

    
5463
    [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq  },
5464

    
5465
    [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
5466

    
5467
    [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
5468

    
5469
    [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
5470

    
5471
    [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
5472

    
5473
    [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
5474
#endif
5475
};
5476