~fboudra/qemu-linaro/new-upstream-release-1.2.0-2012.09-0ubuntu1

« back to all changes in this revision

Viewing changes to target-i386/op_helper.c

  • Committer: Fathi Boudra
  • Author(s): Fathi Boudra
  • Date: 2012-08-21 06:47:11 UTC
  • mfrom: (0.1.16)
  • Revision ID: fathi.boudra@linaro.org-20120821064711-7yxmubp2v8a44xce
Tags: 1.1.50-2012.08-0ubuntu1
* New upstream release.
  - support emulated systems with more than 2G of memory. (LP: #1030588)
* Drop powerpc-missing-include.patch - merged upstream.
* Update debian/control: 
  - drop perl build dependency.
  - add libfdt-dev build dependency.
* Update debian/qemu-keymaps.install file.
* Update debian/rules:
  - update QEMU_CPU for ARM architecture: armv4l -> armv7l.
  - update conf_audio_drv: default to PulseAudio since PA is the default on
    Ubuntu.
  - enable KVM on ARM architecture.
  - enable flat device tree support (--enable-fdt). (LP: #1030594)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  i386 helpers
3
 
 *
4
 
 *  Copyright (c) 2003 Fabrice Bellard
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <math.h>
21
 
#include "cpu.h"
22
 
#include "dyngen-exec.h"
23
 
#include "host-utils.h"
24
 
#include "ioport.h"
25
 
#include "qemu-log.h"
26
 
#include "cpu-defs.h"
27
 
#include "helper.h"
28
 
 
29
 
#if !defined(CONFIG_USER_ONLY)
30
 
#include "softmmu_exec.h"
31
 
#endif /* !defined(CONFIG_USER_ONLY) */
32
 
 
33
 
//#define DEBUG_PCALL
34
 
 
35
 
#ifdef DEBUG_PCALL
36
 
#  define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
37
 
#  define LOG_PCALL_STATE(env) \
38
 
          log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
39
 
#else
40
 
#  define LOG_PCALL(...) do { } while (0)
41
 
#  define LOG_PCALL_STATE(env) do { } while (0)
42
 
#endif
43
 
 
44
 
/* n must be a constant to be efficient */
45
 
static inline target_long lshift(target_long x, int n)
46
 
{
47
 
    if (n >= 0) {
48
 
        return x << n;
49
 
    } else {
50
 
        return x >> (-n);
51
 
    }
52
 
}
53
 
 
54
 
#define FPU_RC_MASK         0xc00
55
 
#define FPU_RC_NEAR         0x000
56
 
#define FPU_RC_DOWN         0x400
57
 
#define FPU_RC_UP           0x800
58
 
#define FPU_RC_CHOP         0xc00
59
 
 
60
 
#define MAXTAN 9223372036854775808.0
61
 
 
62
 
/* the following deal with x86 long double-precision numbers */
63
 
#define MAXEXPD 0x7fff
64
 
#define EXPBIAS 16383
65
 
#define EXPD(fp)        (fp.l.upper & 0x7fff)
66
 
#define SIGND(fp)       ((fp.l.upper) & 0x8000)
67
 
#define MANTD(fp)       (fp.l.lower)
68
 
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
69
 
 
70
 
static inline void fpush(void)
71
 
{
72
 
    env->fpstt = (env->fpstt - 1) & 7;
73
 
    env->fptags[env->fpstt] = 0; /* validate stack entry */
74
 
}
75
 
 
76
 
static inline void fpop(void)
77
 
{
78
 
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
79
 
    env->fpstt = (env->fpstt + 1) & 7;
80
 
}
81
 
 
82
 
static inline floatx80 helper_fldt(target_ulong ptr)
83
 
{
84
 
    CPU_LDoubleU temp;
85
 
 
86
 
    temp.l.lower = ldq(ptr);
87
 
    temp.l.upper = lduw(ptr + 8);
88
 
    return temp.d;
89
 
}
90
 
 
91
 
static inline void helper_fstt(floatx80 f, target_ulong ptr)
92
 
{
93
 
    CPU_LDoubleU temp;
94
 
 
95
 
    temp.d = f;
96
 
    stq(ptr, temp.l.lower);
97
 
    stw(ptr + 8, temp.l.upper);
98
 
}
99
 
 
100
 
#define FPUS_IE (1 << 0)
101
 
#define FPUS_DE (1 << 1)
102
 
#define FPUS_ZE (1 << 2)
103
 
#define FPUS_OE (1 << 3)
104
 
#define FPUS_UE (1 << 4)
105
 
#define FPUS_PE (1 << 5)
106
 
#define FPUS_SF (1 << 6)
107
 
#define FPUS_SE (1 << 7)
108
 
#define FPUS_B  (1 << 15)
109
 
 
110
 
#define FPUC_EM 0x3f
111
 
 
112
 
static inline uint32_t compute_eflags(void)
113
 
{
114
 
    return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
115
 
}
116
 
 
117
 
/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
118
 
static inline void load_eflags(int eflags, int update_mask)
119
 
{
120
 
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
121
 
    DF = 1 - (2 * ((eflags >> 10) & 1));
122
 
    env->eflags = (env->eflags & ~update_mask) |
123
 
        (eflags & update_mask) | 0x2;
124
 
}
125
 
 
126
 
/* load efer and update the corresponding hflags. XXX: do consistency
127
 
   checks with cpuid bits ? */
128
 
static inline void cpu_load_efer(CPUState *env, uint64_t val)
129
 
{
130
 
    env->efer = val;
131
 
    env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
132
 
    if (env->efer & MSR_EFER_LMA) {
133
 
        env->hflags |= HF_LMA_MASK;
134
 
    }
135
 
    if (env->efer & MSR_EFER_SVME) {
136
 
        env->hflags |= HF_SVME_MASK;
137
 
    }
138
 
}
139
 
 
140
 
#if 0
141
 
#define raise_exception_err(a, b)\
142
 
do {\
143
 
    qemu_log("raise_exception line=%d\n", __LINE__);\
144
 
    (raise_exception_err)(a, b);\
145
 
} while (0)
146
 
#endif
147
 
 
148
 
static void QEMU_NORETURN raise_exception_err(int exception_index,
149
 
                                              int error_code);
150
 
 
151
 
static const uint8_t parity_table[256] = {
152
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
153
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
154
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
155
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
156
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
157
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
158
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
159
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
160
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
161
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
162
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
163
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
164
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
165
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
166
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
167
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
168
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
169
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
170
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
171
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
172
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
173
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
174
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
175
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
176
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
177
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
178
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
179
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
180
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
181
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
182
 
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
183
 
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
184
 
};
185
 
 
186
 
/* modulo 17 table */
187
 
static const uint8_t rclw_table[32] = {
188
 
    0, 1, 2, 3, 4, 5, 6, 7,
189
 
    8, 9,10,11,12,13,14,15,
190
 
   16, 0, 1, 2, 3, 4, 5, 6,
191
 
    7, 8, 9,10,11,12,13,14,
192
 
};
193
 
 
194
 
/* modulo 9 table */
195
 
static const uint8_t rclb_table[32] = {
196
 
    0, 1, 2, 3, 4, 5, 6, 7,
197
 
    8, 0, 1, 2, 3, 4, 5, 6,
198
 
    7, 8, 0, 1, 2, 3, 4, 5,
199
 
    6, 7, 8, 0, 1, 2, 3, 4,
200
 
};
201
 
 
202
 
#define floatx80_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL )
203
 
#define floatx80_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL )
204
 
#define floatx80_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL )
205
 
 
206
 
/* broken thread support */
207
 
 
208
 
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
209
 
 
210
 
void helper_lock(void)
211
 
{
212
 
    spin_lock(&global_cpu_lock);
213
 
}
214
 
 
215
 
void helper_unlock(void)
216
 
{
217
 
    spin_unlock(&global_cpu_lock);
218
 
}
219
 
 
220
 
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
221
 
{
222
 
    load_eflags(t0, update_mask);
223
 
}
224
 
 
225
 
target_ulong helper_read_eflags(void)
226
 
{
227
 
    uint32_t eflags;
228
 
    eflags = helper_cc_compute_all(CC_OP);
229
 
    eflags |= (DF & DF_MASK);
230
 
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
231
 
    return eflags;
232
 
}
233
 
 
234
 
/* return non zero if error */
235
 
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
236
 
                               int selector)
237
 
{
238
 
    SegmentCache *dt;
239
 
    int index;
240
 
    target_ulong ptr;
241
 
 
242
 
    if (selector & 0x4)
243
 
        dt = &env->ldt;
244
 
    else
245
 
        dt = &env->gdt;
246
 
    index = selector & ~7;
247
 
    if ((index + 7) > dt->limit)
248
 
        return -1;
249
 
    ptr = dt->base + index;
250
 
    *e1_ptr = ldl_kernel(ptr);
251
 
    *e2_ptr = ldl_kernel(ptr + 4);
252
 
    return 0;
253
 
}
254
 
 
255
 
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
256
 
{
257
 
    unsigned int limit;
258
 
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
259
 
    if (e2 & DESC_G_MASK)
260
 
        limit = (limit << 12) | 0xfff;
261
 
    return limit;
262
 
}
263
 
 
264
 
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
265
 
{
266
 
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
267
 
}
268
 
 
269
 
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
270
 
{
271
 
    sc->base = get_seg_base(e1, e2);
272
 
    sc->limit = get_seg_limit(e1, e2);
273
 
    sc->flags = e2;
274
 
}
275
 
 
276
 
/* init the segment cache in vm86 mode. */
277
 
static inline void load_seg_vm(int seg, int selector)
278
 
{
279
 
    selector &= 0xffff;
280
 
    cpu_x86_load_seg_cache(env, seg, selector,
281
 
                           (selector << 4), 0xffff, 0);
282
 
}
283
 
 
284
 
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
285
 
                                       uint32_t *esp_ptr, int dpl)
286
 
{
287
 
    int type, index, shift;
288
 
 
289
 
#if 0
290
 
    {
291
 
        int i;
292
 
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
293
 
        for(i=0;i<env->tr.limit;i++) {
294
 
            printf("%02x ", env->tr.base[i]);
295
 
            if ((i & 7) == 7) printf("\n");
296
 
        }
297
 
        printf("\n");
298
 
    }
299
 
#endif
300
 
 
301
 
    if (!(env->tr.flags & DESC_P_MASK))
302
 
        cpu_abort(env, "invalid tss");
303
 
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
304
 
    if ((type & 7) != 1)
305
 
        cpu_abort(env, "invalid tss type");
306
 
    shift = type >> 3;
307
 
    index = (dpl * 4 + 2) << shift;
308
 
    if (index + (4 << shift) - 1 > env->tr.limit)
309
 
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
310
 
    if (shift == 0) {
311
 
        *esp_ptr = lduw_kernel(env->tr.base + index);
312
 
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
313
 
    } else {
314
 
        *esp_ptr = ldl_kernel(env->tr.base + index);
315
 
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
316
 
    }
317
 
}
318
 
 
319
 
/* XXX: merge with load_seg() */
320
 
static void tss_load_seg(int seg_reg, int selector)
321
 
{
322
 
    uint32_t e1, e2;
323
 
    int rpl, dpl, cpl;
324
 
 
325
 
    if ((selector & 0xfffc) != 0) {
326
 
        if (load_segment(&e1, &e2, selector) != 0)
327
 
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
328
 
        if (!(e2 & DESC_S_MASK))
329
 
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
330
 
        rpl = selector & 3;
331
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
332
 
        cpl = env->hflags & HF_CPL_MASK;
333
 
        if (seg_reg == R_CS) {
334
 
            if (!(e2 & DESC_CS_MASK))
335
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
336
 
            /* XXX: is it correct ? */
337
 
            if (dpl != rpl)
338
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
339
 
            if ((e2 & DESC_C_MASK) && dpl > rpl)
340
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
341
 
        } else if (seg_reg == R_SS) {
342
 
            /* SS must be writable data */
343
 
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
344
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
345
 
            if (dpl != cpl || dpl != rpl)
346
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
347
 
        } else {
348
 
            /* not readable code */
349
 
            if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
350
 
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
351
 
            /* if data or non conforming code, checks the rights */
352
 
            if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
353
 
                if (dpl < cpl || dpl < rpl)
354
 
                    raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
355
 
            }
356
 
        }
357
 
        if (!(e2 & DESC_P_MASK))
358
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
359
 
        cpu_x86_load_seg_cache(env, seg_reg, selector,
360
 
                       get_seg_base(e1, e2),
361
 
                       get_seg_limit(e1, e2),
362
 
                       e2);
363
 
    } else {
364
 
        if (seg_reg == R_SS || seg_reg == R_CS)
365
 
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
366
 
    }
367
 
}
368
 
 
369
 
#define SWITCH_TSS_JMP  0
370
 
#define SWITCH_TSS_IRET 1
371
 
#define SWITCH_TSS_CALL 2
372
 
 
373
 
/* XXX: restore CPU state in registers (PowerPC case) */
374
 
static void switch_tss(int tss_selector,
375
 
                       uint32_t e1, uint32_t e2, int source,
376
 
                       uint32_t next_eip)
377
 
{
378
 
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
379
 
    target_ulong tss_base;
380
 
    uint32_t new_regs[8], new_segs[6];
381
 
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
382
 
    uint32_t old_eflags, eflags_mask;
383
 
    SegmentCache *dt;
384
 
    int index;
385
 
    target_ulong ptr;
386
 
 
387
 
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
388
 
    LOG_PCALL("switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
389
 
 
390
 
    /* if task gate, we read the TSS segment and we load it */
391
 
    if (type == 5) {
392
 
        if (!(e2 & DESC_P_MASK))
393
 
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
394
 
        tss_selector = e1 >> 16;
395
 
        if (tss_selector & 4)
396
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
397
 
        if (load_segment(&e1, &e2, tss_selector) != 0)
398
 
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
399
 
        if (e2 & DESC_S_MASK)
400
 
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
401
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
402
 
        if ((type & 7) != 1)
403
 
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
404
 
    }
405
 
 
406
 
    if (!(e2 & DESC_P_MASK))
407
 
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
408
 
 
409
 
    if (type & 8)
410
 
        tss_limit_max = 103;
411
 
    else
412
 
        tss_limit_max = 43;
413
 
    tss_limit = get_seg_limit(e1, e2);
414
 
    tss_base = get_seg_base(e1, e2);
415
 
    if ((tss_selector & 4) != 0 ||
416
 
        tss_limit < tss_limit_max)
417
 
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
418
 
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
419
 
    if (old_type & 8)
420
 
        old_tss_limit_max = 103;
421
 
    else
422
 
        old_tss_limit_max = 43;
423
 
 
424
 
    /* read all the registers from the new TSS */
425
 
    if (type & 8) {
426
 
        /* 32 bit */
427
 
        new_cr3 = ldl_kernel(tss_base + 0x1c);
428
 
        new_eip = ldl_kernel(tss_base + 0x20);
429
 
        new_eflags = ldl_kernel(tss_base + 0x24);
430
 
        for(i = 0; i < 8; i++)
431
 
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
432
 
        for(i = 0; i < 6; i++)
433
 
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
434
 
        new_ldt = lduw_kernel(tss_base + 0x60);
435
 
        new_trap = ldl_kernel(tss_base + 0x64);
436
 
    } else {
437
 
        /* 16 bit */
438
 
        new_cr3 = 0;
439
 
        new_eip = lduw_kernel(tss_base + 0x0e);
440
 
        new_eflags = lduw_kernel(tss_base + 0x10);
441
 
        for(i = 0; i < 8; i++)
442
 
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
443
 
        for(i = 0; i < 4; i++)
444
 
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
445
 
        new_ldt = lduw_kernel(tss_base + 0x2a);
446
 
        new_segs[R_FS] = 0;
447
 
        new_segs[R_GS] = 0;
448
 
        new_trap = 0;
449
 
    }
450
 
    /* XXX: avoid a compiler warning, see
451
 
     http://support.amd.com/us/Processor_TechDocs/24593.pdf
452
 
     chapters 12.2.5 and 13.2.4 on how to implement TSS Trap bit */
453
 
    (void)new_trap;
454
 
 
455
 
    /* NOTE: we must avoid memory exceptions during the task switch,
456
 
       so we make dummy accesses before */
457
 
    /* XXX: it can still fail in some cases, so a bigger hack is
458
 
       necessary to valid the TLB after having done the accesses */
459
 
 
460
 
    v1 = ldub_kernel(env->tr.base);
461
 
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
462
 
    stb_kernel(env->tr.base, v1);
463
 
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
464
 
 
465
 
    /* clear busy bit (it is restartable) */
466
 
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
467
 
        target_ulong ptr;
468
 
        uint32_t e2;
469
 
        ptr = env->gdt.base + (env->tr.selector & ~7);
470
 
        e2 = ldl_kernel(ptr + 4);
471
 
        e2 &= ~DESC_TSS_BUSY_MASK;
472
 
        stl_kernel(ptr + 4, e2);
473
 
    }
474
 
    old_eflags = compute_eflags();
475
 
    if (source == SWITCH_TSS_IRET)
476
 
        old_eflags &= ~NT_MASK;
477
 
 
478
 
    /* save the current state in the old TSS */
479
 
    if (type & 8) {
480
 
        /* 32 bit */
481
 
        stl_kernel(env->tr.base + 0x20, next_eip);
482
 
        stl_kernel(env->tr.base + 0x24, old_eflags);
483
 
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
484
 
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
485
 
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
486
 
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
487
 
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
488
 
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
489
 
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
490
 
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
491
 
        for(i = 0; i < 6; i++)
492
 
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
493
 
    } else {
494
 
        /* 16 bit */
495
 
        stw_kernel(env->tr.base + 0x0e, next_eip);
496
 
        stw_kernel(env->tr.base + 0x10, old_eflags);
497
 
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
498
 
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
499
 
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
500
 
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
501
 
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
502
 
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
503
 
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
504
 
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
505
 
        for(i = 0; i < 4; i++)
506
 
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
507
 
    }
508
 
 
509
 
    /* now if an exception occurs, it will occurs in the next task
510
 
       context */
511
 
 
512
 
    if (source == SWITCH_TSS_CALL) {
513
 
        stw_kernel(tss_base, env->tr.selector);
514
 
        new_eflags |= NT_MASK;
515
 
    }
516
 
 
517
 
    /* set busy bit */
518
 
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
519
 
        target_ulong ptr;
520
 
        uint32_t e2;
521
 
        ptr = env->gdt.base + (tss_selector & ~7);
522
 
        e2 = ldl_kernel(ptr + 4);
523
 
        e2 |= DESC_TSS_BUSY_MASK;
524
 
        stl_kernel(ptr + 4, e2);
525
 
    }
526
 
 
527
 
    /* set the new CPU state */
528
 
    /* from this point, any exception which occurs can give problems */
529
 
    env->cr[0] |= CR0_TS_MASK;
530
 
    env->hflags |= HF_TS_MASK;
531
 
    env->tr.selector = tss_selector;
532
 
    env->tr.base = tss_base;
533
 
    env->tr.limit = tss_limit;
534
 
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
535
 
 
536
 
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
537
 
        cpu_x86_update_cr3(env, new_cr3);
538
 
    }
539
 
 
540
 
    /* load all registers without an exception, then reload them with
541
 
       possible exception */
542
 
    env->eip = new_eip;
543
 
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
544
 
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
545
 
    if (!(type & 8))
546
 
        eflags_mask &= 0xffff;
547
 
    load_eflags(new_eflags, eflags_mask);
548
 
    /* XXX: what to do in 16 bit case ? */
549
 
    EAX = new_regs[0];
550
 
    ECX = new_regs[1];
551
 
    EDX = new_regs[2];
552
 
    EBX = new_regs[3];
553
 
    ESP = new_regs[4];
554
 
    EBP = new_regs[5];
555
 
    ESI = new_regs[6];
556
 
    EDI = new_regs[7];
557
 
    if (new_eflags & VM_MASK) {
558
 
        for(i = 0; i < 6; i++)
559
 
            load_seg_vm(i, new_segs[i]);
560
 
        /* in vm86, CPL is always 3 */
561
 
        cpu_x86_set_cpl(env, 3);
562
 
    } else {
563
 
        /* CPL is set the RPL of CS */
564
 
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
565
 
        /* first just selectors as the rest may trigger exceptions */
566
 
        for(i = 0; i < 6; i++)
567
 
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
568
 
    }
569
 
 
570
 
    env->ldt.selector = new_ldt & ~4;
571
 
    env->ldt.base = 0;
572
 
    env->ldt.limit = 0;
573
 
    env->ldt.flags = 0;
574
 
 
575
 
    /* load the LDT */
576
 
    if (new_ldt & 4)
577
 
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
578
 
 
579
 
    if ((new_ldt & 0xfffc) != 0) {
580
 
        dt = &env->gdt;
581
 
        index = new_ldt & ~7;
582
 
        if ((index + 7) > dt->limit)
583
 
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
584
 
        ptr = dt->base + index;
585
 
        e1 = ldl_kernel(ptr);
586
 
        e2 = ldl_kernel(ptr + 4);
587
 
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
588
 
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
589
 
        if (!(e2 & DESC_P_MASK))
590
 
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
591
 
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
592
 
    }
593
 
 
594
 
    /* load the segments */
595
 
    if (!(new_eflags & VM_MASK)) {
596
 
        tss_load_seg(R_CS, new_segs[R_CS]);
597
 
        tss_load_seg(R_SS, new_segs[R_SS]);
598
 
        tss_load_seg(R_ES, new_segs[R_ES]);
599
 
        tss_load_seg(R_DS, new_segs[R_DS]);
600
 
        tss_load_seg(R_FS, new_segs[R_FS]);
601
 
        tss_load_seg(R_GS, new_segs[R_GS]);
602
 
    }
603
 
 
604
 
    /* check that EIP is in the CS segment limits */
605
 
    if (new_eip > env->segs[R_CS].limit) {
606
 
        /* XXX: different exception if CALL ? */
607
 
        raise_exception_err(EXCP0D_GPF, 0);
608
 
    }
609
 
 
610
 
#ifndef CONFIG_USER_ONLY
611
 
    /* reset local breakpoints */
612
 
    if (env->dr[7] & 0x55) {
613
 
        for (i = 0; i < 4; i++) {
614
 
            if (hw_breakpoint_enabled(env->dr[7], i) == 0x1)
615
 
                hw_breakpoint_remove(env, i);
616
 
        }
617
 
        env->dr[7] &= ~0x55;
618
 
    }
619
 
#endif
620
 
}
621
 
 
622
 
/* check if Port I/O is allowed in TSS */
623
 
static inline void check_io(int addr, int size)
624
 
{
625
 
    int io_offset, val, mask;
626
 
 
627
 
    /* TSS must be a valid 32 bit one */
628
 
    if (!(env->tr.flags & DESC_P_MASK) ||
629
 
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
630
 
        env->tr.limit < 103)
631
 
        goto fail;
632
 
    io_offset = lduw_kernel(env->tr.base + 0x66);
633
 
    io_offset += (addr >> 3);
634
 
    /* Note: the check needs two bytes */
635
 
    if ((io_offset + 1) > env->tr.limit)
636
 
        goto fail;
637
 
    val = lduw_kernel(env->tr.base + io_offset);
638
 
    val >>= (addr & 7);
639
 
    mask = (1 << size) - 1;
640
 
    /* all bits must be zero to allow the I/O */
641
 
    if ((val & mask) != 0) {
642
 
    fail:
643
 
        raise_exception_err(EXCP0D_GPF, 0);
644
 
    }
645
 
}
646
 
 
647
 
void helper_check_iob(uint32_t t0)
648
 
{
649
 
    check_io(t0, 1);
650
 
}
651
 
 
652
 
void helper_check_iow(uint32_t t0)
653
 
{
654
 
    check_io(t0, 2);
655
 
}
656
 
 
657
 
void helper_check_iol(uint32_t t0)
658
 
{
659
 
    check_io(t0, 4);
660
 
}
661
 
 
662
 
void helper_outb(uint32_t port, uint32_t data)
663
 
{
664
 
    cpu_outb(port, data & 0xff);
665
 
}
666
 
 
667
 
target_ulong helper_inb(uint32_t port)
668
 
{
669
 
    return cpu_inb(port);
670
 
}
671
 
 
672
 
void helper_outw(uint32_t port, uint32_t data)
673
 
{
674
 
    cpu_outw(port, data & 0xffff);
675
 
}
676
 
 
677
 
target_ulong helper_inw(uint32_t port)
678
 
{
679
 
    return cpu_inw(port);
680
 
}
681
 
 
682
 
void helper_outl(uint32_t port, uint32_t data)
683
 
{
684
 
    cpu_outl(port, data);
685
 
}
686
 
 
687
 
target_ulong helper_inl(uint32_t port)
688
 
{
689
 
    return cpu_inl(port);
690
 
}
691
 
 
692
 
static inline unsigned int get_sp_mask(unsigned int e2)
693
 
{
694
 
    if (e2 & DESC_B_MASK)
695
 
        return 0xffffffff;
696
 
    else
697
 
        return 0xffff;
698
 
}
699
 
 
700
 
static int exeption_has_error_code(int intno)
701
 
{
702
 
        switch(intno) {
703
 
        case 8:
704
 
        case 10:
705
 
        case 11:
706
 
        case 12:
707
 
        case 13:
708
 
        case 14:
709
 
        case 17:
710
 
            return 1;
711
 
        }
712
 
        return 0;
713
 
}
714
 
 
715
 
#ifdef TARGET_X86_64
716
 
#define SET_ESP(val, sp_mask)\
717
 
do {\
718
 
    if ((sp_mask) == 0xffff)\
719
 
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
720
 
    else if ((sp_mask) == 0xffffffffLL)\
721
 
        ESP = (uint32_t)(val);\
722
 
    else\
723
 
        ESP = (val);\
724
 
} while (0)
725
 
#else
726
 
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
727
 
#endif
728
 
 
729
 
/* in 64-bit machines, this can overflow. So this segment addition macro
730
 
 * can be used to trim the value to 32-bit whenever needed */
731
 
#define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
732
 
 
733
 
/* XXX: add a is_user flag to have proper security support */
734
 
#define PUSHW(ssp, sp, sp_mask, val)\
735
 
{\
736
 
    sp -= 2;\
737
 
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
738
 
}
739
 
 
740
 
#define PUSHL(ssp, sp, sp_mask, val)\
741
 
{\
742
 
    sp -= 4;\
743
 
    stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
744
 
}
745
 
 
746
 
#define POPW(ssp, sp, sp_mask, val)\
747
 
{\
748
 
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
749
 
    sp += 2;\
750
 
}
751
 
 
752
 
#define POPL(ssp, sp, sp_mask, val)\
753
 
{\
754
 
    val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
755
 
    sp += 4;\
756
 
}
757
 
 
758
 
/* protected mode interrupt */
759
 
static void do_interrupt_protected(int intno, int is_int, int error_code,
760
 
                                   unsigned int next_eip, int is_hw)
761
 
{
762
 
    SegmentCache *dt;
763
 
    target_ulong ptr, ssp;
764
 
    int type, dpl, selector, ss_dpl, cpl;
765
 
    int has_error_code, new_stack, shift;
766
 
    uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
767
 
    uint32_t old_eip, sp_mask;
768
 
 
769
 
    has_error_code = 0;
770
 
    if (!is_int && !is_hw)
771
 
        has_error_code = exeption_has_error_code(intno);
772
 
    if (is_int)
773
 
        old_eip = next_eip;
774
 
    else
775
 
        old_eip = env->eip;
776
 
 
777
 
    dt = &env->idt;
778
 
    if (intno * 8 + 7 > dt->limit)
779
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
780
 
    ptr = dt->base + intno * 8;
781
 
    e1 = ldl_kernel(ptr);
782
 
    e2 = ldl_kernel(ptr + 4);
783
 
    /* check gate type */
784
 
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
785
 
    switch(type) {
786
 
    case 5: /* task gate */
787
 
        /* must do that check here to return the correct error code */
788
 
        if (!(e2 & DESC_P_MASK))
789
 
            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
790
 
        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
791
 
        if (has_error_code) {
792
 
            int type;
793
 
            uint32_t mask;
794
 
            /* push the error code */
795
 
            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
796
 
            shift = type >> 3;
797
 
            if (env->segs[R_SS].flags & DESC_B_MASK)
798
 
                mask = 0xffffffff;
799
 
            else
800
 
                mask = 0xffff;
801
 
            esp = (ESP - (2 << shift)) & mask;
802
 
            ssp = env->segs[R_SS].base + esp;
803
 
            if (shift)
804
 
                stl_kernel(ssp, error_code);
805
 
            else
806
 
                stw_kernel(ssp, error_code);
807
 
            SET_ESP(esp, mask);
808
 
        }
809
 
        return;
810
 
    case 6: /* 286 interrupt gate */
811
 
    case 7: /* 286 trap gate */
812
 
    case 14: /* 386 interrupt gate */
813
 
    case 15: /* 386 trap gate */
814
 
        break;
815
 
    default:
816
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
817
 
        break;
818
 
    }
819
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
820
 
    cpl = env->hflags & HF_CPL_MASK;
821
 
    /* check privilege if software int */
822
 
    if (is_int && dpl < cpl)
823
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
824
 
    /* check valid bit */
825
 
    if (!(e2 & DESC_P_MASK))
826
 
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
827
 
    selector = e1 >> 16;
828
 
    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
829
 
    if ((selector & 0xfffc) == 0)
830
 
        raise_exception_err(EXCP0D_GPF, 0);
831
 
 
832
 
    if (load_segment(&e1, &e2, selector) != 0)
833
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
834
 
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
835
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
836
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
837
 
    if (dpl > cpl)
838
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
839
 
    if (!(e2 & DESC_P_MASK))
840
 
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
841
 
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
842
 
        /* to inner privilege */
843
 
        get_ss_esp_from_tss(&ss, &esp, dpl);
844
 
        if ((ss & 0xfffc) == 0)
845
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
846
 
        if ((ss & 3) != dpl)
847
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
848
 
        if (load_segment(&ss_e1, &ss_e2, ss) != 0)
849
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
850
 
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
851
 
        if (ss_dpl != dpl)
852
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
853
 
        if (!(ss_e2 & DESC_S_MASK) ||
854
 
            (ss_e2 & DESC_CS_MASK) ||
855
 
            !(ss_e2 & DESC_W_MASK))
856
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
857
 
        if (!(ss_e2 & DESC_P_MASK))
858
 
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
859
 
        new_stack = 1;
860
 
        sp_mask = get_sp_mask(ss_e2);
861
 
        ssp = get_seg_base(ss_e1, ss_e2);
862
 
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
863
 
        /* to same privilege */
864
 
        if (env->eflags & VM_MASK)
865
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
866
 
        new_stack = 0;
867
 
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
868
 
        ssp = env->segs[R_SS].base;
869
 
        esp = ESP;
870
 
        dpl = cpl;
871
 
    } else {
872
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
873
 
        new_stack = 0; /* avoid warning */
874
 
        sp_mask = 0; /* avoid warning */
875
 
        ssp = 0; /* avoid warning */
876
 
        esp = 0; /* avoid warning */
877
 
    }
878
 
 
879
 
    shift = type >> 3;
880
 
 
881
 
#if 0
882
 
    /* XXX: check that enough room is available */
883
 
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
884
 
    if (env->eflags & VM_MASK)
885
 
        push_size += 8;
886
 
    push_size <<= shift;
887
 
#endif
888
 
    if (shift == 1) {
889
 
        if (new_stack) {
890
 
            if (env->eflags & VM_MASK) {
891
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
892
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
893
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
894
 
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
895
 
            }
896
 
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
897
 
            PUSHL(ssp, esp, sp_mask, ESP);
898
 
        }
899
 
        PUSHL(ssp, esp, sp_mask, compute_eflags());
900
 
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
901
 
        PUSHL(ssp, esp, sp_mask, old_eip);
902
 
        if (has_error_code) {
903
 
            PUSHL(ssp, esp, sp_mask, error_code);
904
 
        }
905
 
    } else {
906
 
        if (new_stack) {
907
 
            if (env->eflags & VM_MASK) {
908
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
909
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
910
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
911
 
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
912
 
            }
913
 
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
914
 
            PUSHW(ssp, esp, sp_mask, ESP);
915
 
        }
916
 
        PUSHW(ssp, esp, sp_mask, compute_eflags());
917
 
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
918
 
        PUSHW(ssp, esp, sp_mask, old_eip);
919
 
        if (has_error_code) {
920
 
            PUSHW(ssp, esp, sp_mask, error_code);
921
 
        }
922
 
    }
923
 
 
924
 
    if (new_stack) {
925
 
        if (env->eflags & VM_MASK) {
926
 
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
927
 
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
928
 
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
929
 
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
930
 
        }
931
 
        ss = (ss & ~3) | dpl;
932
 
        cpu_x86_load_seg_cache(env, R_SS, ss,
933
 
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
934
 
    }
935
 
    SET_ESP(esp, sp_mask);
936
 
 
937
 
    selector = (selector & ~3) | dpl;
938
 
    cpu_x86_load_seg_cache(env, R_CS, selector,
939
 
                   get_seg_base(e1, e2),
940
 
                   get_seg_limit(e1, e2),
941
 
                   e2);
942
 
    cpu_x86_set_cpl(env, dpl);
943
 
    env->eip = offset;
944
 
 
945
 
    /* interrupt gate clear IF mask */
946
 
    if ((type & 1) == 0) {
947
 
        env->eflags &= ~IF_MASK;
948
 
    }
949
 
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
950
 
}
951
 
 
952
 
#ifdef TARGET_X86_64
953
 
 
954
 
#define PUSHQ(sp, val)\
955
 
{\
956
 
    sp -= 8;\
957
 
    stq_kernel(sp, (val));\
958
 
}
959
 
 
960
 
#define POPQ(sp, val)\
961
 
{\
962
 
    val = ldq_kernel(sp);\
963
 
    sp += 8;\
964
 
}
965
 
 
966
 
static inline target_ulong get_rsp_from_tss(int level)
967
 
{
968
 
    int index;
969
 
 
970
 
#if 0
971
 
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
972
 
           env->tr.base, env->tr.limit);
973
 
#endif
974
 
 
975
 
    if (!(env->tr.flags & DESC_P_MASK))
976
 
        cpu_abort(env, "invalid tss");
977
 
    index = 8 * level + 4;
978
 
    if ((index + 7) > env->tr.limit)
979
 
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
980
 
    return ldq_kernel(env->tr.base + index);
981
 
}
982
 
 
983
 
/* 64 bit interrupt */
984
 
static void do_interrupt64(int intno, int is_int, int error_code,
985
 
                           target_ulong next_eip, int is_hw)
986
 
{
987
 
    SegmentCache *dt;
988
 
    target_ulong ptr;
989
 
    int type, dpl, selector, cpl, ist;
990
 
    int has_error_code, new_stack;
991
 
    uint32_t e1, e2, e3, ss;
992
 
    target_ulong old_eip, esp, offset;
993
 
 
994
 
    has_error_code = 0;
995
 
    if (!is_int && !is_hw)
996
 
        has_error_code = exeption_has_error_code(intno);
997
 
    if (is_int)
998
 
        old_eip = next_eip;
999
 
    else
1000
 
        old_eip = env->eip;
1001
 
 
1002
 
    dt = &env->idt;
1003
 
    if (intno * 16 + 15 > dt->limit)
1004
 
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
1005
 
    ptr = dt->base + intno * 16;
1006
 
    e1 = ldl_kernel(ptr);
1007
 
    e2 = ldl_kernel(ptr + 4);
1008
 
    e3 = ldl_kernel(ptr + 8);
1009
 
    /* check gate type */
1010
 
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
1011
 
    switch(type) {
1012
 
    case 14: /* 386 interrupt gate */
1013
 
    case 15: /* 386 trap gate */
1014
 
        break;
1015
 
    default:
1016
 
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
1017
 
        break;
1018
 
    }
1019
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1020
 
    cpl = env->hflags & HF_CPL_MASK;
1021
 
    /* check privilege if software int */
1022
 
    if (is_int && dpl < cpl)
1023
 
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
1024
 
    /* check valid bit */
1025
 
    if (!(e2 & DESC_P_MASK))
1026
 
        raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
1027
 
    selector = e1 >> 16;
1028
 
    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
1029
 
    ist = e2 & 7;
1030
 
    if ((selector & 0xfffc) == 0)
1031
 
        raise_exception_err(EXCP0D_GPF, 0);
1032
 
 
1033
 
    if (load_segment(&e1, &e2, selector) != 0)
1034
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1035
 
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
1036
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1037
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1038
 
    if (dpl > cpl)
1039
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1040
 
    if (!(e2 & DESC_P_MASK))
1041
 
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1042
 
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
1043
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1044
 
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
1045
 
        /* to inner privilege */
1046
 
        if (ist != 0)
1047
 
            esp = get_rsp_from_tss(ist + 3);
1048
 
        else
1049
 
            esp = get_rsp_from_tss(dpl);
1050
 
        esp &= ~0xfLL; /* align stack */
1051
 
        ss = 0;
1052
 
        new_stack = 1;
1053
 
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
1054
 
        /* to same privilege */
1055
 
        if (env->eflags & VM_MASK)
1056
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1057
 
        new_stack = 0;
1058
 
        if (ist != 0)
1059
 
            esp = get_rsp_from_tss(ist + 3);
1060
 
        else
1061
 
            esp = ESP;
1062
 
        esp &= ~0xfLL; /* align stack */
1063
 
        dpl = cpl;
1064
 
    } else {
1065
 
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1066
 
        new_stack = 0; /* avoid warning */
1067
 
        esp = 0; /* avoid warning */
1068
 
    }
1069
 
 
1070
 
    PUSHQ(esp, env->segs[R_SS].selector);
1071
 
    PUSHQ(esp, ESP);
1072
 
    PUSHQ(esp, compute_eflags());
1073
 
    PUSHQ(esp, env->segs[R_CS].selector);
1074
 
    PUSHQ(esp, old_eip);
1075
 
    if (has_error_code) {
1076
 
        PUSHQ(esp, error_code);
1077
 
    }
1078
 
 
1079
 
    if (new_stack) {
1080
 
        ss = 0 | dpl;
1081
 
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
1082
 
    }
1083
 
    ESP = esp;
1084
 
 
1085
 
    selector = (selector & ~3) | dpl;
1086
 
    cpu_x86_load_seg_cache(env, R_CS, selector,
1087
 
                   get_seg_base(e1, e2),
1088
 
                   get_seg_limit(e1, e2),
1089
 
                   e2);
1090
 
    cpu_x86_set_cpl(env, dpl);
1091
 
    env->eip = offset;
1092
 
 
1093
 
    /* interrupt gate clear IF mask */
1094
 
    if ((type & 1) == 0) {
1095
 
        env->eflags &= ~IF_MASK;
1096
 
    }
1097
 
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
1098
 
}
1099
 
#endif
1100
 
 
1101
 
#ifdef TARGET_X86_64
1102
 
#if defined(CONFIG_USER_ONLY)
1103
 
void helper_syscall(int next_eip_addend)
1104
 
{
1105
 
    env->exception_index = EXCP_SYSCALL;
1106
 
    env->exception_next_eip = env->eip + next_eip_addend;
1107
 
    cpu_loop_exit(env);
1108
 
}
1109
 
#else
1110
 
void helper_syscall(int next_eip_addend)
1111
 
{
1112
 
    int selector;
1113
 
 
1114
 
    if (!(env->efer & MSR_EFER_SCE)) {
1115
 
        raise_exception_err(EXCP06_ILLOP, 0);
1116
 
    }
1117
 
    selector = (env->star >> 32) & 0xffff;
1118
 
    if (env->hflags & HF_LMA_MASK) {
1119
 
        int code64;
1120
 
 
1121
 
        ECX = env->eip + next_eip_addend;
1122
 
        env->regs[11] = compute_eflags();
1123
 
 
1124
 
        code64 = env->hflags & HF_CS64_MASK;
1125
 
 
1126
 
        cpu_x86_set_cpl(env, 0);
1127
 
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1128
 
                           0, 0xffffffff,
1129
 
                               DESC_G_MASK | DESC_P_MASK |
1130
 
                               DESC_S_MASK |
1131
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1132
 
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1133
 
                               0, 0xffffffff,
1134
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1135
 
                               DESC_S_MASK |
1136
 
                               DESC_W_MASK | DESC_A_MASK);
1137
 
        env->eflags &= ~env->fmask;
1138
 
        load_eflags(env->eflags, 0);
1139
 
        if (code64)
1140
 
            env->eip = env->lstar;
1141
 
        else
1142
 
            env->eip = env->cstar;
1143
 
    } else {
1144
 
        ECX = (uint32_t)(env->eip + next_eip_addend);
1145
 
 
1146
 
        cpu_x86_set_cpl(env, 0);
1147
 
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1148
 
                           0, 0xffffffff,
1149
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1150
 
                               DESC_S_MASK |
1151
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1152
 
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1153
 
                               0, 0xffffffff,
1154
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1155
 
                               DESC_S_MASK |
1156
 
                               DESC_W_MASK | DESC_A_MASK);
1157
 
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1158
 
        env->eip = (uint32_t)env->star;
1159
 
    }
1160
 
}
1161
 
#endif
1162
 
#endif
1163
 
 
1164
 
#ifdef TARGET_X86_64
1165
 
void helper_sysret(int dflag)
1166
 
{
1167
 
    int cpl, selector;
1168
 
 
1169
 
    if (!(env->efer & MSR_EFER_SCE)) {
1170
 
        raise_exception_err(EXCP06_ILLOP, 0);
1171
 
    }
1172
 
    cpl = env->hflags & HF_CPL_MASK;
1173
 
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1174
 
        raise_exception_err(EXCP0D_GPF, 0);
1175
 
    }
1176
 
    selector = (env->star >> 48) & 0xffff;
1177
 
    if (env->hflags & HF_LMA_MASK) {
1178
 
        if (dflag == 2) {
1179
 
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1180
 
                                   0, 0xffffffff,
1181
 
                                   DESC_G_MASK | DESC_P_MASK |
1182
 
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1183
 
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1184
 
                                   DESC_L_MASK);
1185
 
            env->eip = ECX;
1186
 
        } else {
1187
 
            cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1188
 
                                   0, 0xffffffff,
1189
 
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1190
 
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1191
 
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1192
 
            env->eip = (uint32_t)ECX;
1193
 
        }
1194
 
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1195
 
                               0, 0xffffffff,
1196
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1197
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1198
 
                               DESC_W_MASK | DESC_A_MASK);
1199
 
        load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1200
 
                    IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1201
 
        cpu_x86_set_cpl(env, 3);
1202
 
    } else {
1203
 
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1204
 
                               0, 0xffffffff,
1205
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1206
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1207
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1208
 
        env->eip = (uint32_t)ECX;
1209
 
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1210
 
                               0, 0xffffffff,
1211
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1212
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1213
 
                               DESC_W_MASK | DESC_A_MASK);
1214
 
        env->eflags |= IF_MASK;
1215
 
        cpu_x86_set_cpl(env, 3);
1216
 
    }
1217
 
}
1218
 
#endif
1219
 
 
1220
 
/* real mode interrupt */
1221
 
static void do_interrupt_real(int intno, int is_int, int error_code,
1222
 
                              unsigned int next_eip)
1223
 
{
1224
 
    SegmentCache *dt;
1225
 
    target_ulong ptr, ssp;
1226
 
    int selector;
1227
 
    uint32_t offset, esp;
1228
 
    uint32_t old_cs, old_eip;
1229
 
 
1230
 
    /* real mode (simpler !) */
1231
 
    dt = &env->idt;
1232
 
    if (intno * 4 + 3 > dt->limit)
1233
 
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1234
 
    ptr = dt->base + intno * 4;
1235
 
    offset = lduw_kernel(ptr);
1236
 
    selector = lduw_kernel(ptr + 2);
1237
 
    esp = ESP;
1238
 
    ssp = env->segs[R_SS].base;
1239
 
    if (is_int)
1240
 
        old_eip = next_eip;
1241
 
    else
1242
 
        old_eip = env->eip;
1243
 
    old_cs = env->segs[R_CS].selector;
1244
 
    /* XXX: use SS segment size ? */
1245
 
    PUSHW(ssp, esp, 0xffff, compute_eflags());
1246
 
    PUSHW(ssp, esp, 0xffff, old_cs);
1247
 
    PUSHW(ssp, esp, 0xffff, old_eip);
1248
 
 
1249
 
    /* update processor state */
1250
 
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1251
 
    env->eip = offset;
1252
 
    env->segs[R_CS].selector = selector;
1253
 
    env->segs[R_CS].base = (selector << 4);
1254
 
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1255
 
}
1256
 
 
1257
 
#if defined(CONFIG_USER_ONLY)
1258
 
/* fake user mode interrupt */
1259
 
static void do_interrupt_user(int intno, int is_int, int error_code,
1260
 
                              target_ulong next_eip)
1261
 
{
1262
 
    SegmentCache *dt;
1263
 
    target_ulong ptr;
1264
 
    int dpl, cpl, shift;
1265
 
    uint32_t e2;
1266
 
 
1267
 
    dt = &env->idt;
1268
 
    if (env->hflags & HF_LMA_MASK) {
1269
 
        shift = 4;
1270
 
    } else {
1271
 
        shift = 3;
1272
 
    }
1273
 
    ptr = dt->base + (intno << shift);
1274
 
    e2 = ldl_kernel(ptr + 4);
1275
 
 
1276
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1277
 
    cpl = env->hflags & HF_CPL_MASK;
1278
 
    /* check privilege if software int */
1279
 
    if (is_int && dpl < cpl)
1280
 
        raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1281
 
 
1282
 
    /* Since we emulate only user space, we cannot do more than
1283
 
       exiting the emulation with the suitable exception and error
1284
 
       code */
1285
 
    if (is_int)
1286
 
        EIP = next_eip;
1287
 
}
1288
 
 
1289
 
#else
1290
 
 
1291
 
static void handle_even_inj(int intno, int is_int, int error_code,
1292
 
                int is_hw, int rm)
1293
 
{
1294
 
    uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1295
 
    if (!(event_inj & SVM_EVTINJ_VALID)) {
1296
 
            int type;
1297
 
            if (is_int)
1298
 
                    type = SVM_EVTINJ_TYPE_SOFT;
1299
 
            else
1300
 
                    type = SVM_EVTINJ_TYPE_EXEPT;
1301
 
            event_inj = intno | type | SVM_EVTINJ_VALID;
1302
 
            if (!rm && exeption_has_error_code(intno)) {
1303
 
                    event_inj |= SVM_EVTINJ_VALID_ERR;
1304
 
                    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err), error_code);
1305
 
            }
1306
 
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj);
1307
 
    }
1308
 
}
1309
 
#endif
1310
 
 
1311
 
/*
1312
 
 * Begin execution of an interruption. is_int is TRUE if coming from
1313
 
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1314
 
 * instruction. It is only relevant if is_int is TRUE.
1315
 
 */
1316
 
static void do_interrupt_all(int intno, int is_int, int error_code,
1317
 
                             target_ulong next_eip, int is_hw)
1318
 
{
1319
 
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
1320
 
        if ((env->cr[0] & CR0_PE_MASK)) {
1321
 
            static int count;
1322
 
            qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1323
 
                    count, intno, error_code, is_int,
1324
 
                    env->hflags & HF_CPL_MASK,
1325
 
                    env->segs[R_CS].selector, EIP,
1326
 
                    (int)env->segs[R_CS].base + EIP,
1327
 
                    env->segs[R_SS].selector, ESP);
1328
 
            if (intno == 0x0e) {
1329
 
                qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
1330
 
            } else {
1331
 
                qemu_log(" EAX=" TARGET_FMT_lx, EAX);
1332
 
            }
1333
 
            qemu_log("\n");
1334
 
            log_cpu_state(env, X86_DUMP_CCOP);
1335
 
#if 0
1336
 
            {
1337
 
                int i;
1338
 
                target_ulong ptr;
1339
 
                qemu_log("       code=");
1340
 
                ptr = env->segs[R_CS].base + env->eip;
1341
 
                for(i = 0; i < 16; i++) {
1342
 
                    qemu_log(" %02x", ldub(ptr + i));
1343
 
                }
1344
 
                qemu_log("\n");
1345
 
            }
1346
 
#endif
1347
 
            count++;
1348
 
        }
1349
 
    }
1350
 
    if (env->cr[0] & CR0_PE_MASK) {
1351
 
#if !defined(CONFIG_USER_ONLY)
1352
 
        if (env->hflags & HF_SVMI_MASK)
1353
 
            handle_even_inj(intno, is_int, error_code, is_hw, 0);
1354
 
#endif
1355
 
#ifdef TARGET_X86_64
1356
 
        if (env->hflags & HF_LMA_MASK) {
1357
 
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1358
 
        } else
1359
 
#endif
1360
 
        {
1361
 
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1362
 
        }
1363
 
    } else {
1364
 
#if !defined(CONFIG_USER_ONLY)
1365
 
        if (env->hflags & HF_SVMI_MASK)
1366
 
            handle_even_inj(intno, is_int, error_code, is_hw, 1);
1367
 
#endif
1368
 
        do_interrupt_real(intno, is_int, error_code, next_eip);
1369
 
    }
1370
 
 
1371
 
#if !defined(CONFIG_USER_ONLY)
1372
 
    if (env->hflags & HF_SVMI_MASK) {
1373
 
            uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1374
 
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
1375
 
    }
1376
 
#endif
1377
 
}
1378
 
 
1379
 
void do_interrupt(CPUState *env1)
1380
 
{
1381
 
    CPUState *saved_env;
1382
 
 
1383
 
    saved_env = env;
1384
 
    env = env1;
1385
 
#if defined(CONFIG_USER_ONLY)
1386
 
    /* if user mode only, we simulate a fake exception
1387
 
       which will be handled outside the cpu execution
1388
 
       loop */
1389
 
    do_interrupt_user(env->exception_index,
1390
 
                      env->exception_is_int,
1391
 
                      env->error_code,
1392
 
                      env->exception_next_eip);
1393
 
    /* successfully delivered */
1394
 
    env->old_exception = -1;
1395
 
#else
1396
 
    /* simulate a real cpu exception. On i386, it can
1397
 
       trigger new exceptions, but we do not handle
1398
 
       double or triple faults yet. */
1399
 
    do_interrupt_all(env->exception_index,
1400
 
                     env->exception_is_int,
1401
 
                     env->error_code,
1402
 
                     env->exception_next_eip, 0);
1403
 
    /* successfully delivered */
1404
 
    env->old_exception = -1;
1405
 
#endif
1406
 
    env = saved_env;
1407
 
}
1408
 
 
1409
 
void do_interrupt_x86_hardirq(CPUState *env1, int intno, int is_hw)
1410
 
{
1411
 
    CPUState *saved_env;
1412
 
 
1413
 
    saved_env = env;
1414
 
    env = env1;
1415
 
    do_interrupt_all(intno, 0, 0, 0, is_hw);
1416
 
    env = saved_env;
1417
 
}
1418
 
 
1419
 
/* This should come from sysemu.h - if we could include it here... */
1420
 
void qemu_system_reset_request(void);
1421
 
 
1422
 
/*
1423
 
 * Check nested exceptions and change to double or triple fault if
1424
 
 * needed. It should only be called, if this is not an interrupt.
1425
 
 * Returns the new exception number.
1426
 
 */
1427
 
static int check_exception(int intno, int *error_code)
1428
 
{
1429
 
    int first_contributory = env->old_exception == 0 ||
1430
 
                              (env->old_exception >= 10 &&
1431
 
                               env->old_exception <= 13);
1432
 
    int second_contributory = intno == 0 ||
1433
 
                               (intno >= 10 && intno <= 13);
1434
 
 
1435
 
    qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
1436
 
                env->old_exception, intno);
1437
 
 
1438
 
#if !defined(CONFIG_USER_ONLY)
1439
 
    if (env->old_exception == EXCP08_DBLE) {
1440
 
        if (env->hflags & HF_SVMI_MASK)
1441
 
            helper_vmexit(SVM_EXIT_SHUTDOWN, 0); /* does not return */
1442
 
 
1443
 
        qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1444
 
 
1445
 
        qemu_system_reset_request();
1446
 
        return EXCP_HLT;
1447
 
    }
1448
 
#endif
1449
 
 
1450
 
    if ((first_contributory && second_contributory)
1451
 
        || (env->old_exception == EXCP0E_PAGE &&
1452
 
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1453
 
        intno = EXCP08_DBLE;
1454
 
        *error_code = 0;
1455
 
    }
1456
 
 
1457
 
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1458
 
        (intno == EXCP08_DBLE))
1459
 
        env->old_exception = intno;
1460
 
 
1461
 
    return intno;
1462
 
}
1463
 
 
1464
 
/*
1465
 
 * Signal an interruption. It is executed in the main CPU loop.
1466
 
 * is_int is TRUE if coming from the int instruction. next_eip is the
1467
 
 * EIP value AFTER the interrupt instruction. It is only relevant if
1468
 
 * is_int is TRUE.
1469
 
 */
1470
 
static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
1471
 
                                          int next_eip_addend)
1472
 
{
1473
 
    if (!is_int) {
1474
 
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1475
 
        intno = check_exception(intno, &error_code);
1476
 
    } else {
1477
 
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1478
 
    }
1479
 
 
1480
 
    env->exception_index = intno;
1481
 
    env->error_code = error_code;
1482
 
    env->exception_is_int = is_int;
1483
 
    env->exception_next_eip = env->eip + next_eip_addend;
1484
 
    cpu_loop_exit(env);
1485
 
}
1486
 
 
1487
 
/* shortcuts to generate exceptions */
1488
 
 
1489
 
static void QEMU_NORETURN raise_exception_err(int exception_index,
1490
 
                                              int error_code)
1491
 
{
1492
 
    raise_interrupt(exception_index, 0, error_code, 0);
1493
 
}
1494
 
 
1495
 
void raise_exception_err_env(CPUState *nenv, int exception_index,
1496
 
                             int error_code)
1497
 
{
1498
 
    env = nenv;
1499
 
    raise_interrupt(exception_index, 0, error_code, 0);
1500
 
}
1501
 
 
1502
 
static void QEMU_NORETURN raise_exception(int exception_index)
1503
 
{
1504
 
    raise_interrupt(exception_index, 0, 0, 0);
1505
 
}
1506
 
 
1507
 
void raise_exception_env(int exception_index, CPUState *nenv)
1508
 
{
1509
 
    env = nenv;
1510
 
    raise_exception(exception_index);
1511
 
}
1512
 
/* SMM support */
1513
 
 
1514
 
#if defined(CONFIG_USER_ONLY)
1515
 
 
1516
 
void do_smm_enter(CPUState *env1)
1517
 
{
1518
 
}
1519
 
 
1520
 
void helper_rsm(void)
1521
 
{
1522
 
}
1523
 
 
1524
 
#else
1525
 
 
1526
 
#ifdef TARGET_X86_64
1527
 
#define SMM_REVISION_ID 0x00020064
1528
 
#else
1529
 
#define SMM_REVISION_ID 0x00020000
1530
 
#endif
1531
 
 
1532
 
void do_smm_enter(CPUState *env1)
1533
 
{
1534
 
    target_ulong sm_state;
1535
 
    SegmentCache *dt;
1536
 
    int i, offset;
1537
 
    CPUState *saved_env;
1538
 
 
1539
 
    saved_env = env;
1540
 
    env = env1;
1541
 
 
1542
 
    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
1543
 
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1544
 
 
1545
 
    env->hflags |= HF_SMM_MASK;
1546
 
    cpu_smm_update(env);
1547
 
 
1548
 
    sm_state = env->smbase + 0x8000;
1549
 
 
1550
 
#ifdef TARGET_X86_64
1551
 
    for(i = 0; i < 6; i++) {
1552
 
        dt = &env->segs[i];
1553
 
        offset = 0x7e00 + i * 16;
1554
 
        stw_phys(sm_state + offset, dt->selector);
1555
 
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1556
 
        stl_phys(sm_state + offset + 4, dt->limit);
1557
 
        stq_phys(sm_state + offset + 8, dt->base);
1558
 
    }
1559
 
 
1560
 
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1561
 
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1562
 
 
1563
 
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1564
 
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1565
 
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1566
 
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1567
 
 
1568
 
    stq_phys(sm_state + 0x7e88, env->idt.base);
1569
 
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1570
 
 
1571
 
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1572
 
    stq_phys(sm_state + 0x7e98, env->tr.base);
1573
 
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1574
 
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1575
 
 
1576
 
    stq_phys(sm_state + 0x7ed0, env->efer);
1577
 
 
1578
 
    stq_phys(sm_state + 0x7ff8, EAX);
1579
 
    stq_phys(sm_state + 0x7ff0, ECX);
1580
 
    stq_phys(sm_state + 0x7fe8, EDX);
1581
 
    stq_phys(sm_state + 0x7fe0, EBX);
1582
 
    stq_phys(sm_state + 0x7fd8, ESP);
1583
 
    stq_phys(sm_state + 0x7fd0, EBP);
1584
 
    stq_phys(sm_state + 0x7fc8, ESI);
1585
 
    stq_phys(sm_state + 0x7fc0, EDI);
1586
 
    for(i = 8; i < 16; i++)
1587
 
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1588
 
    stq_phys(sm_state + 0x7f78, env->eip);
1589
 
    stl_phys(sm_state + 0x7f70, compute_eflags());
1590
 
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1591
 
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1592
 
 
1593
 
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1594
 
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1595
 
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1596
 
 
1597
 
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1598
 
    stl_phys(sm_state + 0x7f00, env->smbase);
1599
 
#else
1600
 
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1601
 
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1602
 
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1603
 
    stl_phys(sm_state + 0x7ff0, env->eip);
1604
 
    stl_phys(sm_state + 0x7fec, EDI);
1605
 
    stl_phys(sm_state + 0x7fe8, ESI);
1606
 
    stl_phys(sm_state + 0x7fe4, EBP);
1607
 
    stl_phys(sm_state + 0x7fe0, ESP);
1608
 
    stl_phys(sm_state + 0x7fdc, EBX);
1609
 
    stl_phys(sm_state + 0x7fd8, EDX);
1610
 
    stl_phys(sm_state + 0x7fd4, ECX);
1611
 
    stl_phys(sm_state + 0x7fd0, EAX);
1612
 
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1613
 
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1614
 
 
1615
 
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1616
 
    stl_phys(sm_state + 0x7f64, env->tr.base);
1617
 
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1618
 
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1619
 
 
1620
 
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1621
 
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1622
 
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1623
 
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1624
 
 
1625
 
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1626
 
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1627
 
 
1628
 
    stl_phys(sm_state + 0x7f58, env->idt.base);
1629
 
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1630
 
 
1631
 
    for(i = 0; i < 6; i++) {
1632
 
        dt = &env->segs[i];
1633
 
        if (i < 3)
1634
 
            offset = 0x7f84 + i * 12;
1635
 
        else
1636
 
            offset = 0x7f2c + (i - 3) * 12;
1637
 
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1638
 
        stl_phys(sm_state + offset + 8, dt->base);
1639
 
        stl_phys(sm_state + offset + 4, dt->limit);
1640
 
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1641
 
    }
1642
 
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1643
 
 
1644
 
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1645
 
    stl_phys(sm_state + 0x7ef8, env->smbase);
1646
 
#endif
1647
 
    /* init SMM cpu state */
1648
 
 
1649
 
#ifdef TARGET_X86_64
1650
 
    cpu_load_efer(env, 0);
1651
 
#endif
1652
 
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1653
 
    env->eip = 0x00008000;
1654
 
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1655
 
                           0xffffffff, 0);
1656
 
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1657
 
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1658
 
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1659
 
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1660
 
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1661
 
 
1662
 
    cpu_x86_update_cr0(env,
1663
 
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1664
 
    cpu_x86_update_cr4(env, 0);
1665
 
    env->dr[7] = 0x00000400;
1666
 
    CC_OP = CC_OP_EFLAGS;
1667
 
    env = saved_env;
1668
 
}
1669
 
 
1670
 
void helper_rsm(void)
1671
 
{
1672
 
    target_ulong sm_state;
1673
 
    int i, offset;
1674
 
    uint32_t val;
1675
 
 
1676
 
    sm_state = env->smbase + 0x8000;
1677
 
#ifdef TARGET_X86_64
1678
 
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1679
 
 
1680
 
    for(i = 0; i < 6; i++) {
1681
 
        offset = 0x7e00 + i * 16;
1682
 
        cpu_x86_load_seg_cache(env, i,
1683
 
                               lduw_phys(sm_state + offset),
1684
 
                               ldq_phys(sm_state + offset + 8),
1685
 
                               ldl_phys(sm_state + offset + 4),
1686
 
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1687
 
    }
1688
 
 
1689
 
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1690
 
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1691
 
 
1692
 
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1693
 
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1694
 
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1695
 
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1696
 
 
1697
 
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1698
 
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1699
 
 
1700
 
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1701
 
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1702
 
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1703
 
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1704
 
 
1705
 
    EAX = ldq_phys(sm_state + 0x7ff8);
1706
 
    ECX = ldq_phys(sm_state + 0x7ff0);
1707
 
    EDX = ldq_phys(sm_state + 0x7fe8);
1708
 
    EBX = ldq_phys(sm_state + 0x7fe0);
1709
 
    ESP = ldq_phys(sm_state + 0x7fd8);
1710
 
    EBP = ldq_phys(sm_state + 0x7fd0);
1711
 
    ESI = ldq_phys(sm_state + 0x7fc8);
1712
 
    EDI = ldq_phys(sm_state + 0x7fc0);
1713
 
    for(i = 8; i < 16; i++)
1714
 
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1715
 
    env->eip = ldq_phys(sm_state + 0x7f78);
1716
 
    load_eflags(ldl_phys(sm_state + 0x7f70),
1717
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1718
 
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1719
 
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1720
 
 
1721
 
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1722
 
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1723
 
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1724
 
 
1725
 
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1726
 
    if (val & 0x20000) {
1727
 
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1728
 
    }
1729
 
#else
1730
 
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1731
 
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1732
 
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1733
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1734
 
    env->eip = ldl_phys(sm_state + 0x7ff0);
1735
 
    EDI = ldl_phys(sm_state + 0x7fec);
1736
 
    ESI = ldl_phys(sm_state + 0x7fe8);
1737
 
    EBP = ldl_phys(sm_state + 0x7fe4);
1738
 
    ESP = ldl_phys(sm_state + 0x7fe0);
1739
 
    EBX = ldl_phys(sm_state + 0x7fdc);
1740
 
    EDX = ldl_phys(sm_state + 0x7fd8);
1741
 
    ECX = ldl_phys(sm_state + 0x7fd4);
1742
 
    EAX = ldl_phys(sm_state + 0x7fd0);
1743
 
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1744
 
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1745
 
 
1746
 
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1747
 
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1748
 
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1749
 
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1750
 
 
1751
 
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1752
 
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1753
 
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1754
 
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1755
 
 
1756
 
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1757
 
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1758
 
 
1759
 
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1760
 
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1761
 
 
1762
 
    for(i = 0; i < 6; i++) {
1763
 
        if (i < 3)
1764
 
            offset = 0x7f84 + i * 12;
1765
 
        else
1766
 
            offset = 0x7f2c + (i - 3) * 12;
1767
 
        cpu_x86_load_seg_cache(env, i,
1768
 
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1769
 
                               ldl_phys(sm_state + offset + 8),
1770
 
                               ldl_phys(sm_state + offset + 4),
1771
 
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1772
 
    }
1773
 
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1774
 
 
1775
 
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1776
 
    if (val & 0x20000) {
1777
 
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1778
 
    }
1779
 
#endif
1780
 
    CC_OP = CC_OP_EFLAGS;
1781
 
    env->hflags &= ~HF_SMM_MASK;
1782
 
    cpu_smm_update(env);
1783
 
 
1784
 
    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
1785
 
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1786
 
}
1787
 
 
1788
 
#endif /* !CONFIG_USER_ONLY */
1789
 
 
1790
 
 
1791
 
/* division, flags are undefined */
1792
 
 
1793
 
void helper_divb_AL(target_ulong t0)
1794
 
{
1795
 
    unsigned int num, den, q, r;
1796
 
 
1797
 
    num = (EAX & 0xffff);
1798
 
    den = (t0 & 0xff);
1799
 
    if (den == 0) {
1800
 
        raise_exception(EXCP00_DIVZ);
1801
 
    }
1802
 
    q = (num / den);
1803
 
    if (q > 0xff)
1804
 
        raise_exception(EXCP00_DIVZ);
1805
 
    q &= 0xff;
1806
 
    r = (num % den) & 0xff;
1807
 
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1808
 
}
1809
 
 
1810
 
void helper_idivb_AL(target_ulong t0)
1811
 
{
1812
 
    int num, den, q, r;
1813
 
 
1814
 
    num = (int16_t)EAX;
1815
 
    den = (int8_t)t0;
1816
 
    if (den == 0) {
1817
 
        raise_exception(EXCP00_DIVZ);
1818
 
    }
1819
 
    q = (num / den);
1820
 
    if (q != (int8_t)q)
1821
 
        raise_exception(EXCP00_DIVZ);
1822
 
    q &= 0xff;
1823
 
    r = (num % den) & 0xff;
1824
 
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1825
 
}
1826
 
 
1827
 
void helper_divw_AX(target_ulong t0)
1828
 
{
1829
 
    unsigned int num, den, q, r;
1830
 
 
1831
 
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1832
 
    den = (t0 & 0xffff);
1833
 
    if (den == 0) {
1834
 
        raise_exception(EXCP00_DIVZ);
1835
 
    }
1836
 
    q = (num / den);
1837
 
    if (q > 0xffff)
1838
 
        raise_exception(EXCP00_DIVZ);
1839
 
    q &= 0xffff;
1840
 
    r = (num % den) & 0xffff;
1841
 
    EAX = (EAX & ~0xffff) | q;
1842
 
    EDX = (EDX & ~0xffff) | r;
1843
 
}
1844
 
 
1845
 
void helper_idivw_AX(target_ulong t0)
1846
 
{
1847
 
    int num, den, q, r;
1848
 
 
1849
 
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1850
 
    den = (int16_t)t0;
1851
 
    if (den == 0) {
1852
 
        raise_exception(EXCP00_DIVZ);
1853
 
    }
1854
 
    q = (num / den);
1855
 
    if (q != (int16_t)q)
1856
 
        raise_exception(EXCP00_DIVZ);
1857
 
    q &= 0xffff;
1858
 
    r = (num % den) & 0xffff;
1859
 
    EAX = (EAX & ~0xffff) | q;
1860
 
    EDX = (EDX & ~0xffff) | r;
1861
 
}
1862
 
 
1863
 
void helper_divl_EAX(target_ulong t0)
1864
 
{
1865
 
    unsigned int den, r;
1866
 
    uint64_t num, q;
1867
 
 
1868
 
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1869
 
    den = t0;
1870
 
    if (den == 0) {
1871
 
        raise_exception(EXCP00_DIVZ);
1872
 
    }
1873
 
    q = (num / den);
1874
 
    r = (num % den);
1875
 
    if (q > 0xffffffff)
1876
 
        raise_exception(EXCP00_DIVZ);
1877
 
    EAX = (uint32_t)q;
1878
 
    EDX = (uint32_t)r;
1879
 
}
1880
 
 
1881
 
void helper_idivl_EAX(target_ulong t0)
1882
 
{
1883
 
    int den, r;
1884
 
    int64_t num, q;
1885
 
 
1886
 
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1887
 
    den = t0;
1888
 
    if (den == 0) {
1889
 
        raise_exception(EXCP00_DIVZ);
1890
 
    }
1891
 
    q = (num / den);
1892
 
    r = (num % den);
1893
 
    if (q != (int32_t)q)
1894
 
        raise_exception(EXCP00_DIVZ);
1895
 
    EAX = (uint32_t)q;
1896
 
    EDX = (uint32_t)r;
1897
 
}
1898
 
 
1899
 
/* bcd */
1900
 
 
1901
 
/* XXX: exception */
1902
 
void helper_aam(int base)
1903
 
{
1904
 
    int al, ah;
1905
 
    al = EAX & 0xff;
1906
 
    ah = al / base;
1907
 
    al = al % base;
1908
 
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1909
 
    CC_DST = al;
1910
 
}
1911
 
 
1912
 
void helper_aad(int base)
1913
 
{
1914
 
    int al, ah;
1915
 
    al = EAX & 0xff;
1916
 
    ah = (EAX >> 8) & 0xff;
1917
 
    al = ((ah * base) + al) & 0xff;
1918
 
    EAX = (EAX & ~0xffff) | al;
1919
 
    CC_DST = al;
1920
 
}
1921
 
 
1922
 
void helper_aaa(void)
1923
 
{
1924
 
    int icarry;
1925
 
    int al, ah, af;
1926
 
    int eflags;
1927
 
 
1928
 
    eflags = helper_cc_compute_all(CC_OP);
1929
 
    af = eflags & CC_A;
1930
 
    al = EAX & 0xff;
1931
 
    ah = (EAX >> 8) & 0xff;
1932
 
 
1933
 
    icarry = (al > 0xf9);
1934
 
    if (((al & 0x0f) > 9 ) || af) {
1935
 
        al = (al + 6) & 0x0f;
1936
 
        ah = (ah + 1 + icarry) & 0xff;
1937
 
        eflags |= CC_C | CC_A;
1938
 
    } else {
1939
 
        eflags &= ~(CC_C | CC_A);
1940
 
        al &= 0x0f;
1941
 
    }
1942
 
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1943
 
    CC_SRC = eflags;
1944
 
}
1945
 
 
1946
 
void helper_aas(void)
1947
 
{
1948
 
    int icarry;
1949
 
    int al, ah, af;
1950
 
    int eflags;
1951
 
 
1952
 
    eflags = helper_cc_compute_all(CC_OP);
1953
 
    af = eflags & CC_A;
1954
 
    al = EAX & 0xff;
1955
 
    ah = (EAX >> 8) & 0xff;
1956
 
 
1957
 
    icarry = (al < 6);
1958
 
    if (((al & 0x0f) > 9 ) || af) {
1959
 
        al = (al - 6) & 0x0f;
1960
 
        ah = (ah - 1 - icarry) & 0xff;
1961
 
        eflags |= CC_C | CC_A;
1962
 
    } else {
1963
 
        eflags &= ~(CC_C | CC_A);
1964
 
        al &= 0x0f;
1965
 
    }
1966
 
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1967
 
    CC_SRC = eflags;
1968
 
}
1969
 
 
1970
 
void helper_daa(void)
1971
 
{
1972
 
    int old_al, al, af, cf;
1973
 
    int eflags;
1974
 
 
1975
 
    eflags = helper_cc_compute_all(CC_OP);
1976
 
    cf = eflags & CC_C;
1977
 
    af = eflags & CC_A;
1978
 
    old_al = al = EAX & 0xff;
1979
 
 
1980
 
    eflags = 0;
1981
 
    if (((al & 0x0f) > 9 ) || af) {
1982
 
        al = (al + 6) & 0xff;
1983
 
        eflags |= CC_A;
1984
 
    }
1985
 
    if ((old_al > 0x99) || cf) {
1986
 
        al = (al + 0x60) & 0xff;
1987
 
        eflags |= CC_C;
1988
 
    }
1989
 
    EAX = (EAX & ~0xff) | al;
1990
 
    /* well, speed is not an issue here, so we compute the flags by hand */
1991
 
    eflags |= (al == 0) << 6; /* zf */
1992
 
    eflags |= parity_table[al]; /* pf */
1993
 
    eflags |= (al & 0x80); /* sf */
1994
 
    CC_SRC = eflags;
1995
 
}
1996
 
 
1997
 
void helper_das(void)
1998
 
{
1999
 
    int al, al1, af, cf;
2000
 
    int eflags;
2001
 
 
2002
 
    eflags = helper_cc_compute_all(CC_OP);
2003
 
    cf = eflags & CC_C;
2004
 
    af = eflags & CC_A;
2005
 
    al = EAX & 0xff;
2006
 
 
2007
 
    eflags = 0;
2008
 
    al1 = al;
2009
 
    if (((al & 0x0f) > 9 ) || af) {
2010
 
        eflags |= CC_A;
2011
 
        if (al < 6 || cf)
2012
 
            eflags |= CC_C;
2013
 
        al = (al - 6) & 0xff;
2014
 
    }
2015
 
    if ((al1 > 0x99) || cf) {
2016
 
        al = (al - 0x60) & 0xff;
2017
 
        eflags |= CC_C;
2018
 
    }
2019
 
    EAX = (EAX & ~0xff) | al;
2020
 
    /* well, speed is not an issue here, so we compute the flags by hand */
2021
 
    eflags |= (al == 0) << 6; /* zf */
2022
 
    eflags |= parity_table[al]; /* pf */
2023
 
    eflags |= (al & 0x80); /* sf */
2024
 
    CC_SRC = eflags;
2025
 
}
2026
 
 
2027
 
void helper_into(int next_eip_addend)
2028
 
{
2029
 
    int eflags;
2030
 
    eflags = helper_cc_compute_all(CC_OP);
2031
 
    if (eflags & CC_O) {
2032
 
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
2033
 
    }
2034
 
}
2035
 
 
2036
 
void helper_cmpxchg8b(target_ulong a0)
2037
 
{
2038
 
    uint64_t d;
2039
 
    int eflags;
2040
 
 
2041
 
    eflags = helper_cc_compute_all(CC_OP);
2042
 
    d = ldq(a0);
2043
 
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
2044
 
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
2045
 
        eflags |= CC_Z;
2046
 
    } else {
2047
 
        /* always do the store */
2048
 
        stq(a0, d); 
2049
 
        EDX = (uint32_t)(d >> 32);
2050
 
        EAX = (uint32_t)d;
2051
 
        eflags &= ~CC_Z;
2052
 
    }
2053
 
    CC_SRC = eflags;
2054
 
}
2055
 
 
2056
 
#ifdef TARGET_X86_64
2057
 
void helper_cmpxchg16b(target_ulong a0)
2058
 
{
2059
 
    uint64_t d0, d1;
2060
 
    int eflags;
2061
 
 
2062
 
    if ((a0 & 0xf) != 0)
2063
 
        raise_exception(EXCP0D_GPF);
2064
 
    eflags = helper_cc_compute_all(CC_OP);
2065
 
    d0 = ldq(a0);
2066
 
    d1 = ldq(a0 + 8);
2067
 
    if (d0 == EAX && d1 == EDX) {
2068
 
        stq(a0, EBX);
2069
 
        stq(a0 + 8, ECX);
2070
 
        eflags |= CC_Z;
2071
 
    } else {
2072
 
        /* always do the store */
2073
 
        stq(a0, d0); 
2074
 
        stq(a0 + 8, d1); 
2075
 
        EDX = d1;
2076
 
        EAX = d0;
2077
 
        eflags &= ~CC_Z;
2078
 
    }
2079
 
    CC_SRC = eflags;
2080
 
}
2081
 
#endif
2082
 
 
2083
 
void helper_single_step(void)
2084
 
{
2085
 
#ifndef CONFIG_USER_ONLY
2086
 
    check_hw_breakpoints(env, 1);
2087
 
    env->dr[6] |= DR6_BS;
2088
 
#endif
2089
 
    raise_exception(EXCP01_DB);
2090
 
}
2091
 
 
2092
 
void helper_cpuid(void)
2093
 
{
2094
 
    uint32_t eax, ebx, ecx, edx;
2095
 
 
2096
 
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
2097
 
 
2098
 
    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
2099
 
    EAX = eax;
2100
 
    EBX = ebx;
2101
 
    ECX = ecx;
2102
 
    EDX = edx;
2103
 
}
2104
 
 
2105
 
void helper_enter_level(int level, int data32, target_ulong t1)
2106
 
{
2107
 
    target_ulong ssp;
2108
 
    uint32_t esp_mask, esp, ebp;
2109
 
 
2110
 
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2111
 
    ssp = env->segs[R_SS].base;
2112
 
    ebp = EBP;
2113
 
    esp = ESP;
2114
 
    if (data32) {
2115
 
        /* 32 bit */
2116
 
        esp -= 4;
2117
 
        while (--level) {
2118
 
            esp -= 4;
2119
 
            ebp -= 4;
2120
 
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
2121
 
        }
2122
 
        esp -= 4;
2123
 
        stl(ssp + (esp & esp_mask), t1);
2124
 
    } else {
2125
 
        /* 16 bit */
2126
 
        esp -= 2;
2127
 
        while (--level) {
2128
 
            esp -= 2;
2129
 
            ebp -= 2;
2130
 
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
2131
 
        }
2132
 
        esp -= 2;
2133
 
        stw(ssp + (esp & esp_mask), t1);
2134
 
    }
2135
 
}
2136
 
 
2137
 
#ifdef TARGET_X86_64
2138
 
void helper_enter64_level(int level, int data64, target_ulong t1)
2139
 
{
2140
 
    target_ulong esp, ebp;
2141
 
    ebp = EBP;
2142
 
    esp = ESP;
2143
 
 
2144
 
    if (data64) {
2145
 
        /* 64 bit */
2146
 
        esp -= 8;
2147
 
        while (--level) {
2148
 
            esp -= 8;
2149
 
            ebp -= 8;
2150
 
            stq(esp, ldq(ebp));
2151
 
        }
2152
 
        esp -= 8;
2153
 
        stq(esp, t1);
2154
 
    } else {
2155
 
        /* 16 bit */
2156
 
        esp -= 2;
2157
 
        while (--level) {
2158
 
            esp -= 2;
2159
 
            ebp -= 2;
2160
 
            stw(esp, lduw(ebp));
2161
 
        }
2162
 
        esp -= 2;
2163
 
        stw(esp, t1);
2164
 
    }
2165
 
}
2166
 
#endif
2167
 
 
2168
 
void helper_lldt(int selector)
2169
 
{
2170
 
    SegmentCache *dt;
2171
 
    uint32_t e1, e2;
2172
 
    int index, entry_limit;
2173
 
    target_ulong ptr;
2174
 
 
2175
 
    selector &= 0xffff;
2176
 
    if ((selector & 0xfffc) == 0) {
2177
 
        /* XXX: NULL selector case: invalid LDT */
2178
 
        env->ldt.base = 0;
2179
 
        env->ldt.limit = 0;
2180
 
    } else {
2181
 
        if (selector & 0x4)
2182
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2183
 
        dt = &env->gdt;
2184
 
        index = selector & ~7;
2185
 
#ifdef TARGET_X86_64
2186
 
        if (env->hflags & HF_LMA_MASK)
2187
 
            entry_limit = 15;
2188
 
        else
2189
 
#endif
2190
 
            entry_limit = 7;
2191
 
        if ((index + entry_limit) > dt->limit)
2192
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2193
 
        ptr = dt->base + index;
2194
 
        e1 = ldl_kernel(ptr);
2195
 
        e2 = ldl_kernel(ptr + 4);
2196
 
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2197
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2198
 
        if (!(e2 & DESC_P_MASK))
2199
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2200
 
#ifdef TARGET_X86_64
2201
 
        if (env->hflags & HF_LMA_MASK) {
2202
 
            uint32_t e3;
2203
 
            e3 = ldl_kernel(ptr + 8);
2204
 
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2205
 
            env->ldt.base |= (target_ulong)e3 << 32;
2206
 
        } else
2207
 
#endif
2208
 
        {
2209
 
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2210
 
        }
2211
 
    }
2212
 
    env->ldt.selector = selector;
2213
 
}
2214
 
 
2215
 
void helper_ltr(int selector)
2216
 
{
2217
 
    SegmentCache *dt;
2218
 
    uint32_t e1, e2;
2219
 
    int index, type, entry_limit;
2220
 
    target_ulong ptr;
2221
 
 
2222
 
    selector &= 0xffff;
2223
 
    if ((selector & 0xfffc) == 0) {
2224
 
        /* NULL selector case: invalid TR */
2225
 
        env->tr.base = 0;
2226
 
        env->tr.limit = 0;
2227
 
        env->tr.flags = 0;
2228
 
    } else {
2229
 
        if (selector & 0x4)
2230
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2231
 
        dt = &env->gdt;
2232
 
        index = selector & ~7;
2233
 
#ifdef TARGET_X86_64
2234
 
        if (env->hflags & HF_LMA_MASK)
2235
 
            entry_limit = 15;
2236
 
        else
2237
 
#endif
2238
 
            entry_limit = 7;
2239
 
        if ((index + entry_limit) > dt->limit)
2240
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2241
 
        ptr = dt->base + index;
2242
 
        e1 = ldl_kernel(ptr);
2243
 
        e2 = ldl_kernel(ptr + 4);
2244
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2245
 
        if ((e2 & DESC_S_MASK) ||
2246
 
            (type != 1 && type != 9))
2247
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2248
 
        if (!(e2 & DESC_P_MASK))
2249
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2250
 
#ifdef TARGET_X86_64
2251
 
        if (env->hflags & HF_LMA_MASK) {
2252
 
            uint32_t e3, e4;
2253
 
            e3 = ldl_kernel(ptr + 8);
2254
 
            e4 = ldl_kernel(ptr + 12);
2255
 
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2256
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2257
 
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2258
 
            env->tr.base |= (target_ulong)e3 << 32;
2259
 
        } else
2260
 
#endif
2261
 
        {
2262
 
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2263
 
        }
2264
 
        e2 |= DESC_TSS_BUSY_MASK;
2265
 
        stl_kernel(ptr + 4, e2);
2266
 
    }
2267
 
    env->tr.selector = selector;
2268
 
}
2269
 
 
2270
 
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2271
 
void helper_load_seg(int seg_reg, int selector)
2272
 
{
2273
 
    uint32_t e1, e2;
2274
 
    int cpl, dpl, rpl;
2275
 
    SegmentCache *dt;
2276
 
    int index;
2277
 
    target_ulong ptr;
2278
 
 
2279
 
    selector &= 0xffff;
2280
 
    cpl = env->hflags & HF_CPL_MASK;
2281
 
    if ((selector & 0xfffc) == 0) {
2282
 
        /* null selector case */
2283
 
        if (seg_reg == R_SS
2284
 
#ifdef TARGET_X86_64
2285
 
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2286
 
#endif
2287
 
            )
2288
 
            raise_exception_err(EXCP0D_GPF, 0);
2289
 
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2290
 
    } else {
2291
 
 
2292
 
        if (selector & 0x4)
2293
 
            dt = &env->ldt;
2294
 
        else
2295
 
            dt = &env->gdt;
2296
 
        index = selector & ~7;
2297
 
        if ((index + 7) > dt->limit)
2298
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2299
 
        ptr = dt->base + index;
2300
 
        e1 = ldl_kernel(ptr);
2301
 
        e2 = ldl_kernel(ptr + 4);
2302
 
 
2303
 
        if (!(e2 & DESC_S_MASK))
2304
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2305
 
        rpl = selector & 3;
2306
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2307
 
        if (seg_reg == R_SS) {
2308
 
            /* must be writable segment */
2309
 
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2310
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2311
 
            if (rpl != cpl || dpl != cpl)
2312
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2313
 
        } else {
2314
 
            /* must be readable segment */
2315
 
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2316
 
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2317
 
 
2318
 
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2319
 
                /* if not conforming code, test rights */
2320
 
                if (dpl < cpl || dpl < rpl)
2321
 
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2322
 
            }
2323
 
        }
2324
 
 
2325
 
        if (!(e2 & DESC_P_MASK)) {
2326
 
            if (seg_reg == R_SS)
2327
 
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2328
 
            else
2329
 
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2330
 
        }
2331
 
 
2332
 
        /* set the access bit if not already set */
2333
 
        if (!(e2 & DESC_A_MASK)) {
2334
 
            e2 |= DESC_A_MASK;
2335
 
            stl_kernel(ptr + 4, e2);
2336
 
        }
2337
 
 
2338
 
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2339
 
                       get_seg_base(e1, e2),
2340
 
                       get_seg_limit(e1, e2),
2341
 
                       e2);
2342
 
#if 0
2343
 
        qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2344
 
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2345
 
#endif
2346
 
    }
2347
 
}
2348
 
 
2349
 
/* protected mode jump */
2350
 
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2351
 
                           int next_eip_addend)
2352
 
{
2353
 
    int gate_cs, type;
2354
 
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2355
 
    target_ulong next_eip;
2356
 
 
2357
 
    if ((new_cs & 0xfffc) == 0)
2358
 
        raise_exception_err(EXCP0D_GPF, 0);
2359
 
    if (load_segment(&e1, &e2, new_cs) != 0)
2360
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2361
 
    cpl = env->hflags & HF_CPL_MASK;
2362
 
    if (e2 & DESC_S_MASK) {
2363
 
        if (!(e2 & DESC_CS_MASK))
2364
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2365
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2366
 
        if (e2 & DESC_C_MASK) {
2367
 
            /* conforming code segment */
2368
 
            if (dpl > cpl)
2369
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2370
 
        } else {
2371
 
            /* non conforming code segment */
2372
 
            rpl = new_cs & 3;
2373
 
            if (rpl > cpl)
2374
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2375
 
            if (dpl != cpl)
2376
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2377
 
        }
2378
 
        if (!(e2 & DESC_P_MASK))
2379
 
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2380
 
        limit = get_seg_limit(e1, e2);
2381
 
        if (new_eip > limit &&
2382
 
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2383
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2384
 
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2385
 
                       get_seg_base(e1, e2), limit, e2);
2386
 
        EIP = new_eip;
2387
 
    } else {
2388
 
        /* jump to call or task gate */
2389
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2390
 
        rpl = new_cs & 3;
2391
 
        cpl = env->hflags & HF_CPL_MASK;
2392
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2393
 
        switch(type) {
2394
 
        case 1: /* 286 TSS */
2395
 
        case 9: /* 386 TSS */
2396
 
        case 5: /* task gate */
2397
 
            if (dpl < cpl || dpl < rpl)
2398
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2399
 
            next_eip = env->eip + next_eip_addend;
2400
 
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2401
 
            CC_OP = CC_OP_EFLAGS;
2402
 
            break;
2403
 
        case 4: /* 286 call gate */
2404
 
        case 12: /* 386 call gate */
2405
 
            if ((dpl < cpl) || (dpl < rpl))
2406
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2407
 
            if (!(e2 & DESC_P_MASK))
2408
 
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2409
 
            gate_cs = e1 >> 16;
2410
 
            new_eip = (e1 & 0xffff);
2411
 
            if (type == 12)
2412
 
                new_eip |= (e2 & 0xffff0000);
2413
 
            if (load_segment(&e1, &e2, gate_cs) != 0)
2414
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2415
 
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2416
 
            /* must be code segment */
2417
 
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2418
 
                 (DESC_S_MASK | DESC_CS_MASK)))
2419
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2420
 
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2421
 
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2422
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2423
 
            if (!(e2 & DESC_P_MASK))
2424
 
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2425
 
            limit = get_seg_limit(e1, e2);
2426
 
            if (new_eip > limit)
2427
 
                raise_exception_err(EXCP0D_GPF, 0);
2428
 
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2429
 
                                   get_seg_base(e1, e2), limit, e2);
2430
 
            EIP = new_eip;
2431
 
            break;
2432
 
        default:
2433
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2434
 
            break;
2435
 
        }
2436
 
    }
2437
 
}
2438
 
 
2439
 
/* real mode call */
2440
 
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2441
 
                       int shift, int next_eip)
2442
 
{
2443
 
    int new_eip;
2444
 
    uint32_t esp, esp_mask;
2445
 
    target_ulong ssp;
2446
 
 
2447
 
    new_eip = new_eip1;
2448
 
    esp = ESP;
2449
 
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2450
 
    ssp = env->segs[R_SS].base;
2451
 
    if (shift) {
2452
 
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2453
 
        PUSHL(ssp, esp, esp_mask, next_eip);
2454
 
    } else {
2455
 
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2456
 
        PUSHW(ssp, esp, esp_mask, next_eip);
2457
 
    }
2458
 
 
2459
 
    SET_ESP(esp, esp_mask);
2460
 
    env->eip = new_eip;
2461
 
    env->segs[R_CS].selector = new_cs;
2462
 
    env->segs[R_CS].base = (new_cs << 4);
2463
 
}
2464
 
 
2465
 
/* protected mode call */
2466
 
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2467
 
                            int shift, int next_eip_addend)
2468
 
{
2469
 
    int new_stack, i;
2470
 
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2471
 
    uint32_t ss = 0, ss_e1 = 0, ss_e2 = 0, sp, type, ss_dpl, sp_mask;
2472
 
    uint32_t val, limit, old_sp_mask;
2473
 
    target_ulong ssp, old_ssp, next_eip;
2474
 
 
2475
 
    next_eip = env->eip + next_eip_addend;
2476
 
    LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
2477
 
    LOG_PCALL_STATE(env);
2478
 
    if ((new_cs & 0xfffc) == 0)
2479
 
        raise_exception_err(EXCP0D_GPF, 0);
2480
 
    if (load_segment(&e1, &e2, new_cs) != 0)
2481
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2482
 
    cpl = env->hflags & HF_CPL_MASK;
2483
 
    LOG_PCALL("desc=%08x:%08x\n", e1, e2);
2484
 
    if (e2 & DESC_S_MASK) {
2485
 
        if (!(e2 & DESC_CS_MASK))
2486
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2487
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2488
 
        if (e2 & DESC_C_MASK) {
2489
 
            /* conforming code segment */
2490
 
            if (dpl > cpl)
2491
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2492
 
        } else {
2493
 
            /* non conforming code segment */
2494
 
            rpl = new_cs & 3;
2495
 
            if (rpl > cpl)
2496
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2497
 
            if (dpl != cpl)
2498
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2499
 
        }
2500
 
        if (!(e2 & DESC_P_MASK))
2501
 
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2502
 
 
2503
 
#ifdef TARGET_X86_64
2504
 
        /* XXX: check 16/32 bit cases in long mode */
2505
 
        if (shift == 2) {
2506
 
            target_ulong rsp;
2507
 
            /* 64 bit case */
2508
 
            rsp = ESP;
2509
 
            PUSHQ(rsp, env->segs[R_CS].selector);
2510
 
            PUSHQ(rsp, next_eip);
2511
 
            /* from this point, not restartable */
2512
 
            ESP = rsp;
2513
 
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2514
 
                                   get_seg_base(e1, e2),
2515
 
                                   get_seg_limit(e1, e2), e2);
2516
 
            EIP = new_eip;
2517
 
        } else
2518
 
#endif
2519
 
        {
2520
 
            sp = ESP;
2521
 
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2522
 
            ssp = env->segs[R_SS].base;
2523
 
            if (shift) {
2524
 
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2525
 
                PUSHL(ssp, sp, sp_mask, next_eip);
2526
 
            } else {
2527
 
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2528
 
                PUSHW(ssp, sp, sp_mask, next_eip);
2529
 
            }
2530
 
 
2531
 
            limit = get_seg_limit(e1, e2);
2532
 
            if (new_eip > limit)
2533
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2534
 
            /* from this point, not restartable */
2535
 
            SET_ESP(sp, sp_mask);
2536
 
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2537
 
                                   get_seg_base(e1, e2), limit, e2);
2538
 
            EIP = new_eip;
2539
 
        }
2540
 
    } else {
2541
 
        /* check gate type */
2542
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2543
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2544
 
        rpl = new_cs & 3;
2545
 
        switch(type) {
2546
 
        case 1: /* available 286 TSS */
2547
 
        case 9: /* available 386 TSS */
2548
 
        case 5: /* task gate */
2549
 
            if (dpl < cpl || dpl < rpl)
2550
 
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2551
 
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2552
 
            CC_OP = CC_OP_EFLAGS;
2553
 
            return;
2554
 
        case 4: /* 286 call gate */
2555
 
        case 12: /* 386 call gate */
2556
 
            break;
2557
 
        default:
2558
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2559
 
            break;
2560
 
        }
2561
 
        shift = type >> 3;
2562
 
 
2563
 
        if (dpl < cpl || dpl < rpl)
2564
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2565
 
        /* check valid bit */
2566
 
        if (!(e2 & DESC_P_MASK))
2567
 
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2568
 
        selector = e1 >> 16;
2569
 
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2570
 
        param_count = e2 & 0x1f;
2571
 
        if ((selector & 0xfffc) == 0)
2572
 
            raise_exception_err(EXCP0D_GPF, 0);
2573
 
 
2574
 
        if (load_segment(&e1, &e2, selector) != 0)
2575
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2576
 
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2577
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2578
 
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2579
 
        if (dpl > cpl)
2580
 
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2581
 
        if (!(e2 & DESC_P_MASK))
2582
 
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2583
 
 
2584
 
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2585
 
            /* to inner privilege */
2586
 
            get_ss_esp_from_tss(&ss, &sp, dpl);
2587
 
            LOG_PCALL("new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2588
 
                        ss, sp, param_count, ESP);
2589
 
            if ((ss & 0xfffc) == 0)
2590
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2591
 
            if ((ss & 3) != dpl)
2592
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2593
 
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2594
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2595
 
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2596
 
            if (ss_dpl != dpl)
2597
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2598
 
            if (!(ss_e2 & DESC_S_MASK) ||
2599
 
                (ss_e2 & DESC_CS_MASK) ||
2600
 
                !(ss_e2 & DESC_W_MASK))
2601
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2602
 
            if (!(ss_e2 & DESC_P_MASK))
2603
 
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2604
 
 
2605
 
            //            push_size = ((param_count * 2) + 8) << shift;
2606
 
 
2607
 
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2608
 
            old_ssp = env->segs[R_SS].base;
2609
 
 
2610
 
            sp_mask = get_sp_mask(ss_e2);
2611
 
            ssp = get_seg_base(ss_e1, ss_e2);
2612
 
            if (shift) {
2613
 
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2614
 
                PUSHL(ssp, sp, sp_mask, ESP);
2615
 
                for(i = param_count - 1; i >= 0; i--) {
2616
 
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2617
 
                    PUSHL(ssp, sp, sp_mask, val);
2618
 
                }
2619
 
            } else {
2620
 
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2621
 
                PUSHW(ssp, sp, sp_mask, ESP);
2622
 
                for(i = param_count - 1; i >= 0; i--) {
2623
 
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2624
 
                    PUSHW(ssp, sp, sp_mask, val);
2625
 
                }
2626
 
            }
2627
 
            new_stack = 1;
2628
 
        } else {
2629
 
            /* to same privilege */
2630
 
            sp = ESP;
2631
 
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2632
 
            ssp = env->segs[R_SS].base;
2633
 
            //            push_size = (4 << shift);
2634
 
            new_stack = 0;
2635
 
        }
2636
 
 
2637
 
        if (shift) {
2638
 
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2639
 
            PUSHL(ssp, sp, sp_mask, next_eip);
2640
 
        } else {
2641
 
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2642
 
            PUSHW(ssp, sp, sp_mask, next_eip);
2643
 
        }
2644
 
 
2645
 
        /* from this point, not restartable */
2646
 
 
2647
 
        if (new_stack) {
2648
 
            ss = (ss & ~3) | dpl;
2649
 
            cpu_x86_load_seg_cache(env, R_SS, ss,
2650
 
                                   ssp,
2651
 
                                   get_seg_limit(ss_e1, ss_e2),
2652
 
                                   ss_e2);
2653
 
        }
2654
 
 
2655
 
        selector = (selector & ~3) | dpl;
2656
 
        cpu_x86_load_seg_cache(env, R_CS, selector,
2657
 
                       get_seg_base(e1, e2),
2658
 
                       get_seg_limit(e1, e2),
2659
 
                       e2);
2660
 
        cpu_x86_set_cpl(env, dpl);
2661
 
        SET_ESP(sp, sp_mask);
2662
 
        EIP = offset;
2663
 
    }
2664
 
}
2665
 
 
2666
 
/* real and vm86 mode iret */
2667
 
void helper_iret_real(int shift)
2668
 
{
2669
 
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2670
 
    target_ulong ssp;
2671
 
    int eflags_mask;
2672
 
 
2673
 
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2674
 
    sp = ESP;
2675
 
    ssp = env->segs[R_SS].base;
2676
 
    if (shift == 1) {
2677
 
        /* 32 bits */
2678
 
        POPL(ssp, sp, sp_mask, new_eip);
2679
 
        POPL(ssp, sp, sp_mask, new_cs);
2680
 
        new_cs &= 0xffff;
2681
 
        POPL(ssp, sp, sp_mask, new_eflags);
2682
 
    } else {
2683
 
        /* 16 bits */
2684
 
        POPW(ssp, sp, sp_mask, new_eip);
2685
 
        POPW(ssp, sp, sp_mask, new_cs);
2686
 
        POPW(ssp, sp, sp_mask, new_eflags);
2687
 
    }
2688
 
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2689
 
    env->segs[R_CS].selector = new_cs;
2690
 
    env->segs[R_CS].base = (new_cs << 4);
2691
 
    env->eip = new_eip;
2692
 
    if (env->eflags & VM_MASK)
2693
 
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2694
 
    else
2695
 
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2696
 
    if (shift == 0)
2697
 
        eflags_mask &= 0xffff;
2698
 
    load_eflags(new_eflags, eflags_mask);
2699
 
    env->hflags2 &= ~HF2_NMI_MASK;
2700
 
}
2701
 
 
2702
 
static inline void validate_seg(int seg_reg, int cpl)
2703
 
{
2704
 
    int dpl;
2705
 
    uint32_t e2;
2706
 
 
2707
 
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2708
 
       they may still contain a valid base. I would be interested to
2709
 
       know how a real x86_64 CPU behaves */
2710
 
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2711
 
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2712
 
        return;
2713
 
 
2714
 
    e2 = env->segs[seg_reg].flags;
2715
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2716
 
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2717
 
        /* data or non conforming code segment */
2718
 
        if (dpl < cpl) {
2719
 
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2720
 
        }
2721
 
    }
2722
 
}
2723
 
 
2724
 
/* protected mode iret */
2725
 
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2726
 
{
2727
 
    uint32_t new_cs, new_eflags, new_ss;
2728
 
    uint32_t new_es, new_ds, new_fs, new_gs;
2729
 
    uint32_t e1, e2, ss_e1, ss_e2;
2730
 
    int cpl, dpl, rpl, eflags_mask, iopl;
2731
 
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2732
 
 
2733
 
#ifdef TARGET_X86_64
2734
 
    if (shift == 2)
2735
 
        sp_mask = -1;
2736
 
    else
2737
 
#endif
2738
 
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2739
 
    sp = ESP;
2740
 
    ssp = env->segs[R_SS].base;
2741
 
    new_eflags = 0; /* avoid warning */
2742
 
#ifdef TARGET_X86_64
2743
 
    if (shift == 2) {
2744
 
        POPQ(sp, new_eip);
2745
 
        POPQ(sp, new_cs);
2746
 
        new_cs &= 0xffff;
2747
 
        if (is_iret) {
2748
 
            POPQ(sp, new_eflags);
2749
 
        }
2750
 
    } else
2751
 
#endif
2752
 
    if (shift == 1) {
2753
 
        /* 32 bits */
2754
 
        POPL(ssp, sp, sp_mask, new_eip);
2755
 
        POPL(ssp, sp, sp_mask, new_cs);
2756
 
        new_cs &= 0xffff;
2757
 
        if (is_iret) {
2758
 
            POPL(ssp, sp, sp_mask, new_eflags);
2759
 
            if (new_eflags & VM_MASK)
2760
 
                goto return_to_vm86;
2761
 
        }
2762
 
    } else {
2763
 
        /* 16 bits */
2764
 
        POPW(ssp, sp, sp_mask, new_eip);
2765
 
        POPW(ssp, sp, sp_mask, new_cs);
2766
 
        if (is_iret)
2767
 
            POPW(ssp, sp, sp_mask, new_eflags);
2768
 
    }
2769
 
    LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2770
 
              new_cs, new_eip, shift, addend);
2771
 
    LOG_PCALL_STATE(env);
2772
 
    if ((new_cs & 0xfffc) == 0)
2773
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2774
 
    if (load_segment(&e1, &e2, new_cs) != 0)
2775
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2776
 
    if (!(e2 & DESC_S_MASK) ||
2777
 
        !(e2 & DESC_CS_MASK))
2778
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2779
 
    cpl = env->hflags & HF_CPL_MASK;
2780
 
    rpl = new_cs & 3;
2781
 
    if (rpl < cpl)
2782
 
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2783
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2784
 
    if (e2 & DESC_C_MASK) {
2785
 
        if (dpl > rpl)
2786
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2787
 
    } else {
2788
 
        if (dpl != rpl)
2789
 
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2790
 
    }
2791
 
    if (!(e2 & DESC_P_MASK))
2792
 
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2793
 
 
2794
 
    sp += addend;
2795
 
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2796
 
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2797
 
        /* return to same privilege level */
2798
 
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2799
 
                       get_seg_base(e1, e2),
2800
 
                       get_seg_limit(e1, e2),
2801
 
                       e2);
2802
 
    } else {
2803
 
        /* return to different privilege level */
2804
 
#ifdef TARGET_X86_64
2805
 
        if (shift == 2) {
2806
 
            POPQ(sp, new_esp);
2807
 
            POPQ(sp, new_ss);
2808
 
            new_ss &= 0xffff;
2809
 
        } else
2810
 
#endif
2811
 
        if (shift == 1) {
2812
 
            /* 32 bits */
2813
 
            POPL(ssp, sp, sp_mask, new_esp);
2814
 
            POPL(ssp, sp, sp_mask, new_ss);
2815
 
            new_ss &= 0xffff;
2816
 
        } else {
2817
 
            /* 16 bits */
2818
 
            POPW(ssp, sp, sp_mask, new_esp);
2819
 
            POPW(ssp, sp, sp_mask, new_ss);
2820
 
        }
2821
 
        LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",
2822
 
                    new_ss, new_esp);
2823
 
        if ((new_ss & 0xfffc) == 0) {
2824
 
#ifdef TARGET_X86_64
2825
 
            /* NULL ss is allowed in long mode if cpl != 3*/
2826
 
            /* XXX: test CS64 ? */
2827
 
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2828
 
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2829
 
                                       0, 0xffffffff,
2830
 
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2831
 
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2832
 
                                       DESC_W_MASK | DESC_A_MASK);
2833
 
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2834
 
            } else
2835
 
#endif
2836
 
            {
2837
 
                raise_exception_err(EXCP0D_GPF, 0);
2838
 
            }
2839
 
        } else {
2840
 
            if ((new_ss & 3) != rpl)
2841
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2842
 
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2843
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2844
 
            if (!(ss_e2 & DESC_S_MASK) ||
2845
 
                (ss_e2 & DESC_CS_MASK) ||
2846
 
                !(ss_e2 & DESC_W_MASK))
2847
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2848
 
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2849
 
            if (dpl != rpl)
2850
 
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2851
 
            if (!(ss_e2 & DESC_P_MASK))
2852
 
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2853
 
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2854
 
                                   get_seg_base(ss_e1, ss_e2),
2855
 
                                   get_seg_limit(ss_e1, ss_e2),
2856
 
                                   ss_e2);
2857
 
        }
2858
 
 
2859
 
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2860
 
                       get_seg_base(e1, e2),
2861
 
                       get_seg_limit(e1, e2),
2862
 
                       e2);
2863
 
        cpu_x86_set_cpl(env, rpl);
2864
 
        sp = new_esp;
2865
 
#ifdef TARGET_X86_64
2866
 
        if (env->hflags & HF_CS64_MASK)
2867
 
            sp_mask = -1;
2868
 
        else
2869
 
#endif
2870
 
            sp_mask = get_sp_mask(ss_e2);
2871
 
 
2872
 
        /* validate data segments */
2873
 
        validate_seg(R_ES, rpl);
2874
 
        validate_seg(R_DS, rpl);
2875
 
        validate_seg(R_FS, rpl);
2876
 
        validate_seg(R_GS, rpl);
2877
 
 
2878
 
        sp += addend;
2879
 
    }
2880
 
    SET_ESP(sp, sp_mask);
2881
 
    env->eip = new_eip;
2882
 
    if (is_iret) {
2883
 
        /* NOTE: 'cpl' is the _old_ CPL */
2884
 
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2885
 
        if (cpl == 0)
2886
 
            eflags_mask |= IOPL_MASK;
2887
 
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2888
 
        if (cpl <= iopl)
2889
 
            eflags_mask |= IF_MASK;
2890
 
        if (shift == 0)
2891
 
            eflags_mask &= 0xffff;
2892
 
        load_eflags(new_eflags, eflags_mask);
2893
 
    }
2894
 
    return;
2895
 
 
2896
 
 return_to_vm86:
2897
 
    POPL(ssp, sp, sp_mask, new_esp);
2898
 
    POPL(ssp, sp, sp_mask, new_ss);
2899
 
    POPL(ssp, sp, sp_mask, new_es);
2900
 
    POPL(ssp, sp, sp_mask, new_ds);
2901
 
    POPL(ssp, sp, sp_mask, new_fs);
2902
 
    POPL(ssp, sp, sp_mask, new_gs);
2903
 
 
2904
 
    /* modify processor state */
2905
 
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2906
 
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2907
 
    load_seg_vm(R_CS, new_cs & 0xffff);
2908
 
    cpu_x86_set_cpl(env, 3);
2909
 
    load_seg_vm(R_SS, new_ss & 0xffff);
2910
 
    load_seg_vm(R_ES, new_es & 0xffff);
2911
 
    load_seg_vm(R_DS, new_ds & 0xffff);
2912
 
    load_seg_vm(R_FS, new_fs & 0xffff);
2913
 
    load_seg_vm(R_GS, new_gs & 0xffff);
2914
 
 
2915
 
    env->eip = new_eip & 0xffff;
2916
 
    ESP = new_esp;
2917
 
}
2918
 
 
2919
 
void helper_iret_protected(int shift, int next_eip)
2920
 
{
2921
 
    int tss_selector, type;
2922
 
    uint32_t e1, e2;
2923
 
 
2924
 
    /* specific case for TSS */
2925
 
    if (env->eflags & NT_MASK) {
2926
 
#ifdef TARGET_X86_64
2927
 
        if (env->hflags & HF_LMA_MASK)
2928
 
            raise_exception_err(EXCP0D_GPF, 0);
2929
 
#endif
2930
 
        tss_selector = lduw_kernel(env->tr.base + 0);
2931
 
        if (tss_selector & 4)
2932
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2933
 
        if (load_segment(&e1, &e2, tss_selector) != 0)
2934
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2935
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2936
 
        /* NOTE: we check both segment and busy TSS */
2937
 
        if (type != 3)
2938
 
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2939
 
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2940
 
    } else {
2941
 
        helper_ret_protected(shift, 1, 0);
2942
 
    }
2943
 
    env->hflags2 &= ~HF2_NMI_MASK;
2944
 
}
2945
 
 
2946
 
void helper_lret_protected(int shift, int addend)
2947
 
{
2948
 
    helper_ret_protected(shift, 0, addend);
2949
 
}
2950
 
 
2951
 
void helper_sysenter(void)
2952
 
{
2953
 
    if (env->sysenter_cs == 0) {
2954
 
        raise_exception_err(EXCP0D_GPF, 0);
2955
 
    }
2956
 
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2957
 
    cpu_x86_set_cpl(env, 0);
2958
 
 
2959
 
#ifdef TARGET_X86_64
2960
 
    if (env->hflags & HF_LMA_MASK) {
2961
 
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2962
 
                               0, 0xffffffff,
2963
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2964
 
                               DESC_S_MASK |
2965
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2966
 
    } else
2967
 
#endif
2968
 
    {
2969
 
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2970
 
                               0, 0xffffffff,
2971
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2972
 
                               DESC_S_MASK |
2973
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2974
 
    }
2975
 
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2976
 
                           0, 0xffffffff,
2977
 
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2978
 
                           DESC_S_MASK |
2979
 
                           DESC_W_MASK | DESC_A_MASK);
2980
 
    ESP = env->sysenter_esp;
2981
 
    EIP = env->sysenter_eip;
2982
 
}
2983
 
 
2984
 
void helper_sysexit(int dflag)
2985
 
{
2986
 
    int cpl;
2987
 
 
2988
 
    cpl = env->hflags & HF_CPL_MASK;
2989
 
    if (env->sysenter_cs == 0 || cpl != 0) {
2990
 
        raise_exception_err(EXCP0D_GPF, 0);
2991
 
    }
2992
 
    cpu_x86_set_cpl(env, 3);
2993
 
#ifdef TARGET_X86_64
2994
 
    if (dflag == 2) {
2995
 
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3,
2996
 
                               0, 0xffffffff,
2997
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2998
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2999
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
3000
 
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3,
3001
 
                               0, 0xffffffff,
3002
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3003
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3004
 
                               DESC_W_MASK | DESC_A_MASK);
3005
 
    } else
3006
 
#endif
3007
 
    {
3008
 
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
3009
 
                               0, 0xffffffff,
3010
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3011
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3012
 
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
3013
 
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
3014
 
                               0, 0xffffffff,
3015
 
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3016
 
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3017
 
                               DESC_W_MASK | DESC_A_MASK);
3018
 
    }
3019
 
    ESP = ECX;
3020
 
    EIP = EDX;
3021
 
}
3022
 
 
3023
 
#if defined(CONFIG_USER_ONLY)
3024
 
target_ulong helper_read_crN(int reg)
3025
 
{
3026
 
    return 0;
3027
 
}
3028
 
 
3029
 
void helper_write_crN(int reg, target_ulong t0)
3030
 
{
3031
 
}
3032
 
 
3033
 
void helper_movl_drN_T0(int reg, target_ulong t0)
3034
 
{
3035
 
}
3036
 
#else
3037
 
target_ulong helper_read_crN(int reg)
3038
 
{
3039
 
    target_ulong val;
3040
 
 
3041
 
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
3042
 
    switch(reg) {
3043
 
    default:
3044
 
        val = env->cr[reg];
3045
 
        break;
3046
 
    case 8:
3047
 
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
3048
 
            val = cpu_get_apic_tpr(env->apic_state);
3049
 
        } else {
3050
 
            val = env->v_tpr;
3051
 
        }
3052
 
        break;
3053
 
    }
3054
 
    return val;
3055
 
}
3056
 
 
3057
 
void helper_write_crN(int reg, target_ulong t0)
3058
 
{
3059
 
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
3060
 
    switch(reg) {
3061
 
    case 0:
3062
 
        cpu_x86_update_cr0(env, t0);
3063
 
        break;
3064
 
    case 3:
3065
 
        cpu_x86_update_cr3(env, t0);
3066
 
        break;
3067
 
    case 4:
3068
 
        cpu_x86_update_cr4(env, t0);
3069
 
        break;
3070
 
    case 8:
3071
 
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
3072
 
            cpu_set_apic_tpr(env->apic_state, t0);
3073
 
        }
3074
 
        env->v_tpr = t0 & 0x0f;
3075
 
        break;
3076
 
    default:
3077
 
        env->cr[reg] = t0;
3078
 
        break;
3079
 
    }
3080
 
}
3081
 
 
3082
 
void helper_movl_drN_T0(int reg, target_ulong t0)
3083
 
{
3084
 
    int i;
3085
 
 
3086
 
    if (reg < 4) {
3087
 
        hw_breakpoint_remove(env, reg);
3088
 
        env->dr[reg] = t0;
3089
 
        hw_breakpoint_insert(env, reg);
3090
 
    } else if (reg == 7) {
3091
 
        for (i = 0; i < 4; i++)
3092
 
            hw_breakpoint_remove(env, i);
3093
 
        env->dr[7] = t0;
3094
 
        for (i = 0; i < 4; i++)
3095
 
            hw_breakpoint_insert(env, i);
3096
 
    } else
3097
 
        env->dr[reg] = t0;
3098
 
}
3099
 
#endif
3100
 
 
3101
 
void helper_lmsw(target_ulong t0)
3102
 
{
3103
 
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
3104
 
       if already set to one. */
3105
 
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
3106
 
    helper_write_crN(0, t0);
3107
 
}
3108
 
 
3109
 
void helper_clts(void)
3110
 
{
3111
 
    env->cr[0] &= ~CR0_TS_MASK;
3112
 
    env->hflags &= ~HF_TS_MASK;
3113
 
}
3114
 
 
3115
 
void helper_invlpg(target_ulong addr)
3116
 
{
3117
 
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
3118
 
    tlb_flush_page(env, addr);
3119
 
}
3120
 
 
3121
 
void helper_rdtsc(void)
3122
 
{
3123
 
    uint64_t val;
3124
 
 
3125
 
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3126
 
        raise_exception(EXCP0D_GPF);
3127
 
    }
3128
 
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
3129
 
 
3130
 
    val = cpu_get_tsc(env) + env->tsc_offset;
3131
 
    EAX = (uint32_t)(val);
3132
 
    EDX = (uint32_t)(val >> 32);
3133
 
}
3134
 
 
3135
 
void helper_rdtscp(void)
3136
 
{
3137
 
    helper_rdtsc();
3138
 
    ECX = (uint32_t)(env->tsc_aux);
3139
 
}
3140
 
 
3141
 
void helper_rdpmc(void)
3142
 
{
3143
 
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3144
 
        raise_exception(EXCP0D_GPF);
3145
 
    }
3146
 
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3147
 
    
3148
 
    /* currently unimplemented */
3149
 
    raise_exception_err(EXCP06_ILLOP, 0);
3150
 
}
3151
 
 
3152
 
#if defined(CONFIG_USER_ONLY)
3153
 
void helper_wrmsr(void)
3154
 
{
3155
 
}
3156
 
 
3157
 
void helper_rdmsr(void)
3158
 
{
3159
 
}
3160
 
#else
3161
 
void helper_wrmsr(void)
3162
 
{
3163
 
    uint64_t val;
3164
 
 
3165
 
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3166
 
 
3167
 
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3168
 
 
3169
 
    switch((uint32_t)ECX) {
3170
 
    case MSR_IA32_SYSENTER_CS:
3171
 
        env->sysenter_cs = val & 0xffff;
3172
 
        break;
3173
 
    case MSR_IA32_SYSENTER_ESP:
3174
 
        env->sysenter_esp = val;
3175
 
        break;
3176
 
    case MSR_IA32_SYSENTER_EIP:
3177
 
        env->sysenter_eip = val;
3178
 
        break;
3179
 
    case MSR_IA32_APICBASE:
3180
 
        cpu_set_apic_base(env->apic_state, val);
3181
 
        break;
3182
 
    case MSR_EFER:
3183
 
        {
3184
 
            uint64_t update_mask;
3185
 
            update_mask = 0;
3186
 
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3187
 
                update_mask |= MSR_EFER_SCE;
3188
 
            if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3189
 
                update_mask |= MSR_EFER_LME;
3190
 
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3191
 
                update_mask |= MSR_EFER_FFXSR;
3192
 
            if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3193
 
                update_mask |= MSR_EFER_NXE;
3194
 
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3195
 
                update_mask |= MSR_EFER_SVME;
3196
 
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3197
 
                update_mask |= MSR_EFER_FFXSR;
3198
 
            cpu_load_efer(env, (env->efer & ~update_mask) |
3199
 
                          (val & update_mask));
3200
 
        }
3201
 
        break;
3202
 
    case MSR_STAR:
3203
 
        env->star = val;
3204
 
        break;
3205
 
    case MSR_PAT:
3206
 
        env->pat = val;
3207
 
        break;
3208
 
    case MSR_VM_HSAVE_PA:
3209
 
        env->vm_hsave = val;
3210
 
        break;
3211
 
#ifdef TARGET_X86_64
3212
 
    case MSR_LSTAR:
3213
 
        env->lstar = val;
3214
 
        break;
3215
 
    case MSR_CSTAR:
3216
 
        env->cstar = val;
3217
 
        break;
3218
 
    case MSR_FMASK:
3219
 
        env->fmask = val;
3220
 
        break;
3221
 
    case MSR_FSBASE:
3222
 
        env->segs[R_FS].base = val;
3223
 
        break;
3224
 
    case MSR_GSBASE:
3225
 
        env->segs[R_GS].base = val;
3226
 
        break;
3227
 
    case MSR_KERNELGSBASE:
3228
 
        env->kernelgsbase = val;
3229
 
        break;
3230
 
#endif
3231
 
    case MSR_MTRRphysBase(0):
3232
 
    case MSR_MTRRphysBase(1):
3233
 
    case MSR_MTRRphysBase(2):
3234
 
    case MSR_MTRRphysBase(3):
3235
 
    case MSR_MTRRphysBase(4):
3236
 
    case MSR_MTRRphysBase(5):
3237
 
    case MSR_MTRRphysBase(6):
3238
 
    case MSR_MTRRphysBase(7):
3239
 
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
3240
 
        break;
3241
 
    case MSR_MTRRphysMask(0):
3242
 
    case MSR_MTRRphysMask(1):
3243
 
    case MSR_MTRRphysMask(2):
3244
 
    case MSR_MTRRphysMask(3):
3245
 
    case MSR_MTRRphysMask(4):
3246
 
    case MSR_MTRRphysMask(5):
3247
 
    case MSR_MTRRphysMask(6):
3248
 
    case MSR_MTRRphysMask(7):
3249
 
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
3250
 
        break;
3251
 
    case MSR_MTRRfix64K_00000:
3252
 
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
3253
 
        break;
3254
 
    case MSR_MTRRfix16K_80000:
3255
 
    case MSR_MTRRfix16K_A0000:
3256
 
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
3257
 
        break;
3258
 
    case MSR_MTRRfix4K_C0000:
3259
 
    case MSR_MTRRfix4K_C8000:
3260
 
    case MSR_MTRRfix4K_D0000:
3261
 
    case MSR_MTRRfix4K_D8000:
3262
 
    case MSR_MTRRfix4K_E0000:
3263
 
    case MSR_MTRRfix4K_E8000:
3264
 
    case MSR_MTRRfix4K_F0000:
3265
 
    case MSR_MTRRfix4K_F8000:
3266
 
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
3267
 
        break;
3268
 
    case MSR_MTRRdefType:
3269
 
        env->mtrr_deftype = val;
3270
 
        break;
3271
 
    case MSR_MCG_STATUS:
3272
 
        env->mcg_status = val;
3273
 
        break;
3274
 
    case MSR_MCG_CTL:
3275
 
        if ((env->mcg_cap & MCG_CTL_P)
3276
 
            && (val == 0 || val == ~(uint64_t)0))
3277
 
            env->mcg_ctl = val;
3278
 
        break;
3279
 
    case MSR_TSC_AUX:
3280
 
        env->tsc_aux = val;
3281
 
        break;
3282
 
    case MSR_IA32_MISC_ENABLE:
3283
 
        env->msr_ia32_misc_enable = val;
3284
 
        break;
3285
 
    default:
3286
 
        if ((uint32_t)ECX >= MSR_MC0_CTL
3287
 
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3288
 
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3289
 
            if ((offset & 0x3) != 0
3290
 
                || (val == 0 || val == ~(uint64_t)0))
3291
 
                env->mce_banks[offset] = val;
3292
 
            break;
3293
 
        }
3294
 
        /* XXX: exception ? */
3295
 
        break;
3296
 
    }
3297
 
}
3298
 
 
3299
 
void helper_rdmsr(void)
3300
 
{
3301
 
    uint64_t val;
3302
 
 
3303
 
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3304
 
 
3305
 
    switch((uint32_t)ECX) {
3306
 
    case MSR_IA32_SYSENTER_CS:
3307
 
        val = env->sysenter_cs;
3308
 
        break;
3309
 
    case MSR_IA32_SYSENTER_ESP:
3310
 
        val = env->sysenter_esp;
3311
 
        break;
3312
 
    case MSR_IA32_SYSENTER_EIP:
3313
 
        val = env->sysenter_eip;
3314
 
        break;
3315
 
    case MSR_IA32_APICBASE:
3316
 
        val = cpu_get_apic_base(env->apic_state);
3317
 
        break;
3318
 
    case MSR_EFER:
3319
 
        val = env->efer;
3320
 
        break;
3321
 
    case MSR_STAR:
3322
 
        val = env->star;
3323
 
        break;
3324
 
    case MSR_PAT:
3325
 
        val = env->pat;
3326
 
        break;
3327
 
    case MSR_VM_HSAVE_PA:
3328
 
        val = env->vm_hsave;
3329
 
        break;
3330
 
    case MSR_IA32_PERF_STATUS:
3331
 
        /* tsc_increment_by_tick */
3332
 
        val = 1000ULL;
3333
 
        /* CPU multiplier */
3334
 
        val |= (((uint64_t)4ULL) << 40);
3335
 
        break;
3336
 
#ifdef TARGET_X86_64
3337
 
    case MSR_LSTAR:
3338
 
        val = env->lstar;
3339
 
        break;
3340
 
    case MSR_CSTAR:
3341
 
        val = env->cstar;
3342
 
        break;
3343
 
    case MSR_FMASK:
3344
 
        val = env->fmask;
3345
 
        break;
3346
 
    case MSR_FSBASE:
3347
 
        val = env->segs[R_FS].base;
3348
 
        break;
3349
 
    case MSR_GSBASE:
3350
 
        val = env->segs[R_GS].base;
3351
 
        break;
3352
 
    case MSR_KERNELGSBASE:
3353
 
        val = env->kernelgsbase;
3354
 
        break;
3355
 
    case MSR_TSC_AUX:
3356
 
        val = env->tsc_aux;
3357
 
        break;
3358
 
#endif
3359
 
    case MSR_MTRRphysBase(0):
3360
 
    case MSR_MTRRphysBase(1):
3361
 
    case MSR_MTRRphysBase(2):
3362
 
    case MSR_MTRRphysBase(3):
3363
 
    case MSR_MTRRphysBase(4):
3364
 
    case MSR_MTRRphysBase(5):
3365
 
    case MSR_MTRRphysBase(6):
3366
 
    case MSR_MTRRphysBase(7):
3367
 
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;
3368
 
        break;
3369
 
    case MSR_MTRRphysMask(0):
3370
 
    case MSR_MTRRphysMask(1):
3371
 
    case MSR_MTRRphysMask(2):
3372
 
    case MSR_MTRRphysMask(3):
3373
 
    case MSR_MTRRphysMask(4):
3374
 
    case MSR_MTRRphysMask(5):
3375
 
    case MSR_MTRRphysMask(6):
3376
 
    case MSR_MTRRphysMask(7):
3377
 
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;
3378
 
        break;
3379
 
    case MSR_MTRRfix64K_00000:
3380
 
        val = env->mtrr_fixed[0];
3381
 
        break;
3382
 
    case MSR_MTRRfix16K_80000:
3383
 
    case MSR_MTRRfix16K_A0000:
3384
 
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];
3385
 
        break;
3386
 
    case MSR_MTRRfix4K_C0000:
3387
 
    case MSR_MTRRfix4K_C8000:
3388
 
    case MSR_MTRRfix4K_D0000:
3389
 
    case MSR_MTRRfix4K_D8000:
3390
 
    case MSR_MTRRfix4K_E0000:
3391
 
    case MSR_MTRRfix4K_E8000:
3392
 
    case MSR_MTRRfix4K_F0000:
3393
 
    case MSR_MTRRfix4K_F8000:
3394
 
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];
3395
 
        break;
3396
 
    case MSR_MTRRdefType:
3397
 
        val = env->mtrr_deftype;
3398
 
        break;
3399
 
    case MSR_MTRRcap:
3400
 
        if (env->cpuid_features & CPUID_MTRR)
3401
 
            val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED;
3402
 
        else
3403
 
            /* XXX: exception ? */
3404
 
            val = 0;
3405
 
        break;
3406
 
    case MSR_MCG_CAP:
3407
 
        val = env->mcg_cap;
3408
 
        break;
3409
 
    case MSR_MCG_CTL:
3410
 
        if (env->mcg_cap & MCG_CTL_P)
3411
 
            val = env->mcg_ctl;
3412
 
        else
3413
 
            val = 0;
3414
 
        break;
3415
 
    case MSR_MCG_STATUS:
3416
 
        val = env->mcg_status;
3417
 
        break;
3418
 
    case MSR_IA32_MISC_ENABLE:
3419
 
        val = env->msr_ia32_misc_enable;
3420
 
        break;
3421
 
    default:
3422
 
        if ((uint32_t)ECX >= MSR_MC0_CTL
3423
 
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3424
 
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3425
 
            val = env->mce_banks[offset];
3426
 
            break;
3427
 
        }
3428
 
        /* XXX: exception ? */
3429
 
        val = 0;
3430
 
        break;
3431
 
    }
3432
 
    EAX = (uint32_t)(val);
3433
 
    EDX = (uint32_t)(val >> 32);
3434
 
}
3435
 
#endif
3436
 
 
3437
 
target_ulong helper_lsl(target_ulong selector1)
3438
 
{
3439
 
    unsigned int limit;
3440
 
    uint32_t e1, e2, eflags, selector;
3441
 
    int rpl, dpl, cpl, type;
3442
 
 
3443
 
    selector = selector1 & 0xffff;
3444
 
    eflags = helper_cc_compute_all(CC_OP);
3445
 
    if ((selector & 0xfffc) == 0)
3446
 
        goto fail;
3447
 
    if (load_segment(&e1, &e2, selector) != 0)
3448
 
        goto fail;
3449
 
    rpl = selector & 3;
3450
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3451
 
    cpl = env->hflags & HF_CPL_MASK;
3452
 
    if (e2 & DESC_S_MASK) {
3453
 
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3454
 
            /* conforming */
3455
 
        } else {
3456
 
            if (dpl < cpl || dpl < rpl)
3457
 
                goto fail;
3458
 
        }
3459
 
    } else {
3460
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3461
 
        switch(type) {
3462
 
        case 1:
3463
 
        case 2:
3464
 
        case 3:
3465
 
        case 9:
3466
 
        case 11:
3467
 
            break;
3468
 
        default:
3469
 
            goto fail;
3470
 
        }
3471
 
        if (dpl < cpl || dpl < rpl) {
3472
 
        fail:
3473
 
            CC_SRC = eflags & ~CC_Z;
3474
 
            return 0;
3475
 
        }
3476
 
    }
3477
 
    limit = get_seg_limit(e1, e2);
3478
 
    CC_SRC = eflags | CC_Z;
3479
 
    return limit;
3480
 
}
3481
 
 
3482
 
target_ulong helper_lar(target_ulong selector1)
3483
 
{
3484
 
    uint32_t e1, e2, eflags, selector;
3485
 
    int rpl, dpl, cpl, type;
3486
 
 
3487
 
    selector = selector1 & 0xffff;
3488
 
    eflags = helper_cc_compute_all(CC_OP);
3489
 
    if ((selector & 0xfffc) == 0)
3490
 
        goto fail;
3491
 
    if (load_segment(&e1, &e2, selector) != 0)
3492
 
        goto fail;
3493
 
    rpl = selector & 3;
3494
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3495
 
    cpl = env->hflags & HF_CPL_MASK;
3496
 
    if (e2 & DESC_S_MASK) {
3497
 
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3498
 
            /* conforming */
3499
 
        } else {
3500
 
            if (dpl < cpl || dpl < rpl)
3501
 
                goto fail;
3502
 
        }
3503
 
    } else {
3504
 
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3505
 
        switch(type) {
3506
 
        case 1:
3507
 
        case 2:
3508
 
        case 3:
3509
 
        case 4:
3510
 
        case 5:
3511
 
        case 9:
3512
 
        case 11:
3513
 
        case 12:
3514
 
            break;
3515
 
        default:
3516
 
            goto fail;
3517
 
        }
3518
 
        if (dpl < cpl || dpl < rpl) {
3519
 
        fail:
3520
 
            CC_SRC = eflags & ~CC_Z;
3521
 
            return 0;
3522
 
        }
3523
 
    }
3524
 
    CC_SRC = eflags | CC_Z;
3525
 
    return e2 & 0x00f0ff00;
3526
 
}
3527
 
 
3528
 
void helper_verr(target_ulong selector1)
3529
 
{
3530
 
    uint32_t e1, e2, eflags, selector;
3531
 
    int rpl, dpl, cpl;
3532
 
 
3533
 
    selector = selector1 & 0xffff;
3534
 
    eflags = helper_cc_compute_all(CC_OP);
3535
 
    if ((selector & 0xfffc) == 0)
3536
 
        goto fail;
3537
 
    if (load_segment(&e1, &e2, selector) != 0)
3538
 
        goto fail;
3539
 
    if (!(e2 & DESC_S_MASK))
3540
 
        goto fail;
3541
 
    rpl = selector & 3;
3542
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3543
 
    cpl = env->hflags & HF_CPL_MASK;
3544
 
    if (e2 & DESC_CS_MASK) {
3545
 
        if (!(e2 & DESC_R_MASK))
3546
 
            goto fail;
3547
 
        if (!(e2 & DESC_C_MASK)) {
3548
 
            if (dpl < cpl || dpl < rpl)
3549
 
                goto fail;
3550
 
        }
3551
 
    } else {
3552
 
        if (dpl < cpl || dpl < rpl) {
3553
 
        fail:
3554
 
            CC_SRC = eflags & ~CC_Z;
3555
 
            return;
3556
 
        }
3557
 
    }
3558
 
    CC_SRC = eflags | CC_Z;
3559
 
}
3560
 
 
3561
 
void helper_verw(target_ulong selector1)
3562
 
{
3563
 
    uint32_t e1, e2, eflags, selector;
3564
 
    int rpl, dpl, cpl;
3565
 
 
3566
 
    selector = selector1 & 0xffff;
3567
 
    eflags = helper_cc_compute_all(CC_OP);
3568
 
    if ((selector & 0xfffc) == 0)
3569
 
        goto fail;
3570
 
    if (load_segment(&e1, &e2, selector) != 0)
3571
 
        goto fail;
3572
 
    if (!(e2 & DESC_S_MASK))
3573
 
        goto fail;
3574
 
    rpl = selector & 3;
3575
 
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3576
 
    cpl = env->hflags & HF_CPL_MASK;
3577
 
    if (e2 & DESC_CS_MASK) {
3578
 
        goto fail;
3579
 
    } else {
3580
 
        if (dpl < cpl || dpl < rpl)
3581
 
            goto fail;
3582
 
        if (!(e2 & DESC_W_MASK)) {
3583
 
        fail:
3584
 
            CC_SRC = eflags & ~CC_Z;
3585
 
            return;
3586
 
        }
3587
 
    }
3588
 
    CC_SRC = eflags | CC_Z;
3589
 
}
3590
 
 
3591
 
/* x87 FPU helpers */
3592
 
 
3593
 
static inline double floatx80_to_double(floatx80 a)
3594
 
{
3595
 
    union {
3596
 
        float64 f64;
3597
 
        double d;
3598
 
    } u;
3599
 
 
3600
 
    u.f64 = floatx80_to_float64(a, &env->fp_status);
3601
 
    return u.d;
3602
 
}
3603
 
 
3604
 
static inline floatx80 double_to_floatx80(double a)
3605
 
{
3606
 
    union {
3607
 
        float64 f64;
3608
 
        double d;
3609
 
    } u;
3610
 
 
3611
 
    u.d = a;
3612
 
    return float64_to_floatx80(u.f64, &env->fp_status);
3613
 
}
3614
 
 
3615
 
static void fpu_set_exception(int mask)
3616
 
{
3617
 
    env->fpus |= mask;
3618
 
    if (env->fpus & (~env->fpuc & FPUC_EM))
3619
 
        env->fpus |= FPUS_SE | FPUS_B;
3620
 
}
3621
 
 
3622
 
static inline floatx80 helper_fdiv(floatx80 a, floatx80 b)
3623
 
{
3624
 
    if (floatx80_is_zero(b)) {
3625
 
        fpu_set_exception(FPUS_ZE);
3626
 
    }
3627
 
    return floatx80_div(a, b, &env->fp_status);
3628
 
}
3629
 
 
3630
 
static void fpu_raise_exception(void)
3631
 
{
3632
 
    if (env->cr[0] & CR0_NE_MASK) {
3633
 
        raise_exception(EXCP10_COPR);
3634
 
    }
3635
 
#if !defined(CONFIG_USER_ONLY)
3636
 
    else {
3637
 
        cpu_set_ferr(env);
3638
 
    }
3639
 
#endif
3640
 
}
3641
 
 
3642
 
void helper_flds_FT0(uint32_t val)
3643
 
{
3644
 
    union {
3645
 
        float32 f;
3646
 
        uint32_t i;
3647
 
    } u;
3648
 
    u.i = val;
3649
 
    FT0 = float32_to_floatx80(u.f, &env->fp_status);
3650
 
}
3651
 
 
3652
 
void helper_fldl_FT0(uint64_t val)
3653
 
{
3654
 
    union {
3655
 
        float64 f;
3656
 
        uint64_t i;
3657
 
    } u;
3658
 
    u.i = val;
3659
 
    FT0 = float64_to_floatx80(u.f, &env->fp_status);
3660
 
}
3661
 
 
3662
 
void helper_fildl_FT0(int32_t val)
3663
 
{
3664
 
    FT0 = int32_to_floatx80(val, &env->fp_status);
3665
 
}
3666
 
 
3667
 
void helper_flds_ST0(uint32_t val)
3668
 
{
3669
 
    int new_fpstt;
3670
 
    union {
3671
 
        float32 f;
3672
 
        uint32_t i;
3673
 
    } u;
3674
 
    new_fpstt = (env->fpstt - 1) & 7;
3675
 
    u.i = val;
3676
 
    env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status);
3677
 
    env->fpstt = new_fpstt;
3678
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3679
 
}
3680
 
 
3681
 
void helper_fldl_ST0(uint64_t val)
3682
 
{
3683
 
    int new_fpstt;
3684
 
    union {
3685
 
        float64 f;
3686
 
        uint64_t i;
3687
 
    } u;
3688
 
    new_fpstt = (env->fpstt - 1) & 7;
3689
 
    u.i = val;
3690
 
    env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status);
3691
 
    env->fpstt = new_fpstt;
3692
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3693
 
}
3694
 
 
3695
 
void helper_fildl_ST0(int32_t val)
3696
 
{
3697
 
    int new_fpstt;
3698
 
    new_fpstt = (env->fpstt - 1) & 7;
3699
 
    env->fpregs[new_fpstt].d = int32_to_floatx80(val, &env->fp_status);
3700
 
    env->fpstt = new_fpstt;
3701
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3702
 
}
3703
 
 
3704
 
void helper_fildll_ST0(int64_t val)
3705
 
{
3706
 
    int new_fpstt;
3707
 
    new_fpstt = (env->fpstt - 1) & 7;
3708
 
    env->fpregs[new_fpstt].d = int64_to_floatx80(val, &env->fp_status);
3709
 
    env->fpstt = new_fpstt;
3710
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3711
 
}
3712
 
 
3713
 
uint32_t helper_fsts_ST0(void)
3714
 
{
3715
 
    union {
3716
 
        float32 f;
3717
 
        uint32_t i;
3718
 
    } u;
3719
 
    u.f = floatx80_to_float32(ST0, &env->fp_status);
3720
 
    return u.i;
3721
 
}
3722
 
 
3723
 
uint64_t helper_fstl_ST0(void)
3724
 
{
3725
 
    union {
3726
 
        float64 f;
3727
 
        uint64_t i;
3728
 
    } u;
3729
 
    u.f = floatx80_to_float64(ST0, &env->fp_status);
3730
 
    return u.i;
3731
 
}
3732
 
 
3733
 
int32_t helper_fist_ST0(void)
3734
 
{
3735
 
    int32_t val;
3736
 
    val = floatx80_to_int32(ST0, &env->fp_status);
3737
 
    if (val != (int16_t)val)
3738
 
        val = -32768;
3739
 
    return val;
3740
 
}
3741
 
 
3742
 
int32_t helper_fistl_ST0(void)
3743
 
{
3744
 
    int32_t val;
3745
 
    val = floatx80_to_int32(ST0, &env->fp_status);
3746
 
    return val;
3747
 
}
3748
 
 
3749
 
int64_t helper_fistll_ST0(void)
3750
 
{
3751
 
    int64_t val;
3752
 
    val = floatx80_to_int64(ST0, &env->fp_status);
3753
 
    return val;
3754
 
}
3755
 
 
3756
 
int32_t helper_fistt_ST0(void)
3757
 
{
3758
 
    int32_t val;
3759
 
    val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
3760
 
    if (val != (int16_t)val)
3761
 
        val = -32768;
3762
 
    return val;
3763
 
}
3764
 
 
3765
 
int32_t helper_fisttl_ST0(void)
3766
 
{
3767
 
    int32_t val;
3768
 
    val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
3769
 
    return val;
3770
 
}
3771
 
 
3772
 
int64_t helper_fisttll_ST0(void)
3773
 
{
3774
 
    int64_t val;
3775
 
    val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
3776
 
    return val;
3777
 
}
3778
 
 
3779
 
void helper_fldt_ST0(target_ulong ptr)
3780
 
{
3781
 
    int new_fpstt;
3782
 
    new_fpstt = (env->fpstt - 1) & 7;
3783
 
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3784
 
    env->fpstt = new_fpstt;
3785
 
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3786
 
}
3787
 
 
3788
 
void helper_fstt_ST0(target_ulong ptr)
3789
 
{
3790
 
    helper_fstt(ST0, ptr);
3791
 
}
3792
 
 
3793
 
void helper_fpush(void)
3794
 
{
3795
 
    fpush();
3796
 
}
3797
 
 
3798
 
void helper_fpop(void)
3799
 
{
3800
 
    fpop();
3801
 
}
3802
 
 
3803
 
void helper_fdecstp(void)
3804
 
{
3805
 
    env->fpstt = (env->fpstt - 1) & 7;
3806
 
    env->fpus &= (~0x4700);
3807
 
}
3808
 
 
3809
 
void helper_fincstp(void)
3810
 
{
3811
 
    env->fpstt = (env->fpstt + 1) & 7;
3812
 
    env->fpus &= (~0x4700);
3813
 
}
3814
 
 
3815
 
/* FPU move */
3816
 
 
3817
 
void helper_ffree_STN(int st_index)
3818
 
{
3819
 
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3820
 
}
3821
 
 
3822
 
void helper_fmov_ST0_FT0(void)
3823
 
{
3824
 
    ST0 = FT0;
3825
 
}
3826
 
 
3827
 
void helper_fmov_FT0_STN(int st_index)
3828
 
{
3829
 
    FT0 = ST(st_index);
3830
 
}
3831
 
 
3832
 
void helper_fmov_ST0_STN(int st_index)
3833
 
{
3834
 
    ST0 = ST(st_index);
3835
 
}
3836
 
 
3837
 
void helper_fmov_STN_ST0(int st_index)
3838
 
{
3839
 
    ST(st_index) = ST0;
3840
 
}
3841
 
 
3842
 
void helper_fxchg_ST0_STN(int st_index)
3843
 
{
3844
 
    floatx80 tmp;
3845
 
    tmp = ST(st_index);
3846
 
    ST(st_index) = ST0;
3847
 
    ST0 = tmp;
3848
 
}
3849
 
 
3850
 
/* FPU operations */
3851
 
 
3852
 
static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
3853
 
 
3854
 
void helper_fcom_ST0_FT0(void)
3855
 
{
3856
 
    int ret;
3857
 
 
3858
 
    ret = floatx80_compare(ST0, FT0, &env->fp_status);
3859
 
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3860
 
}
3861
 
 
3862
 
void helper_fucom_ST0_FT0(void)
3863
 
{
3864
 
    int ret;
3865
 
 
3866
 
    ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
3867
 
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3868
 
}
3869
 
 
3870
 
static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
3871
 
 
3872
 
void helper_fcomi_ST0_FT0(void)
3873
 
{
3874
 
    int eflags;
3875
 
    int ret;
3876
 
 
3877
 
    ret = floatx80_compare(ST0, FT0, &env->fp_status);
3878
 
    eflags = helper_cc_compute_all(CC_OP);
3879
 
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3880
 
    CC_SRC = eflags;
3881
 
}
3882
 
 
3883
 
void helper_fucomi_ST0_FT0(void)
3884
 
{
3885
 
    int eflags;
3886
 
    int ret;
3887
 
 
3888
 
    ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
3889
 
    eflags = helper_cc_compute_all(CC_OP);
3890
 
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3891
 
    CC_SRC = eflags;
3892
 
}
3893
 
 
3894
 
void helper_fadd_ST0_FT0(void)
3895
 
{
3896
 
    ST0 = floatx80_add(ST0, FT0, &env->fp_status);
3897
 
}
3898
 
 
3899
 
void helper_fmul_ST0_FT0(void)
3900
 
{
3901
 
    ST0 = floatx80_mul(ST0, FT0, &env->fp_status);
3902
 
}
3903
 
 
3904
 
void helper_fsub_ST0_FT0(void)
3905
 
{
3906
 
    ST0 = floatx80_sub(ST0, FT0, &env->fp_status);
3907
 
}
3908
 
 
3909
 
void helper_fsubr_ST0_FT0(void)
3910
 
{
3911
 
    ST0 = floatx80_sub(FT0, ST0, &env->fp_status);
3912
 
}
3913
 
 
3914
 
void helper_fdiv_ST0_FT0(void)
3915
 
{
3916
 
    ST0 = helper_fdiv(ST0, FT0);
3917
 
}
3918
 
 
3919
 
void helper_fdivr_ST0_FT0(void)
3920
 
{
3921
 
    ST0 = helper_fdiv(FT0, ST0);
3922
 
}
3923
 
 
3924
 
/* fp operations between STN and ST0 */
3925
 
 
3926
 
void helper_fadd_STN_ST0(int st_index)
3927
 
{
3928
 
    ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status);
3929
 
}
3930
 
 
3931
 
void helper_fmul_STN_ST0(int st_index)
3932
 
{
3933
 
    ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status);
3934
 
}
3935
 
 
3936
 
void helper_fsub_STN_ST0(int st_index)
3937
 
{
3938
 
    ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status);
3939
 
}
3940
 
 
3941
 
void helper_fsubr_STN_ST0(int st_index)
3942
 
{
3943
 
    ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status);
3944
 
}
3945
 
 
3946
 
void helper_fdiv_STN_ST0(int st_index)
3947
 
{
3948
 
    floatx80 *p;
3949
 
    p = &ST(st_index);
3950
 
    *p = helper_fdiv(*p, ST0);
3951
 
}
3952
 
 
3953
 
void helper_fdivr_STN_ST0(int st_index)
3954
 
{
3955
 
    floatx80 *p;
3956
 
    p = &ST(st_index);
3957
 
    *p = helper_fdiv(ST0, *p);
3958
 
}
3959
 
 
3960
 
/* misc FPU operations */
3961
 
void helper_fchs_ST0(void)
3962
 
{
3963
 
    ST0 = floatx80_chs(ST0);
3964
 
}
3965
 
 
3966
 
void helper_fabs_ST0(void)
3967
 
{
3968
 
    ST0 = floatx80_abs(ST0);
3969
 
}
3970
 
 
3971
 
void helper_fld1_ST0(void)
3972
 
{
3973
 
    ST0 = floatx80_one;
3974
 
}
3975
 
 
3976
 
void helper_fldl2t_ST0(void)
3977
 
{
3978
 
    ST0 = floatx80_l2t;
3979
 
}
3980
 
 
3981
 
void helper_fldl2e_ST0(void)
3982
 
{
3983
 
    ST0 = floatx80_l2e;
3984
 
}
3985
 
 
3986
 
void helper_fldpi_ST0(void)
3987
 
{
3988
 
    ST0 = floatx80_pi;
3989
 
}
3990
 
 
3991
 
void helper_fldlg2_ST0(void)
3992
 
{
3993
 
    ST0 = floatx80_lg2;
3994
 
}
3995
 
 
3996
 
void helper_fldln2_ST0(void)
3997
 
{
3998
 
    ST0 = floatx80_ln2;
3999
 
}
4000
 
 
4001
 
void helper_fldz_ST0(void)
4002
 
{
4003
 
    ST0 = floatx80_zero;
4004
 
}
4005
 
 
4006
 
void helper_fldz_FT0(void)
4007
 
{
4008
 
    FT0 = floatx80_zero;
4009
 
}
4010
 
 
4011
 
uint32_t helper_fnstsw(void)
4012
 
{
4013
 
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4014
 
}
4015
 
 
4016
 
uint32_t helper_fnstcw(void)
4017
 
{
4018
 
    return env->fpuc;
4019
 
}
4020
 
 
4021
 
static void update_fp_status(void)
4022
 
{
4023
 
    int rnd_type;
4024
 
 
4025
 
    /* set rounding mode */
4026
 
    switch(env->fpuc & FPU_RC_MASK) {
4027
 
    default:
4028
 
    case FPU_RC_NEAR:
4029
 
        rnd_type = float_round_nearest_even;
4030
 
        break;
4031
 
    case FPU_RC_DOWN:
4032
 
        rnd_type = float_round_down;
4033
 
        break;
4034
 
    case FPU_RC_UP:
4035
 
        rnd_type = float_round_up;
4036
 
        break;
4037
 
    case FPU_RC_CHOP:
4038
 
        rnd_type = float_round_to_zero;
4039
 
        break;
4040
 
    }
4041
 
    set_float_rounding_mode(rnd_type, &env->fp_status);
4042
 
    switch((env->fpuc >> 8) & 3) {
4043
 
    case 0:
4044
 
        rnd_type = 32;
4045
 
        break;
4046
 
    case 2:
4047
 
        rnd_type = 64;
4048
 
        break;
4049
 
    case 3:
4050
 
    default:
4051
 
        rnd_type = 80;
4052
 
        break;
4053
 
    }
4054
 
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
4055
 
}
4056
 
 
4057
 
void helper_fldcw(uint32_t val)
4058
 
{
4059
 
    env->fpuc = val;
4060
 
    update_fp_status();
4061
 
}
4062
 
 
4063
 
void helper_fclex(void)
4064
 
{
4065
 
    env->fpus &= 0x7f00;
4066
 
}
4067
 
 
4068
 
void helper_fwait(void)
4069
 
{
4070
 
    if (env->fpus & FPUS_SE)
4071
 
        fpu_raise_exception();
4072
 
}
4073
 
 
4074
 
void helper_fninit(void)
4075
 
{
4076
 
    env->fpus = 0;
4077
 
    env->fpstt = 0;
4078
 
    env->fpuc = 0x37f;
4079
 
    env->fptags[0] = 1;
4080
 
    env->fptags[1] = 1;
4081
 
    env->fptags[2] = 1;
4082
 
    env->fptags[3] = 1;
4083
 
    env->fptags[4] = 1;
4084
 
    env->fptags[5] = 1;
4085
 
    env->fptags[6] = 1;
4086
 
    env->fptags[7] = 1;
4087
 
}
4088
 
 
4089
 
/* BCD ops */
4090
 
 
4091
 
void helper_fbld_ST0(target_ulong ptr)
4092
 
{
4093
 
    floatx80 tmp;
4094
 
    uint64_t val;
4095
 
    unsigned int v;
4096
 
    int i;
4097
 
 
4098
 
    val = 0;
4099
 
    for(i = 8; i >= 0; i--) {
4100
 
        v = ldub(ptr + i);
4101
 
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
4102
 
    }
4103
 
    tmp = int64_to_floatx80(val, &env->fp_status);
4104
 
    if (ldub(ptr + 9) & 0x80) {
4105
 
        floatx80_chs(tmp);
4106
 
    }
4107
 
    fpush();
4108
 
    ST0 = tmp;
4109
 
}
4110
 
 
4111
 
void helper_fbst_ST0(target_ulong ptr)
4112
 
{
4113
 
    int v;
4114
 
    target_ulong mem_ref, mem_end;
4115
 
    int64_t val;
4116
 
 
4117
 
    val = floatx80_to_int64(ST0, &env->fp_status);
4118
 
    mem_ref = ptr;
4119
 
    mem_end = mem_ref + 9;
4120
 
    if (val < 0) {
4121
 
        stb(mem_end, 0x80);
4122
 
        val = -val;
4123
 
    } else {
4124
 
        stb(mem_end, 0x00);
4125
 
    }
4126
 
    while (mem_ref < mem_end) {
4127
 
        if (val == 0)
4128
 
            break;
4129
 
        v = val % 100;
4130
 
        val = val / 100;
4131
 
        v = ((v / 10) << 4) | (v % 10);
4132
 
        stb(mem_ref++, v);
4133
 
    }
4134
 
    while (mem_ref < mem_end) {
4135
 
        stb(mem_ref++, 0);
4136
 
    }
4137
 
}
4138
 
 
4139
 
void helper_f2xm1(void)
4140
 
{
4141
 
    double val = floatx80_to_double(ST0);
4142
 
    val = pow(2.0, val) - 1.0;
4143
 
    ST0 = double_to_floatx80(val);
4144
 
}
4145
 
 
4146
 
void helper_fyl2x(void)
4147
 
{
4148
 
    double fptemp = floatx80_to_double(ST0);
4149
 
 
4150
 
    if (fptemp>0.0){
4151
 
        fptemp = log(fptemp)/log(2.0);    /* log2(ST) */
4152
 
        fptemp *= floatx80_to_double(ST1);
4153
 
        ST1 = double_to_floatx80(fptemp);
4154
 
        fpop();
4155
 
    } else {
4156
 
        env->fpus &= (~0x4700);
4157
 
        env->fpus |= 0x400;
4158
 
    }
4159
 
}
4160
 
 
4161
 
void helper_fptan(void)
4162
 
{
4163
 
    double fptemp = floatx80_to_double(ST0);
4164
 
 
4165
 
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4166
 
        env->fpus |= 0x400;
4167
 
    } else {
4168
 
        fptemp = tan(fptemp);
4169
 
        ST0 = double_to_floatx80(fptemp);
4170
 
        fpush();
4171
 
        ST0 = floatx80_one;
4172
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4173
 
        /* the above code is for  |arg| < 2**52 only */
4174
 
    }
4175
 
}
4176
 
 
4177
 
void helper_fpatan(void)
4178
 
{
4179
 
    double fptemp, fpsrcop;
4180
 
 
4181
 
    fpsrcop = floatx80_to_double(ST1);
4182
 
    fptemp = floatx80_to_double(ST0);
4183
 
    ST1 = double_to_floatx80(atan2(fpsrcop, fptemp));
4184
 
    fpop();
4185
 
}
4186
 
 
4187
 
void helper_fxtract(void)
4188
 
{
4189
 
    CPU_LDoubleU temp;
4190
 
 
4191
 
    temp.d = ST0;
4192
 
 
4193
 
    if (floatx80_is_zero(ST0)) {
4194
 
        /* Easy way to generate -inf and raising division by 0 exception */
4195
 
        ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero, &env->fp_status);
4196
 
        fpush();
4197
 
        ST0 = temp.d;
4198
 
    } else {
4199
 
        int expdif;
4200
 
 
4201
 
        expdif = EXPD(temp) - EXPBIAS;
4202
 
        /*DP exponent bias*/
4203
 
        ST0 = int32_to_floatx80(expdif, &env->fp_status);
4204
 
        fpush();
4205
 
        BIASEXPONENT(temp);
4206
 
        ST0 = temp.d;
4207
 
    }
4208
 
}
4209
 
 
4210
 
void helper_fprem1(void)
4211
 
{
4212
 
    double st0, st1, dblq, fpsrcop, fptemp;
4213
 
    CPU_LDoubleU fpsrcop1, fptemp1;
4214
 
    int expdif;
4215
 
    signed long long int q;
4216
 
 
4217
 
    st0 = floatx80_to_double(ST0);
4218
 
    st1 = floatx80_to_double(ST1);
4219
 
 
4220
 
    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
4221
 
        ST0 = double_to_floatx80(0.0 / 0.0); /* NaN */
4222
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4223
 
        return;
4224
 
    }
4225
 
 
4226
 
    fpsrcop = st0;
4227
 
    fptemp = st1;
4228
 
    fpsrcop1.d = ST0;
4229
 
    fptemp1.d = ST1;
4230
 
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4231
 
 
4232
 
    if (expdif < 0) {
4233
 
        /* optimisation? taken from the AMD docs */
4234
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4235
 
        /* ST0 is unchanged */
4236
 
        return;
4237
 
    }
4238
 
 
4239
 
    if (expdif < 53) {
4240
 
        dblq = fpsrcop / fptemp;
4241
 
        /* round dblq towards nearest integer */
4242
 
        dblq = rint(dblq);
4243
 
        st0 = fpsrcop - fptemp * dblq;
4244
 
 
4245
 
        /* convert dblq to q by truncating towards zero */
4246
 
        if (dblq < 0.0)
4247
 
           q = (signed long long int)(-dblq);
4248
 
        else
4249
 
           q = (signed long long int)dblq;
4250
 
 
4251
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4252
 
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4253
 
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4254
 
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4255
 
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4256
 
    } else {
4257
 
        env->fpus |= 0x400;  /* C2 <-- 1 */
4258
 
        fptemp = pow(2.0, expdif - 50);
4259
 
        fpsrcop = (st0 / st1) / fptemp;
4260
 
        /* fpsrcop = integer obtained by chopping */
4261
 
        fpsrcop = (fpsrcop < 0.0) ?
4262
 
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4263
 
        st0 -= (st1 * fpsrcop * fptemp);
4264
 
    }
4265
 
    ST0 = double_to_floatx80(st0);
4266
 
}
4267
 
 
4268
 
void helper_fprem(void)
4269
 
{
4270
 
    double st0, st1, dblq, fpsrcop, fptemp;
4271
 
    CPU_LDoubleU fpsrcop1, fptemp1;
4272
 
    int expdif;
4273
 
    signed long long int q;
4274
 
 
4275
 
    st0 = floatx80_to_double(ST0);
4276
 
    st1 = floatx80_to_double(ST1);
4277
 
 
4278
 
    if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
4279
 
       ST0 = double_to_floatx80(0.0 / 0.0); /* NaN */
4280
 
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4281
 
       return;
4282
 
    }
4283
 
 
4284
 
    fpsrcop = st0;
4285
 
    fptemp = st1;
4286
 
    fpsrcop1.d = ST0;
4287
 
    fptemp1.d = ST1;
4288
 
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
4289
 
 
4290
 
    if (expdif < 0) {
4291
 
        /* optimisation? taken from the AMD docs */
4292
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4293
 
        /* ST0 is unchanged */
4294
 
        return;
4295
 
    }
4296
 
 
4297
 
    if ( expdif < 53 ) {
4298
 
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4299
 
        /* round dblq towards zero */
4300
 
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4301
 
        st0 = fpsrcop/*ST0*/ - fptemp * dblq;
4302
 
 
4303
 
        /* convert dblq to q by truncating towards zero */
4304
 
        if (dblq < 0.0)
4305
 
           q = (signed long long int)(-dblq);
4306
 
        else
4307
 
           q = (signed long long int)dblq;
4308
 
 
4309
 
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4310
 
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
4311
 
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4312
 
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4313
 
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4314
 
    } else {
4315
 
        int N = 32 + (expdif % 32); /* as per AMD docs */
4316
 
        env->fpus |= 0x400;  /* C2 <-- 1 */
4317
 
        fptemp = pow(2.0, (double)(expdif - N));
4318
 
        fpsrcop = (st0 / st1) / fptemp;
4319
 
        /* fpsrcop = integer obtained by chopping */
4320
 
        fpsrcop = (fpsrcop < 0.0) ?
4321
 
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4322
 
        st0 -= (st1 * fpsrcop * fptemp);
4323
 
    }
4324
 
    ST0 = double_to_floatx80(st0);
4325
 
}
4326
 
 
4327
 
void helper_fyl2xp1(void)
4328
 
{
4329
 
    double fptemp = floatx80_to_double(ST0);
4330
 
 
4331
 
    if ((fptemp+1.0)>0.0) {
4332
 
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4333
 
        fptemp *= floatx80_to_double(ST1);
4334
 
        ST1 = double_to_floatx80(fptemp);
4335
 
        fpop();
4336
 
    } else {
4337
 
        env->fpus &= (~0x4700);
4338
 
        env->fpus |= 0x400;
4339
 
    }
4340
 
}
4341
 
 
4342
 
void helper_fsqrt(void)
4343
 
{
4344
 
    if (floatx80_is_neg(ST0)) {
4345
 
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4346
 
        env->fpus |= 0x400;
4347
 
    }
4348
 
    ST0 = floatx80_sqrt(ST0, &env->fp_status);
4349
 
}
4350
 
 
4351
 
void helper_fsincos(void)
4352
 
{
4353
 
    double fptemp = floatx80_to_double(ST0);
4354
 
 
4355
 
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4356
 
        env->fpus |= 0x400;
4357
 
    } else {
4358
 
        ST0 = double_to_floatx80(sin(fptemp));
4359
 
        fpush();
4360
 
        ST0 = double_to_floatx80(cos(fptemp));
4361
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4362
 
        /* the above code is for  |arg| < 2**63 only */
4363
 
    }
4364
 
}
4365
 
 
4366
 
void helper_frndint(void)
4367
 
{
4368
 
    ST0 = floatx80_round_to_int(ST0, &env->fp_status);
4369
 
}
4370
 
 
4371
 
void helper_fscale(void)
4372
 
{
4373
 
    if (floatx80_is_any_nan(ST1)) {
4374
 
        ST0 = ST1;
4375
 
    } else {
4376
 
        int n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status);
4377
 
        ST0 = floatx80_scalbn(ST0, n, &env->fp_status);
4378
 
    }
4379
 
}
4380
 
 
4381
 
void helper_fsin(void)
4382
 
{
4383
 
    double fptemp = floatx80_to_double(ST0);
4384
 
 
4385
 
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4386
 
        env->fpus |= 0x400;
4387
 
    } else {
4388
 
        ST0 = double_to_floatx80(sin(fptemp));
4389
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4390
 
        /* the above code is for  |arg| < 2**53 only */
4391
 
    }
4392
 
}
4393
 
 
4394
 
void helper_fcos(void)
4395
 
{
4396
 
    double fptemp = floatx80_to_double(ST0);
4397
 
 
4398
 
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4399
 
        env->fpus |= 0x400;
4400
 
    } else {
4401
 
        ST0 = double_to_floatx80(cos(fptemp));
4402
 
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4403
 
        /* the above code is for  |arg5 < 2**63 only */
4404
 
    }
4405
 
}
4406
 
 
4407
 
void helper_fxam_ST0(void)
4408
 
{
4409
 
    CPU_LDoubleU temp;
4410
 
    int expdif;
4411
 
 
4412
 
    temp.d = ST0;
4413
 
 
4414
 
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4415
 
    if (SIGND(temp))
4416
 
        env->fpus |= 0x200; /* C1 <-- 1 */
4417
 
 
4418
 
    /* XXX: test fptags too */
4419
 
    expdif = EXPD(temp);
4420
 
    if (expdif == MAXEXPD) {
4421
 
        if (MANTD(temp) == 0x8000000000000000ULL)
4422
 
            env->fpus |=  0x500 /*Infinity*/;
4423
 
        else
4424
 
            env->fpus |=  0x100 /*NaN*/;
4425
 
    } else if (expdif == 0) {
4426
 
        if (MANTD(temp) == 0)
4427
 
            env->fpus |=  0x4000 /*Zero*/;
4428
 
        else
4429
 
            env->fpus |= 0x4400 /*Denormal*/;
4430
 
    } else {
4431
 
        env->fpus |= 0x400;
4432
 
    }
4433
 
}
4434
 
 
4435
 
void helper_fstenv(target_ulong ptr, int data32)
4436
 
{
4437
 
    int fpus, fptag, exp, i;
4438
 
    uint64_t mant;
4439
 
    CPU_LDoubleU tmp;
4440
 
 
4441
 
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4442
 
    fptag = 0;
4443
 
    for (i=7; i>=0; i--) {
4444
 
        fptag <<= 2;
4445
 
        if (env->fptags[i]) {
4446
 
            fptag |= 3;
4447
 
        } else {
4448
 
            tmp.d = env->fpregs[i].d;
4449
 
            exp = EXPD(tmp);
4450
 
            mant = MANTD(tmp);
4451
 
            if (exp == 0 && mant == 0) {
4452
 
                /* zero */
4453
 
                fptag |= 1;
4454
 
            } else if (exp == 0 || exp == MAXEXPD
4455
 
                       || (mant & (1LL << 63)) == 0
4456
 
                       ) {
4457
 
                /* NaNs, infinity, denormal */
4458
 
                fptag |= 2;
4459
 
            }
4460
 
        }
4461
 
    }
4462
 
    if (data32) {
4463
 
        /* 32 bit */
4464
 
        stl(ptr, env->fpuc);
4465
 
        stl(ptr + 4, fpus);
4466
 
        stl(ptr + 8, fptag);
4467
 
        stl(ptr + 12, 0); /* fpip */
4468
 
        stl(ptr + 16, 0); /* fpcs */
4469
 
        stl(ptr + 20, 0); /* fpoo */
4470
 
        stl(ptr + 24, 0); /* fpos */
4471
 
    } else {
4472
 
        /* 16 bit */
4473
 
        stw(ptr, env->fpuc);
4474
 
        stw(ptr + 2, fpus);
4475
 
        stw(ptr + 4, fptag);
4476
 
        stw(ptr + 6, 0);
4477
 
        stw(ptr + 8, 0);
4478
 
        stw(ptr + 10, 0);
4479
 
        stw(ptr + 12, 0);
4480
 
    }
4481
 
}
4482
 
 
4483
 
void helper_fldenv(target_ulong ptr, int data32)
4484
 
{
4485
 
    int i, fpus, fptag;
4486
 
 
4487
 
    if (data32) {
4488
 
        env->fpuc = lduw(ptr);
4489
 
        fpus = lduw(ptr + 4);
4490
 
        fptag = lduw(ptr + 8);
4491
 
    }
4492
 
    else {
4493
 
        env->fpuc = lduw(ptr);
4494
 
        fpus = lduw(ptr + 2);
4495
 
        fptag = lduw(ptr + 4);
4496
 
    }
4497
 
    env->fpstt = (fpus >> 11) & 7;
4498
 
    env->fpus = fpus & ~0x3800;
4499
 
    for(i = 0;i < 8; i++) {
4500
 
        env->fptags[i] = ((fptag & 3) == 3);
4501
 
        fptag >>= 2;
4502
 
    }
4503
 
}
4504
 
 
4505
 
void helper_fsave(target_ulong ptr, int data32)
4506
 
{
4507
 
    floatx80 tmp;
4508
 
    int i;
4509
 
 
4510
 
    helper_fstenv(ptr, data32);
4511
 
 
4512
 
    ptr += (14 << data32);
4513
 
    for(i = 0;i < 8; i++) {
4514
 
        tmp = ST(i);
4515
 
        helper_fstt(tmp, ptr);
4516
 
        ptr += 10;
4517
 
    }
4518
 
 
4519
 
    /* fninit */
4520
 
    env->fpus = 0;
4521
 
    env->fpstt = 0;
4522
 
    env->fpuc = 0x37f;
4523
 
    env->fptags[0] = 1;
4524
 
    env->fptags[1] = 1;
4525
 
    env->fptags[2] = 1;
4526
 
    env->fptags[3] = 1;
4527
 
    env->fptags[4] = 1;
4528
 
    env->fptags[5] = 1;
4529
 
    env->fptags[6] = 1;
4530
 
    env->fptags[7] = 1;
4531
 
}
4532
 
 
4533
 
void helper_frstor(target_ulong ptr, int data32)
4534
 
{
4535
 
    floatx80 tmp;
4536
 
    int i;
4537
 
 
4538
 
    helper_fldenv(ptr, data32);
4539
 
    ptr += (14 << data32);
4540
 
 
4541
 
    for(i = 0;i < 8; i++) {
4542
 
        tmp = helper_fldt(ptr);
4543
 
        ST(i) = tmp;
4544
 
        ptr += 10;
4545
 
    }
4546
 
}
4547
 
 
4548
 
 
4549
 
#if defined(CONFIG_USER_ONLY)
4550
 
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
4551
 
{
4552
 
    CPUX86State *saved_env;
4553
 
 
4554
 
    saved_env = env;
4555
 
    env = s;
4556
 
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
4557
 
        selector &= 0xffff;
4558
 
        cpu_x86_load_seg_cache(env, seg_reg, selector,
4559
 
                               (selector << 4), 0xffff, 0);
4560
 
    } else {
4561
 
        helper_load_seg(seg_reg, selector);
4562
 
    }
4563
 
    env = saved_env;
4564
 
}
4565
 
 
4566
 
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
4567
 
{
4568
 
    CPUX86State *saved_env;
4569
 
 
4570
 
    saved_env = env;
4571
 
    env = s;
4572
 
 
4573
 
    helper_fsave(ptr, data32);
4574
 
 
4575
 
    env = saved_env;
4576
 
}
4577
 
 
4578
 
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
4579
 
{
4580
 
    CPUX86State *saved_env;
4581
 
 
4582
 
    saved_env = env;
4583
 
    env = s;
4584
 
 
4585
 
    helper_frstor(ptr, data32);
4586
 
 
4587
 
    env = saved_env;
4588
 
}
4589
 
#endif
4590
 
 
4591
 
void helper_fxsave(target_ulong ptr, int data64)
4592
 
{
4593
 
    int fpus, fptag, i, nb_xmm_regs;
4594
 
    floatx80 tmp;
4595
 
    target_ulong addr;
4596
 
 
4597
 
    /* The operand must be 16 byte aligned */
4598
 
    if (ptr & 0xf) {
4599
 
        raise_exception(EXCP0D_GPF);
4600
 
    }
4601
 
 
4602
 
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4603
 
    fptag = 0;
4604
 
    for(i = 0; i < 8; i++) {
4605
 
        fptag |= (env->fptags[i] << i);
4606
 
    }
4607
 
    stw(ptr, env->fpuc);
4608
 
    stw(ptr + 2, fpus);
4609
 
    stw(ptr + 4, fptag ^ 0xff);
4610
 
#ifdef TARGET_X86_64
4611
 
    if (data64) {
4612
 
        stq(ptr + 0x08, 0); /* rip */
4613
 
        stq(ptr + 0x10, 0); /* rdp */
4614
 
    } else 
4615
 
#endif
4616
 
    {
4617
 
        stl(ptr + 0x08, 0); /* eip */
4618
 
        stl(ptr + 0x0c, 0); /* sel  */
4619
 
        stl(ptr + 0x10, 0); /* dp */
4620
 
        stl(ptr + 0x14, 0); /* sel  */
4621
 
    }
4622
 
 
4623
 
    addr = ptr + 0x20;
4624
 
    for(i = 0;i < 8; i++) {
4625
 
        tmp = ST(i);
4626
 
        helper_fstt(tmp, addr);
4627
 
        addr += 16;
4628
 
    }
4629
 
 
4630
 
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4631
 
        /* XXX: finish it */
4632
 
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4633
 
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4634
 
        if (env->hflags & HF_CS64_MASK)
4635
 
            nb_xmm_regs = 16;
4636
 
        else
4637
 
            nb_xmm_regs = 8;
4638
 
        addr = ptr + 0xa0;
4639
 
        /* Fast FXSAVE leaves out the XMM registers */
4640
 
        if (!(env->efer & MSR_EFER_FFXSR)
4641
 
          || (env->hflags & HF_CPL_MASK)
4642
 
          || !(env->hflags & HF_LMA_MASK)) {
4643
 
            for(i = 0; i < nb_xmm_regs; i++) {
4644
 
                stq(addr, env->xmm_regs[i].XMM_Q(0));
4645
 
                stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4646
 
                addr += 16;
4647
 
            }
4648
 
        }
4649
 
    }
4650
 
}
4651
 
 
4652
 
void helper_fxrstor(target_ulong ptr, int data64)
4653
 
{
4654
 
    int i, fpus, fptag, nb_xmm_regs;
4655
 
    floatx80 tmp;
4656
 
    target_ulong addr;
4657
 
 
4658
 
    /* The operand must be 16 byte aligned */
4659
 
    if (ptr & 0xf) {
4660
 
        raise_exception(EXCP0D_GPF);
4661
 
    }
4662
 
 
4663
 
    env->fpuc = lduw(ptr);
4664
 
    fpus = lduw(ptr + 2);
4665
 
    fptag = lduw(ptr + 4);
4666
 
    env->fpstt = (fpus >> 11) & 7;
4667
 
    env->fpus = fpus & ~0x3800;
4668
 
    fptag ^= 0xff;
4669
 
    for(i = 0;i < 8; i++) {
4670
 
        env->fptags[i] = ((fptag >> i) & 1);
4671
 
    }
4672
 
 
4673
 
    addr = ptr + 0x20;
4674
 
    for(i = 0;i < 8; i++) {
4675
 
        tmp = helper_fldt(addr);
4676
 
        ST(i) = tmp;
4677
 
        addr += 16;
4678
 
    }
4679
 
 
4680
 
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4681
 
        /* XXX: finish it */
4682
 
        env->mxcsr = ldl(ptr + 0x18);
4683
 
        //ldl(ptr + 0x1c);
4684
 
        if (env->hflags & HF_CS64_MASK)
4685
 
            nb_xmm_regs = 16;
4686
 
        else
4687
 
            nb_xmm_regs = 8;
4688
 
        addr = ptr + 0xa0;
4689
 
        /* Fast FXRESTORE leaves out the XMM registers */
4690
 
        if (!(env->efer & MSR_EFER_FFXSR)
4691
 
          || (env->hflags & HF_CPL_MASK)
4692
 
          || !(env->hflags & HF_LMA_MASK)) {
4693
 
            for(i = 0; i < nb_xmm_regs; i++) {
4694
 
                env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4695
 
                env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4696
 
                addr += 16;
4697
 
            }
4698
 
        }
4699
 
    }
4700
 
}
4701
 
 
4702
 
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
4703
 
{
4704
 
    CPU_LDoubleU temp;
4705
 
 
4706
 
    temp.d = f;
4707
 
    *pmant = temp.l.lower;
4708
 
    *pexp = temp.l.upper;
4709
 
}
4710
 
 
4711
 
floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
4712
 
{
4713
 
    CPU_LDoubleU temp;
4714
 
 
4715
 
    temp.l.upper = upper;
4716
 
    temp.l.lower = mant;
4717
 
    return temp.d;
4718
 
}
4719
 
 
4720
 
#ifdef TARGET_X86_64
4721
 
 
4722
 
//#define DEBUG_MULDIV
4723
 
 
4724
 
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4725
 
{
4726
 
    *plow += a;
4727
 
    /* carry test */
4728
 
    if (*plow < a)
4729
 
        (*phigh)++;
4730
 
    *phigh += b;
4731
 
}
4732
 
 
4733
 
static void neg128(uint64_t *plow, uint64_t *phigh)
4734
 
{
4735
 
    *plow = ~ *plow;
4736
 
    *phigh = ~ *phigh;
4737
 
    add128(plow, phigh, 1, 0);
4738
 
}
4739
 
 
4740
 
/* return TRUE if overflow */
4741
 
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4742
 
{
4743
 
    uint64_t q, r, a1, a0;
4744
 
    int i, qb, ab;
4745
 
 
4746
 
    a0 = *plow;
4747
 
    a1 = *phigh;
4748
 
    if (a1 == 0) {
4749
 
        q = a0 / b;
4750
 
        r = a0 % b;
4751
 
        *plow = q;
4752
 
        *phigh = r;
4753
 
    } else {
4754
 
        if (a1 >= b)
4755
 
            return 1;
4756
 
        /* XXX: use a better algorithm */
4757
 
        for(i = 0; i < 64; i++) {
4758
 
            ab = a1 >> 63;
4759
 
            a1 = (a1 << 1) | (a0 >> 63);
4760
 
            if (ab || a1 >= b) {
4761
 
                a1 -= b;
4762
 
                qb = 1;
4763
 
            } else {
4764
 
                qb = 0;
4765
 
            }
4766
 
            a0 = (a0 << 1) | qb;
4767
 
        }
4768
 
#if defined(DEBUG_MULDIV)
4769
 
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4770
 
               *phigh, *plow, b, a0, a1);
4771
 
#endif
4772
 
        *plow = a0;
4773
 
        *phigh = a1;
4774
 
    }
4775
 
    return 0;
4776
 
}
4777
 
 
4778
 
/* return TRUE if overflow */
4779
 
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4780
 
{
4781
 
    int sa, sb;
4782
 
    sa = ((int64_t)*phigh < 0);
4783
 
    if (sa)
4784
 
        neg128(plow, phigh);
4785
 
    sb = (b < 0);
4786
 
    if (sb)
4787
 
        b = -b;
4788
 
    if (div64(plow, phigh, b) != 0)
4789
 
        return 1;
4790
 
    if (sa ^ sb) {
4791
 
        if (*plow > (1ULL << 63))
4792
 
            return 1;
4793
 
        *plow = - *plow;
4794
 
    } else {
4795
 
        if (*plow >= (1ULL << 63))
4796
 
            return 1;
4797
 
    }
4798
 
    if (sa)
4799
 
        *phigh = - *phigh;
4800
 
    return 0;
4801
 
}
4802
 
 
4803
 
void helper_mulq_EAX_T0(target_ulong t0)
4804
 
{
4805
 
    uint64_t r0, r1;
4806
 
 
4807
 
    mulu64(&r0, &r1, EAX, t0);
4808
 
    EAX = r0;
4809
 
    EDX = r1;
4810
 
    CC_DST = r0;
4811
 
    CC_SRC = r1;
4812
 
}
4813
 
 
4814
 
void helper_imulq_EAX_T0(target_ulong t0)
4815
 
{
4816
 
    uint64_t r0, r1;
4817
 
 
4818
 
    muls64(&r0, &r1, EAX, t0);
4819
 
    EAX = r0;
4820
 
    EDX = r1;
4821
 
    CC_DST = r0;
4822
 
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4823
 
}
4824
 
 
4825
 
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4826
 
{
4827
 
    uint64_t r0, r1;
4828
 
 
4829
 
    muls64(&r0, &r1, t0, t1);
4830
 
    CC_DST = r0;
4831
 
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4832
 
    return r0;
4833
 
}
4834
 
 
4835
 
void helper_divq_EAX(target_ulong t0)
4836
 
{
4837
 
    uint64_t r0, r1;
4838
 
    if (t0 == 0) {
4839
 
        raise_exception(EXCP00_DIVZ);
4840
 
    }
4841
 
    r0 = EAX;
4842
 
    r1 = EDX;
4843
 
    if (div64(&r0, &r1, t0))
4844
 
        raise_exception(EXCP00_DIVZ);
4845
 
    EAX = r0;
4846
 
    EDX = r1;
4847
 
}
4848
 
 
4849
 
void helper_idivq_EAX(target_ulong t0)
4850
 
{
4851
 
    uint64_t r0, r1;
4852
 
    if (t0 == 0) {
4853
 
        raise_exception(EXCP00_DIVZ);
4854
 
    }
4855
 
    r0 = EAX;
4856
 
    r1 = EDX;
4857
 
    if (idiv64(&r0, &r1, t0))
4858
 
        raise_exception(EXCP00_DIVZ);
4859
 
    EAX = r0;
4860
 
    EDX = r1;
4861
 
}
4862
 
#endif
4863
 
 
4864
 
static void do_hlt(void)
4865
 
{
4866
 
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4867
 
    env->halted = 1;
4868
 
    env->exception_index = EXCP_HLT;
4869
 
    cpu_loop_exit(env);
4870
 
}
4871
 
 
4872
 
void helper_hlt(int next_eip_addend)
4873
 
{
4874
 
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4875
 
    EIP += next_eip_addend;
4876
 
    
4877
 
    do_hlt();
4878
 
}
4879
 
 
4880
 
void helper_monitor(target_ulong ptr)
4881
 
{
4882
 
    if ((uint32_t)ECX != 0)
4883
 
        raise_exception(EXCP0D_GPF);
4884
 
    /* XXX: store address ? */
4885
 
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4886
 
}
4887
 
 
4888
 
void helper_mwait(int next_eip_addend)
4889
 
{
4890
 
    if ((uint32_t)ECX != 0)
4891
 
        raise_exception(EXCP0D_GPF);
4892
 
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4893
 
    EIP += next_eip_addend;
4894
 
 
4895
 
    /* XXX: not complete but not completely erroneous */
4896
 
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4897
 
        /* more than one CPU: do not sleep because another CPU may
4898
 
           wake this one */
4899
 
    } else {
4900
 
        do_hlt();
4901
 
    }
4902
 
}
4903
 
 
4904
 
void helper_debug(void)
4905
 
{
4906
 
    env->exception_index = EXCP_DEBUG;
4907
 
    cpu_loop_exit(env);
4908
 
}
4909
 
 
4910
 
void helper_reset_rf(void)
4911
 
{
4912
 
    env->eflags &= ~RF_MASK;
4913
 
}
4914
 
 
4915
 
void helper_raise_interrupt(int intno, int next_eip_addend)
4916
 
{
4917
 
    raise_interrupt(intno, 1, 0, next_eip_addend);
4918
 
}
4919
 
 
4920
 
void helper_raise_exception(int exception_index)
4921
 
{
4922
 
    raise_exception(exception_index);
4923
 
}
4924
 
 
4925
 
void helper_cli(void)
4926
 
{
4927
 
    env->eflags &= ~IF_MASK;
4928
 
}
4929
 
 
4930
 
void helper_sti(void)
4931
 
{
4932
 
    env->eflags |= IF_MASK;
4933
 
}
4934
 
 
4935
 
#if 0
4936
 
/* vm86plus instructions */
4937
 
void helper_cli_vm(void)
4938
 
{
4939
 
    env->eflags &= ~VIF_MASK;
4940
 
}
4941
 
 
4942
 
void helper_sti_vm(void)
4943
 
{
4944
 
    env->eflags |= VIF_MASK;
4945
 
    if (env->eflags & VIP_MASK) {
4946
 
        raise_exception(EXCP0D_GPF);
4947
 
    }
4948
 
}
4949
 
#endif
4950
 
 
4951
 
void helper_set_inhibit_irq(void)
4952
 
{
4953
 
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4954
 
}
4955
 
 
4956
 
void helper_reset_inhibit_irq(void)
4957
 
{
4958
 
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4959
 
}
4960
 
 
4961
 
void helper_boundw(target_ulong a0, int v)
4962
 
{
4963
 
    int low, high;
4964
 
    low = ldsw(a0);
4965
 
    high = ldsw(a0 + 2);
4966
 
    v = (int16_t)v;
4967
 
    if (v < low || v > high) {
4968
 
        raise_exception(EXCP05_BOUND);
4969
 
    }
4970
 
}
4971
 
 
4972
 
void helper_boundl(target_ulong a0, int v)
4973
 
{
4974
 
    int low, high;
4975
 
    low = ldl(a0);
4976
 
    high = ldl(a0 + 4);
4977
 
    if (v < low || v > high) {
4978
 
        raise_exception(EXCP05_BOUND);
4979
 
    }
4980
 
}
4981
 
 
4982
 
#if !defined(CONFIG_USER_ONLY)
4983
 
 
4984
 
#define MMUSUFFIX _mmu
4985
 
 
4986
 
#define SHIFT 0
4987
 
#include "softmmu_template.h"
4988
 
 
4989
 
#define SHIFT 1
4990
 
#include "softmmu_template.h"
4991
 
 
4992
 
#define SHIFT 2
4993
 
#include "softmmu_template.h"
4994
 
 
4995
 
#define SHIFT 3
4996
 
#include "softmmu_template.h"
4997
 
 
4998
 
#endif
4999
 
 
5000
 
#if !defined(CONFIG_USER_ONLY)
5001
 
/* try to fill the TLB and return an exception if error. If retaddr is
5002
 
   NULL, it means that the function was called in C code (i.e. not
5003
 
   from generated code or from helper.c) */
5004
 
/* XXX: fix it to restore all registers */
5005
 
void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
5006
 
              void *retaddr)
5007
 
{
5008
 
    TranslationBlock *tb;
5009
 
    int ret;
5010
 
    unsigned long pc;
5011
 
    CPUX86State *saved_env;
5012
 
 
5013
 
    saved_env = env;
5014
 
    env = env1;
5015
 
 
5016
 
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx);
5017
 
    if (ret) {
5018
 
        if (retaddr) {
5019
 
            /* now we have a real cpu fault */
5020
 
            pc = (unsigned long)retaddr;
5021
 
            tb = tb_find_pc(pc);
5022
 
            if (tb) {
5023
 
                /* the PC is inside the translated code. It means that we have
5024
 
                   a virtual CPU fault */
5025
 
                cpu_restore_state(tb, env, pc);
5026
 
            }
5027
 
        }
5028
 
        raise_exception_err(env->exception_index, env->error_code);
5029
 
    }
5030
 
    env = saved_env;
5031
 
}
5032
 
#endif
5033
 
 
5034
 
/* Secure Virtual Machine helpers */
5035
 
 
5036
 
#if defined(CONFIG_USER_ONLY)
5037
 
 
5038
 
void helper_vmrun(int aflag, int next_eip_addend)
5039
 
5040
 
}
5041
 
void helper_vmmcall(void) 
5042
 
5043
 
}
5044
 
void helper_vmload(int aflag)
5045
 
5046
 
}
5047
 
void helper_vmsave(int aflag)
5048
 
5049
 
}
5050
 
void helper_stgi(void)
5051
 
{
5052
 
}
5053
 
void helper_clgi(void)
5054
 
{
5055
 
}
5056
 
void helper_skinit(void) 
5057
 
5058
 
}
5059
 
void helper_invlpga(int aflag)
5060
 
5061
 
}
5062
 
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
5063
 
5064
 
}
5065
 
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5066
 
{
5067
 
}
5068
 
 
5069
 
void svm_check_intercept(CPUState *env1, uint32_t type)
5070
 
{
5071
 
}
5072
 
 
5073
 
void helper_svm_check_io(uint32_t port, uint32_t param, 
5074
 
                         uint32_t next_eip_addend)
5075
 
{
5076
 
}
5077
 
#else
5078
 
 
5079
 
static inline void svm_save_seg(target_phys_addr_t addr,
5080
 
                                const SegmentCache *sc)
5081
 
{
5082
 
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
5083
 
             sc->selector);
5084
 
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
5085
 
             sc->base);
5086
 
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
5087
 
             sc->limit);
5088
 
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
5089
 
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
5090
 
}
5091
 
                                
5092
 
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
5093
 
{
5094
 
    unsigned int flags;
5095
 
 
5096
 
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
5097
 
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
5098
 
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
5099
 
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
5100
 
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
5101
 
}
5102
 
 
5103
 
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
5104
 
                                      CPUState *env, int seg_reg)
5105
 
{
5106
 
    SegmentCache sc1, *sc = &sc1;
5107
 
    svm_load_seg(addr, sc);
5108
 
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
5109
 
                           sc->base, sc->limit, sc->flags);
5110
 
}
5111
 
 
5112
 
void helper_vmrun(int aflag, int next_eip_addend)
5113
 
{
5114
 
    target_ulong addr;
5115
 
    uint32_t event_inj;
5116
 
    uint32_t int_ctl;
5117
 
 
5118
 
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
5119
 
 
5120
 
    if (aflag == 2)
5121
 
        addr = EAX;
5122
 
    else
5123
 
        addr = (uint32_t)EAX;
5124
 
 
5125
 
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
5126
 
 
5127
 
    env->vm_vmcb = addr;
5128
 
 
5129
 
    /* save the current CPU state in the hsave page */
5130
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5131
 
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5132
 
 
5133
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5134
 
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5135
 
 
5136
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
5137
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
5138
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
5139
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
5140
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
5141
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
5142
 
 
5143
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
5144
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
5145
 
 
5146
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
5147
 
                  &env->segs[R_ES]);
5148
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
5149
 
                 &env->segs[R_CS]);
5150
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
5151
 
                 &env->segs[R_SS]);
5152
 
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
5153
 
                 &env->segs[R_DS]);
5154
 
 
5155
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
5156
 
             EIP + next_eip_addend);
5157
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
5158
 
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
5159
 
 
5160
 
    /* load the interception bitmaps so we do not need to access the
5161
 
       vmcb in svm mode */
5162
 
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
5163
 
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
5164
 
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
5165
 
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
5166
 
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
5167
 
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
5168
 
 
5169
 
    /* enable intercepts */
5170
 
    env->hflags |= HF_SVMI_MASK;
5171
 
 
5172
 
    env->tsc_offset = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.tsc_offset));
5173
 
 
5174
 
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
5175
 
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
5176
 
 
5177
 
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
5178
 
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
5179
 
 
5180
 
    /* clear exit_info_2 so we behave like the real hardware */
5181
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
5182
 
 
5183
 
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
5184
 
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
5185
 
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
5186
 
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
5187
 
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5188
 
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5189
 
    if (int_ctl & V_INTR_MASKING_MASK) {
5190
 
        env->v_tpr = int_ctl & V_TPR_MASK;
5191
 
        env->hflags2 |= HF2_VINTR_MASK;
5192
 
        if (env->eflags & IF_MASK)
5193
 
            env->hflags2 |= HF2_HIF_MASK;
5194
 
    }
5195
 
 
5196
 
    cpu_load_efer(env, 
5197
 
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
5198
 
    env->eflags = 0;
5199
 
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
5200
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5201
 
    CC_OP = CC_OP_EFLAGS;
5202
 
 
5203
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
5204
 
                       env, R_ES);
5205
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
5206
 
                       env, R_CS);
5207
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
5208
 
                       env, R_SS);
5209
 
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
5210
 
                       env, R_DS);
5211
 
 
5212
 
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
5213
 
    env->eip = EIP;
5214
 
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
5215
 
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
5216
 
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
5217
 
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
5218
 
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
5219
 
 
5220
 
    /* FIXME: guest state consistency checks */
5221
 
 
5222
 
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
5223
 
        case TLB_CONTROL_DO_NOTHING:
5224
 
            break;
5225
 
        case TLB_CONTROL_FLUSH_ALL_ASID:
5226
 
            /* FIXME: this is not 100% correct but should work for now */
5227
 
            tlb_flush(env, 1);
5228
 
        break;
5229
 
    }
5230
 
 
5231
 
    env->hflags2 |= HF2_GIF_MASK;
5232
 
 
5233
 
    if (int_ctl & V_IRQ_MASK) {
5234
 
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
5235
 
    }
5236
 
 
5237
 
    /* maybe we need to inject an event */
5238
 
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
5239
 
    if (event_inj & SVM_EVTINJ_VALID) {
5240
 
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
5241
 
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
5242
 
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
5243
 
 
5244
 
        qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
5245
 
        /* FIXME: need to implement valid_err */
5246
 
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
5247
 
        case SVM_EVTINJ_TYPE_INTR:
5248
 
                env->exception_index = vector;
5249
 
                env->error_code = event_inj_err;
5250
 
                env->exception_is_int = 0;
5251
 
                env->exception_next_eip = -1;
5252
 
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
5253
 
                /* XXX: is it always correct ? */
5254
 
                do_interrupt_all(vector, 0, 0, 0, 1);
5255
 
                break;
5256
 
        case SVM_EVTINJ_TYPE_NMI:
5257
 
                env->exception_index = EXCP02_NMI;
5258
 
                env->error_code = event_inj_err;
5259
 
                env->exception_is_int = 0;
5260
 
                env->exception_next_eip = EIP;
5261
 
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
5262
 
                cpu_loop_exit(env);
5263
 
                break;
5264
 
        case SVM_EVTINJ_TYPE_EXEPT:
5265
 
                env->exception_index = vector;
5266
 
                env->error_code = event_inj_err;
5267
 
                env->exception_is_int = 0;
5268
 
                env->exception_next_eip = -1;
5269
 
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
5270
 
                cpu_loop_exit(env);
5271
 
                break;
5272
 
        case SVM_EVTINJ_TYPE_SOFT:
5273
 
                env->exception_index = vector;
5274
 
                env->error_code = event_inj_err;
5275
 
                env->exception_is_int = 1;
5276
 
                env->exception_next_eip = EIP;
5277
 
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
5278
 
                cpu_loop_exit(env);
5279
 
                break;
5280
 
        }
5281
 
        qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index, env->error_code);
5282
 
    }
5283
 
}
5284
 
 
5285
 
void helper_vmmcall(void)
5286
 
{
5287
 
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
5288
 
    raise_exception(EXCP06_ILLOP);
5289
 
}
5290
 
 
5291
 
void helper_vmload(int aflag)
5292
 
{
5293
 
    target_ulong addr;
5294
 
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
5295
 
 
5296
 
    if (aflag == 2)
5297
 
        addr = EAX;
5298
 
    else
5299
 
        addr = (uint32_t)EAX;
5300
 
 
5301
 
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5302
 
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5303
 
                env->segs[R_FS].base);
5304
 
 
5305
 
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
5306
 
                       env, R_FS);
5307
 
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
5308
 
                       env, R_GS);
5309
 
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
5310
 
                 &env->tr);
5311
 
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
5312
 
                 &env->ldt);
5313
 
 
5314
 
#ifdef TARGET_X86_64
5315
 
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
5316
 
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
5317
 
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
5318
 
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
5319
 
#endif
5320
 
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
5321
 
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
5322
 
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
5323
 
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
5324
 
}
5325
 
 
5326
 
void helper_vmsave(int aflag)
5327
 
{
5328
 
    target_ulong addr;
5329
 
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5330
 
 
5331
 
    if (aflag == 2)
5332
 
        addr = EAX;
5333
 
    else
5334
 
        addr = (uint32_t)EAX;
5335
 
 
5336
 
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5337
 
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5338
 
                env->segs[R_FS].base);
5339
 
 
5340
 
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5341
 
                 &env->segs[R_FS]);
5342
 
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5343
 
                 &env->segs[R_GS]);
5344
 
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5345
 
                 &env->tr);
5346
 
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5347
 
                 &env->ldt);
5348
 
 
5349
 
#ifdef TARGET_X86_64
5350
 
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
5351
 
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
5352
 
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
5353
 
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
5354
 
#endif
5355
 
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
5356
 
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
5357
 
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
5358
 
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
5359
 
}
5360
 
 
5361
 
void helper_stgi(void)
5362
 
{
5363
 
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5364
 
    env->hflags2 |= HF2_GIF_MASK;
5365
 
}
5366
 
 
5367
 
void helper_clgi(void)
5368
 
{
5369
 
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5370
 
    env->hflags2 &= ~HF2_GIF_MASK;
5371
 
}
5372
 
 
5373
 
void helper_skinit(void)
5374
 
{
5375
 
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5376
 
    /* XXX: not implemented */
5377
 
    raise_exception(EXCP06_ILLOP);
5378
 
}
5379
 
 
5380
 
void helper_invlpga(int aflag)
5381
 
{
5382
 
    target_ulong addr;
5383
 
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5384
 
    
5385
 
    if (aflag == 2)
5386
 
        addr = EAX;
5387
 
    else
5388
 
        addr = (uint32_t)EAX;
5389
 
 
5390
 
    /* XXX: could use the ASID to see if it is needed to do the
5391
 
       flush */
5392
 
    tlb_flush_page(env, addr);
5393
 
}
5394
 
 
5395
 
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5396
 
{
5397
 
    if (likely(!(env->hflags & HF_SVMI_MASK)))
5398
 
        return;
5399
 
    switch(type) {
5400
 
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5401
 
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5402
 
            helper_vmexit(type, param);
5403
 
        }
5404
 
        break;
5405
 
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5406
 
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
5407
 
            helper_vmexit(type, param);
5408
 
        }
5409
 
        break;
5410
 
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
5411
 
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
5412
 
            helper_vmexit(type, param);
5413
 
        }
5414
 
        break;
5415
 
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
5416
 
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
5417
 
            helper_vmexit(type, param);
5418
 
        }
5419
 
        break;
5420
 
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
5421
 
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
5422
 
            helper_vmexit(type, param);
5423
 
        }
5424
 
        break;
5425
 
    case SVM_EXIT_MSR:
5426
 
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5427
 
            /* FIXME: this should be read in at vmrun (faster this way?) */
5428
 
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5429
 
            uint32_t t0, t1;
5430
 
            switch((uint32_t)ECX) {
5431
 
            case 0 ... 0x1fff:
5432
 
                t0 = (ECX * 2) % 8;
5433
 
                t1 = (ECX * 2) / 8;
5434
 
                break;
5435
 
            case 0xc0000000 ... 0xc0001fff:
5436
 
                t0 = (8192 + ECX - 0xc0000000) * 2;
5437
 
                t1 = (t0 / 8);
5438
 
                t0 %= 8;
5439
 
                break;
5440
 
            case 0xc0010000 ... 0xc0011fff:
5441
 
                t0 = (16384 + ECX - 0xc0010000) * 2;
5442
 
                t1 = (t0 / 8);
5443
 
                t0 %= 8;
5444
 
                break;
5445
 
            default:
5446
 
                helper_vmexit(type, param);
5447
 
                t0 = 0;
5448
 
                t1 = 0;
5449
 
                break;
5450
 
            }
5451
 
            if (ldub_phys(addr + t1) & ((1 << param) << t0))
5452
 
                helper_vmexit(type, param);
5453
 
        }
5454
 
        break;
5455
 
    default:
5456
 
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5457
 
            helper_vmexit(type, param);
5458
 
        }
5459
 
        break;
5460
 
    }
5461
 
}
5462
 
 
5463
 
void svm_check_intercept(CPUState *env1, uint32_t type)
5464
 
{
5465
 
    CPUState *saved_env;
5466
 
 
5467
 
    saved_env = env;
5468
 
    env = env1;
5469
 
    helper_svm_check_intercept_param(type, 0);
5470
 
    env = saved_env;
5471
 
}
5472
 
 
5473
 
void helper_svm_check_io(uint32_t port, uint32_t param, 
5474
 
                         uint32_t next_eip_addend)
5475
 
{
5476
 
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5477
 
        /* FIXME: this should be read in at vmrun (faster this way?) */
5478
 
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5479
 
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5480
 
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5481
 
            /* next EIP */
5482
 
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5483
 
                     env->eip + next_eip_addend);
5484
 
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5485
 
        }
5486
 
    }
5487
 
}
5488
 
 
5489
 
/* Note: currently only 32 bits of exit_code are used */
5490
 
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5491
 
{
5492
 
    uint32_t int_ctl;
5493
 
 
5494
 
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5495
 
                exit_code, exit_info_1,
5496
 
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5497
 
                EIP);
5498
 
 
5499
 
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5500
 
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5501
 
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5502
 
    } else {
5503
 
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5504
 
    }
5505
 
 
5506
 
    /* Save the VM state in the vmcb */
5507
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5508
 
                 &env->segs[R_ES]);
5509
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5510
 
                 &env->segs[R_CS]);
5511
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5512
 
                 &env->segs[R_SS]);
5513
 
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5514
 
                 &env->segs[R_DS]);
5515
 
 
5516
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5517
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5518
 
 
5519
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5520
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5521
 
 
5522
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5523
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5524
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5525
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5526
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5527
 
 
5528
 
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5529
 
    int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
5530
 
    int_ctl |= env->v_tpr & V_TPR_MASK;
5531
 
    if (env->interrupt_request & CPU_INTERRUPT_VIRQ)
5532
 
        int_ctl |= V_IRQ_MASK;
5533
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5534
 
 
5535
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5536
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5537
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5538
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5539
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5540
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5541
 
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5542
 
 
5543
 
    /* Reload the host state from vm_hsave */
5544
 
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5545
 
    env->hflags &= ~HF_SVMI_MASK;
5546
 
    env->intercept = 0;
5547
 
    env->intercept_exceptions = 0;
5548
 
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5549
 
    env->tsc_offset = 0;
5550
 
 
5551
 
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5552
 
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5553
 
 
5554
 
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5555
 
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5556
 
 
5557
 
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5558
 
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5559
 
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5560
 
    /* we need to set the efer after the crs so the hidden flags get
5561
 
       set properly */
5562
 
    cpu_load_efer(env, 
5563
 
                  ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
5564
 
    env->eflags = 0;
5565
 
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5566
 
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5567
 
    CC_OP = CC_OP_EFLAGS;
5568
 
 
5569
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5570
 
                       env, R_ES);
5571
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5572
 
                       env, R_CS);
5573
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5574
 
                       env, R_SS);
5575
 
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5576
 
                       env, R_DS);
5577
 
 
5578
 
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5579
 
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5580
 
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5581
 
 
5582
 
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5583
 
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5584
 
 
5585
 
    /* other setups */
5586
 
    cpu_x86_set_cpl(env, 0);
5587
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5588
 
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5589
 
 
5590
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info),
5591
 
             ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)));
5592
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err),
5593
 
             ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err)));
5594
 
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 0);
5595
 
 
5596
 
    env->hflags2 &= ~HF2_GIF_MASK;
5597
 
    /* FIXME: Resets the current ASID register to zero (host ASID). */
5598
 
 
5599
 
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5600
 
 
5601
 
    /* Clears the TSC_OFFSET inside the processor. */
5602
 
 
5603
 
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5604
 
       from the page table indicated the host's CR3. If the PDPEs contain
5605
 
       illegal state, the processor causes a shutdown. */
5606
 
 
5607
 
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5608
 
    env->cr[0] |= CR0_PE_MASK;
5609
 
    env->eflags &= ~VM_MASK;
5610
 
 
5611
 
    /* Disables all breakpoints in the host DR7 register. */
5612
 
 
5613
 
    /* Checks the reloaded host state for consistency. */
5614
 
 
5615
 
    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5616
 
       host's code segment or non-canonical (in the case of long mode), a
5617
 
       #GP fault is delivered inside the host.) */
5618
 
 
5619
 
    /* remove any pending exception */
5620
 
    env->exception_index = -1;
5621
 
    env->error_code = 0;
5622
 
    env->old_exception = -1;
5623
 
 
5624
 
    cpu_loop_exit(env);
5625
 
}
5626
 
 
5627
 
#endif
5628
 
 
5629
 
/* MMX/SSE */
5630
 
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5631
 
 
5632
 
#define SSE_DAZ             0x0040
5633
 
#define SSE_RC_MASK         0x6000
5634
 
#define SSE_RC_NEAR         0x0000
5635
 
#define SSE_RC_DOWN         0x2000
5636
 
#define SSE_RC_UP           0x4000
5637
 
#define SSE_RC_CHOP         0x6000
5638
 
#define SSE_FZ              0x8000
5639
 
 
5640
 
static void update_sse_status(void)
5641
 
{
5642
 
    int rnd_type;
5643
 
 
5644
 
    /* set rounding mode */
5645
 
    switch(env->mxcsr & SSE_RC_MASK) {
5646
 
    default:
5647
 
    case SSE_RC_NEAR:
5648
 
        rnd_type = float_round_nearest_even;
5649
 
        break;
5650
 
    case SSE_RC_DOWN:
5651
 
        rnd_type = float_round_down;
5652
 
        break;
5653
 
    case SSE_RC_UP:
5654
 
        rnd_type = float_round_up;
5655
 
        break;
5656
 
    case SSE_RC_CHOP:
5657
 
        rnd_type = float_round_to_zero;
5658
 
        break;
5659
 
    }
5660
 
    set_float_rounding_mode(rnd_type, &env->sse_status);
5661
 
 
5662
 
    /* set denormals are zero */
5663
 
    set_flush_inputs_to_zero((env->mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status);
5664
 
 
5665
 
    /* set flush to zero */
5666
 
    set_flush_to_zero((env->mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
5667
 
}
5668
 
 
5669
 
void helper_ldmxcsr(uint32_t val)
5670
 
{
5671
 
    env->mxcsr = val;
5672
 
    update_sse_status();
5673
 
}
5674
 
 
5675
 
void helper_enter_mmx(void)
5676
 
{
5677
 
    env->fpstt = 0;
5678
 
    *(uint32_t *)(env->fptags) = 0;
5679
 
    *(uint32_t *)(env->fptags + 4) = 0;
5680
 
}
5681
 
 
5682
 
void helper_emms(void)
5683
 
{
5684
 
    /* set to empty state */
5685
 
    *(uint32_t *)(env->fptags) = 0x01010101;
5686
 
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5687
 
}
5688
 
 
5689
 
/* XXX: suppress */
5690
 
void helper_movq(void *d, void *s)
5691
 
{
5692
 
    *(uint64_t *)d = *(uint64_t *)s;
5693
 
}
5694
 
 
5695
 
#define SHIFT 0
5696
 
#include "ops_sse.h"
5697
 
 
5698
 
#define SHIFT 1
5699
 
#include "ops_sse.h"
5700
 
 
5701
 
#define SHIFT 0
5702
 
#include "helper_template.h"
5703
 
#undef SHIFT
5704
 
 
5705
 
#define SHIFT 1
5706
 
#include "helper_template.h"
5707
 
#undef SHIFT
5708
 
 
5709
 
#define SHIFT 2
5710
 
#include "helper_template.h"
5711
 
#undef SHIFT
5712
 
 
5713
 
#ifdef TARGET_X86_64
5714
 
 
5715
 
#define SHIFT 3
5716
 
#include "helper_template.h"
5717
 
#undef SHIFT
5718
 
 
5719
 
#endif
5720
 
 
5721
 
/* bit operations */
5722
 
target_ulong helper_bsf(target_ulong t0)
5723
 
{
5724
 
    int count;
5725
 
    target_ulong res;
5726
 
 
5727
 
    res = t0;
5728
 
    count = 0;
5729
 
    while ((res & 1) == 0) {
5730
 
        count++;
5731
 
        res >>= 1;
5732
 
    }
5733
 
    return count;
5734
 
}
5735
 
 
5736
 
target_ulong helper_lzcnt(target_ulong t0, int wordsize)
5737
 
{
5738
 
    int count;
5739
 
    target_ulong res, mask;
5740
 
 
5741
 
    if (wordsize > 0 && t0 == 0) {
5742
 
        return wordsize;
5743
 
    }
5744
 
    res = t0;
5745
 
    count = TARGET_LONG_BITS - 1;
5746
 
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5747
 
    while ((res & mask) == 0) {
5748
 
        count--;
5749
 
        res <<= 1;
5750
 
    }
5751
 
    if (wordsize > 0) {
5752
 
        return wordsize - 1 - count;
5753
 
    }
5754
 
    return count;
5755
 
}
5756
 
 
5757
 
target_ulong helper_bsr(target_ulong t0)
5758
 
{
5759
 
        return helper_lzcnt(t0, 0);
5760
 
}
5761
 
 
5762
 
static int compute_all_eflags(void)
5763
 
{
5764
 
    return CC_SRC;
5765
 
}
5766
 
 
5767
 
static int compute_c_eflags(void)
5768
 
{
5769
 
    return CC_SRC & CC_C;
5770
 
}
5771
 
 
5772
 
uint32_t helper_cc_compute_all(int op)
5773
 
{
5774
 
    switch (op) {
5775
 
    default: /* should never happen */ return 0;
5776
 
 
5777
 
    case CC_OP_EFLAGS: return compute_all_eflags();
5778
 
 
5779
 
    case CC_OP_MULB: return compute_all_mulb();
5780
 
    case CC_OP_MULW: return compute_all_mulw();
5781
 
    case CC_OP_MULL: return compute_all_mull();
5782
 
 
5783
 
    case CC_OP_ADDB: return compute_all_addb();
5784
 
    case CC_OP_ADDW: return compute_all_addw();
5785
 
    case CC_OP_ADDL: return compute_all_addl();
5786
 
 
5787
 
    case CC_OP_ADCB: return compute_all_adcb();
5788
 
    case CC_OP_ADCW: return compute_all_adcw();
5789
 
    case CC_OP_ADCL: return compute_all_adcl();
5790
 
 
5791
 
    case CC_OP_SUBB: return compute_all_subb();
5792
 
    case CC_OP_SUBW: return compute_all_subw();
5793
 
    case CC_OP_SUBL: return compute_all_subl();
5794
 
 
5795
 
    case CC_OP_SBBB: return compute_all_sbbb();
5796
 
    case CC_OP_SBBW: return compute_all_sbbw();
5797
 
    case CC_OP_SBBL: return compute_all_sbbl();
5798
 
 
5799
 
    case CC_OP_LOGICB: return compute_all_logicb();
5800
 
    case CC_OP_LOGICW: return compute_all_logicw();
5801
 
    case CC_OP_LOGICL: return compute_all_logicl();
5802
 
 
5803
 
    case CC_OP_INCB: return compute_all_incb();
5804
 
    case CC_OP_INCW: return compute_all_incw();
5805
 
    case CC_OP_INCL: return compute_all_incl();
5806
 
 
5807
 
    case CC_OP_DECB: return compute_all_decb();
5808
 
    case CC_OP_DECW: return compute_all_decw();
5809
 
    case CC_OP_DECL: return compute_all_decl();
5810
 
 
5811
 
    case CC_OP_SHLB: return compute_all_shlb();
5812
 
    case CC_OP_SHLW: return compute_all_shlw();
5813
 
    case CC_OP_SHLL: return compute_all_shll();
5814
 
 
5815
 
    case CC_OP_SARB: return compute_all_sarb();
5816
 
    case CC_OP_SARW: return compute_all_sarw();
5817
 
    case CC_OP_SARL: return compute_all_sarl();
5818
 
 
5819
 
#ifdef TARGET_X86_64
5820
 
    case CC_OP_MULQ: return compute_all_mulq();
5821
 
 
5822
 
    case CC_OP_ADDQ: return compute_all_addq();
5823
 
 
5824
 
    case CC_OP_ADCQ: return compute_all_adcq();
5825
 
 
5826
 
    case CC_OP_SUBQ: return compute_all_subq();
5827
 
 
5828
 
    case CC_OP_SBBQ: return compute_all_sbbq();
5829
 
 
5830
 
    case CC_OP_LOGICQ: return compute_all_logicq();
5831
 
 
5832
 
    case CC_OP_INCQ: return compute_all_incq();
5833
 
 
5834
 
    case CC_OP_DECQ: return compute_all_decq();
5835
 
 
5836
 
    case CC_OP_SHLQ: return compute_all_shlq();
5837
 
 
5838
 
    case CC_OP_SARQ: return compute_all_sarq();
5839
 
#endif
5840
 
    }
5841
 
}
5842
 
 
5843
 
uint32_t cpu_cc_compute_all(CPUState *env1, int op)
5844
 
{
5845
 
    CPUState *saved_env;
5846
 
    uint32_t ret;
5847
 
 
5848
 
    saved_env = env;
5849
 
    env = env1;
5850
 
    ret = helper_cc_compute_all(op);
5851
 
    env = saved_env;
5852
 
    return ret;
5853
 
}
5854
 
 
5855
 
uint32_t helper_cc_compute_c(int op)
5856
 
{
5857
 
    switch (op) {
5858
 
    default: /* should never happen */ return 0;
5859
 
 
5860
 
    case CC_OP_EFLAGS: return compute_c_eflags();
5861
 
 
5862
 
    case CC_OP_MULB: return compute_c_mull();
5863
 
    case CC_OP_MULW: return compute_c_mull();
5864
 
    case CC_OP_MULL: return compute_c_mull();
5865
 
 
5866
 
    case CC_OP_ADDB: return compute_c_addb();
5867
 
    case CC_OP_ADDW: return compute_c_addw();
5868
 
    case CC_OP_ADDL: return compute_c_addl();
5869
 
 
5870
 
    case CC_OP_ADCB: return compute_c_adcb();
5871
 
    case CC_OP_ADCW: return compute_c_adcw();
5872
 
    case CC_OP_ADCL: return compute_c_adcl();
5873
 
 
5874
 
    case CC_OP_SUBB: return compute_c_subb();
5875
 
    case CC_OP_SUBW: return compute_c_subw();
5876
 
    case CC_OP_SUBL: return compute_c_subl();
5877
 
 
5878
 
    case CC_OP_SBBB: return compute_c_sbbb();
5879
 
    case CC_OP_SBBW: return compute_c_sbbw();
5880
 
    case CC_OP_SBBL: return compute_c_sbbl();
5881
 
 
5882
 
    case CC_OP_LOGICB: return compute_c_logicb();
5883
 
    case CC_OP_LOGICW: return compute_c_logicw();
5884
 
    case CC_OP_LOGICL: return compute_c_logicl();
5885
 
 
5886
 
    case CC_OP_INCB: return compute_c_incl();
5887
 
    case CC_OP_INCW: return compute_c_incl();
5888
 
    case CC_OP_INCL: return compute_c_incl();
5889
 
 
5890
 
    case CC_OP_DECB: return compute_c_incl();
5891
 
    case CC_OP_DECW: return compute_c_incl();
5892
 
    case CC_OP_DECL: return compute_c_incl();
5893
 
 
5894
 
    case CC_OP_SHLB: return compute_c_shlb();
5895
 
    case CC_OP_SHLW: return compute_c_shlw();
5896
 
    case CC_OP_SHLL: return compute_c_shll();
5897
 
 
5898
 
    case CC_OP_SARB: return compute_c_sarl();
5899
 
    case CC_OP_SARW: return compute_c_sarl();
5900
 
    case CC_OP_SARL: return compute_c_sarl();
5901
 
 
5902
 
#ifdef TARGET_X86_64
5903
 
    case CC_OP_MULQ: return compute_c_mull();
5904
 
 
5905
 
    case CC_OP_ADDQ: return compute_c_addq();
5906
 
 
5907
 
    case CC_OP_ADCQ: return compute_c_adcq();
5908
 
 
5909
 
    case CC_OP_SUBQ: return compute_c_subq();
5910
 
 
5911
 
    case CC_OP_SBBQ: return compute_c_sbbq();
5912
 
 
5913
 
    case CC_OP_LOGICQ: return compute_c_logicq();
5914
 
 
5915
 
    case CC_OP_INCQ: return compute_c_incl();
5916
 
 
5917
 
    case CC_OP_DECQ: return compute_c_incl();
5918
 
 
5919
 
    case CC_OP_SHLQ: return compute_c_shlq();
5920
 
 
5921
 
    case CC_OP_SARQ: return compute_c_sarl();
5922
 
#endif
5923
 
    }
5924
 
}