Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 997ff0d9

History | View | Annotate | Download (146.3 kB)

1 eaa728ee bellard
/*
2 eaa728ee bellard
 *  i386 helpers
3 eaa728ee bellard
 *
4 eaa728ee bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 eaa728ee bellard
 *
6 eaa728ee bellard
 * This library is free software; you can redistribute it and/or
7 eaa728ee bellard
 * modify it under the terms of the GNU Lesser General Public
8 eaa728ee bellard
 * License as published by the Free Software Foundation; either
9 eaa728ee bellard
 * version 2 of the License, or (at your option) any later version.
10 eaa728ee bellard
 *
11 eaa728ee bellard
 * This library is distributed in the hope that it will be useful,
12 eaa728ee bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 eaa728ee bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 eaa728ee bellard
 * Lesser General Public License for more details.
15 eaa728ee bellard
 *
16 eaa728ee bellard
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 eaa728ee bellard
 */
19 83dae095 Paolo Bonzini
20 3e457172 Blue Swirl
#include "cpu.h"
21 3e457172 Blue Swirl
#include "dyngen-exec.h"
22 eaa728ee bellard
#include "host-utils.h"
23 35bed8ee Paul Brook
#include "ioport.h"
24 3e457172 Blue Swirl
#include "qemu-log.h"
25 3e457172 Blue Swirl
#include "cpu-defs.h"
26 3e457172 Blue Swirl
#include "helper.h"
27 eaa728ee bellard
28 3e457172 Blue Swirl
#if !defined(CONFIG_USER_ONLY)
29 3e457172 Blue Swirl
#include "softmmu_exec.h"
30 3e457172 Blue Swirl
#endif /* !defined(CONFIG_USER_ONLY) */
31 eaa728ee bellard
32 3e457172 Blue Swirl
//#define DEBUG_PCALL
33 20054ef0 Blue Swirl
//#define DEBUG_MULDIV
34 d12d51d5 aliguori
35 d12d51d5 aliguori
#ifdef DEBUG_PCALL
36 20054ef0 Blue Swirl
# define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
37 20054ef0 Blue Swirl
# define LOG_PCALL_STATE(env)                                  \
38 20054ef0 Blue Swirl
    log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
39 d12d51d5 aliguori
#else
40 20054ef0 Blue Swirl
# define LOG_PCALL(...) do { } while (0)
41 20054ef0 Blue Swirl
# define LOG_PCALL_STATE(env) do { } while (0)
42 d12d51d5 aliguori
#endif
43 d12d51d5 aliguori
44 3e457172 Blue Swirl
/* n must be a constant to be efficient */
45 3e457172 Blue Swirl
static inline target_long lshift(target_long x, int n)
46 3e457172 Blue Swirl
{
47 3e457172 Blue Swirl
    if (n >= 0) {
48 3e457172 Blue Swirl
        return x << n;
49 3e457172 Blue Swirl
    } else {
50 3e457172 Blue Swirl
        return x >> (-n);
51 3e457172 Blue Swirl
    }
52 3e457172 Blue Swirl
}
53 3e457172 Blue Swirl
54 997ff0d9 Blue Swirl
static inline uint32_t cpu_compute_eflags(CPUX86State *env)
55 3e457172 Blue Swirl
{
56 997ff0d9 Blue Swirl
    return env->eflags | cpu_cc_compute_all(env, CC_OP) | (DF & DF_MASK);
57 3e457172 Blue Swirl
}
58 3e457172 Blue Swirl
59 3e457172 Blue Swirl
/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
60 997ff0d9 Blue Swirl
static inline void cpu_load_eflags(CPUX86State *env, int eflags,
61 997ff0d9 Blue Swirl
                                   int update_mask)
62 3e457172 Blue Swirl
{
63 3e457172 Blue Swirl
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
64 3e457172 Blue Swirl
    DF = 1 - (2 * ((eflags >> 10) & 1));
65 3e457172 Blue Swirl
    env->eflags = (env->eflags & ~update_mask) |
66 3e457172 Blue Swirl
        (eflags & update_mask) | 0x2;
67 3e457172 Blue Swirl
}
68 3e457172 Blue Swirl
69 3e457172 Blue Swirl
/* load efer and update the corresponding hflags. XXX: do consistency
70 20054ef0 Blue Swirl
   checks with cpuid bits? */
71 317ac620 Andreas Färber
static inline void cpu_load_efer(CPUX86State *env, uint64_t val)
72 3e457172 Blue Swirl
{
73 3e457172 Blue Swirl
    env->efer = val;
74 3e457172 Blue Swirl
    env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
75 3e457172 Blue Swirl
    if (env->efer & MSR_EFER_LMA) {
76 3e457172 Blue Swirl
        env->hflags |= HF_LMA_MASK;
77 3e457172 Blue Swirl
    }
78 3e457172 Blue Swirl
    if (env->efer & MSR_EFER_SVME) {
79 3e457172 Blue Swirl
        env->hflags |= HF_SVME_MASK;
80 3e457172 Blue Swirl
    }
81 3e457172 Blue Swirl
}
82 d12d51d5 aliguori
83 d9957a8b blueswir1
static const uint8_t parity_table[256] = {
84 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
85 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
86 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
87 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
88 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
89 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
90 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
91 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
92 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
93 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
94 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
95 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
96 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
97 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
98 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
99 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
100 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
101 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
102 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
103 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
104 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
105 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
106 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
107 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
108 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
109 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
110 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
111 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
112 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
113 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
114 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
115 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
116 eaa728ee bellard
};
117 eaa728ee bellard
118 eaa728ee bellard
/* modulo 17 table */
119 d9957a8b blueswir1
static const uint8_t rclw_table[32] = {
120 eaa728ee bellard
    0, 1, 2, 3, 4, 5, 6, 7,
121 20054ef0 Blue Swirl
    8, 9, 10, 11, 12, 13, 14, 15,
122 20054ef0 Blue Swirl
    16, 0, 1, 2, 3, 4, 5, 6,
123 20054ef0 Blue Swirl
    7, 8, 9, 10, 11, 12, 13, 14,
124 eaa728ee bellard
};
125 eaa728ee bellard
126 eaa728ee bellard
/* modulo 9 table */
127 d9957a8b blueswir1
static const uint8_t rclb_table[32] = {
128 eaa728ee bellard
    0, 1, 2, 3, 4, 5, 6, 7,
129 eaa728ee bellard
    8, 0, 1, 2, 3, 4, 5, 6,
130 eaa728ee bellard
    7, 8, 0, 1, 2, 3, 4, 5,
131 eaa728ee bellard
    6, 7, 8, 0, 1, 2, 3, 4,
132 eaa728ee bellard
};
133 eaa728ee bellard
134 eaa728ee bellard
/* broken thread support */
135 eaa728ee bellard
136 c227f099 Anthony Liguori
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
137 eaa728ee bellard
138 eaa728ee bellard
void helper_lock(void)
139 eaa728ee bellard
{
140 eaa728ee bellard
    spin_lock(&global_cpu_lock);
141 eaa728ee bellard
}
142 eaa728ee bellard
143 eaa728ee bellard
void helper_unlock(void)
144 eaa728ee bellard
{
145 eaa728ee bellard
    spin_unlock(&global_cpu_lock);
146 eaa728ee bellard
}
147 eaa728ee bellard
148 eaa728ee bellard
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
149 eaa728ee bellard
{
150 997ff0d9 Blue Swirl
    cpu_load_eflags(env, t0, update_mask);
151 eaa728ee bellard
}
152 eaa728ee bellard
153 eaa728ee bellard
target_ulong helper_read_eflags(void)
154 eaa728ee bellard
{
155 eaa728ee bellard
    uint32_t eflags;
156 20054ef0 Blue Swirl
157 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
158 eaa728ee bellard
    eflags |= (DF & DF_MASK);
159 eaa728ee bellard
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
160 eaa728ee bellard
    return eflags;
161 eaa728ee bellard
}
162 eaa728ee bellard
163 eaa728ee bellard
/* return non zero if error */
164 eaa728ee bellard
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
165 eaa728ee bellard
                               int selector)
166 eaa728ee bellard
{
167 eaa728ee bellard
    SegmentCache *dt;
168 eaa728ee bellard
    int index;
169 eaa728ee bellard
    target_ulong ptr;
170 eaa728ee bellard
171 20054ef0 Blue Swirl
    if (selector & 0x4) {
172 eaa728ee bellard
        dt = &env->ldt;
173 20054ef0 Blue Swirl
    } else {
174 eaa728ee bellard
        dt = &env->gdt;
175 20054ef0 Blue Swirl
    }
176 eaa728ee bellard
    index = selector & ~7;
177 20054ef0 Blue Swirl
    if ((index + 7) > dt->limit) {
178 eaa728ee bellard
        return -1;
179 20054ef0 Blue Swirl
    }
180 eaa728ee bellard
    ptr = dt->base + index;
181 eaa728ee bellard
    *e1_ptr = ldl_kernel(ptr);
182 eaa728ee bellard
    *e2_ptr = ldl_kernel(ptr + 4);
183 eaa728ee bellard
    return 0;
184 eaa728ee bellard
}
185 eaa728ee bellard
186 eaa728ee bellard
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
187 eaa728ee bellard
{
188 eaa728ee bellard
    unsigned int limit;
189 20054ef0 Blue Swirl
190 eaa728ee bellard
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
191 20054ef0 Blue Swirl
    if (e2 & DESC_G_MASK) {
192 eaa728ee bellard
        limit = (limit << 12) | 0xfff;
193 20054ef0 Blue Swirl
    }
194 eaa728ee bellard
    return limit;
195 eaa728ee bellard
}
196 eaa728ee bellard
197 eaa728ee bellard
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
198 eaa728ee bellard
{
199 20054ef0 Blue Swirl
    return (e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000);
200 eaa728ee bellard
}
201 eaa728ee bellard
202 20054ef0 Blue Swirl
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1,
203 20054ef0 Blue Swirl
                                         uint32_t e2)
204 eaa728ee bellard
{
205 eaa728ee bellard
    sc->base = get_seg_base(e1, e2);
206 eaa728ee bellard
    sc->limit = get_seg_limit(e1, e2);
207 eaa728ee bellard
    sc->flags = e2;
208 eaa728ee bellard
}
209 eaa728ee bellard
210 eaa728ee bellard
/* init the segment cache in vm86 mode. */
211 eaa728ee bellard
static inline void load_seg_vm(int seg, int selector)
212 eaa728ee bellard
{
213 eaa728ee bellard
    selector &= 0xffff;
214 eaa728ee bellard
    cpu_x86_load_seg_cache(env, seg, selector,
215 eaa728ee bellard
                           (selector << 4), 0xffff, 0);
216 eaa728ee bellard
}
217 eaa728ee bellard
218 eaa728ee bellard
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
219 eaa728ee bellard
                                       uint32_t *esp_ptr, int dpl)
220 eaa728ee bellard
{
221 eaa728ee bellard
    int type, index, shift;
222 eaa728ee bellard
223 eaa728ee bellard
#if 0
224 eaa728ee bellard
    {
225 eaa728ee bellard
        int i;
226 eaa728ee bellard
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
227 20054ef0 Blue Swirl
        for (i = 0; i < env->tr.limit; i++) {
228 eaa728ee bellard
            printf("%02x ", env->tr.base[i]);
229 20054ef0 Blue Swirl
            if ((i & 7) == 7) {
230 20054ef0 Blue Swirl
                printf("\n");
231 20054ef0 Blue Swirl
            }
232 eaa728ee bellard
        }
233 eaa728ee bellard
        printf("\n");
234 eaa728ee bellard
    }
235 eaa728ee bellard
#endif
236 eaa728ee bellard
237 20054ef0 Blue Swirl
    if (!(env->tr.flags & DESC_P_MASK)) {
238 eaa728ee bellard
        cpu_abort(env, "invalid tss");
239 20054ef0 Blue Swirl
    }
240 eaa728ee bellard
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
241 20054ef0 Blue Swirl
    if ((type & 7) != 1) {
242 eaa728ee bellard
        cpu_abort(env, "invalid tss type");
243 20054ef0 Blue Swirl
    }
244 eaa728ee bellard
    shift = type >> 3;
245 eaa728ee bellard
    index = (dpl * 4 + 2) << shift;
246 20054ef0 Blue Swirl
    if (index + (4 << shift) - 1 > env->tr.limit) {
247 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc);
248 20054ef0 Blue Swirl
    }
249 eaa728ee bellard
    if (shift == 0) {
250 eaa728ee bellard
        *esp_ptr = lduw_kernel(env->tr.base + index);
251 eaa728ee bellard
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
252 eaa728ee bellard
    } else {
253 eaa728ee bellard
        *esp_ptr = ldl_kernel(env->tr.base + index);
254 eaa728ee bellard
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
255 eaa728ee bellard
    }
256 eaa728ee bellard
}
257 eaa728ee bellard
258 eaa728ee bellard
/* XXX: merge with load_seg() */
259 eaa728ee bellard
static void tss_load_seg(int seg_reg, int selector)
260 eaa728ee bellard
{
261 eaa728ee bellard
    uint32_t e1, e2;
262 eaa728ee bellard
    int rpl, dpl, cpl;
263 eaa728ee bellard
264 eaa728ee bellard
    if ((selector & 0xfffc) != 0) {
265 20054ef0 Blue Swirl
        if (load_segment(&e1, &e2, selector) != 0) {
266 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
267 20054ef0 Blue Swirl
        }
268 20054ef0 Blue Swirl
        if (!(e2 & DESC_S_MASK)) {
269 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
270 20054ef0 Blue Swirl
        }
271 eaa728ee bellard
        rpl = selector & 3;
272 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
273 eaa728ee bellard
        cpl = env->hflags & HF_CPL_MASK;
274 eaa728ee bellard
        if (seg_reg == R_CS) {
275 20054ef0 Blue Swirl
            if (!(e2 & DESC_CS_MASK)) {
276 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
277 20054ef0 Blue Swirl
            }
278 20054ef0 Blue Swirl
            /* XXX: is it correct? */
279 20054ef0 Blue Swirl
            if (dpl != rpl) {
280 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
281 20054ef0 Blue Swirl
            }
282 20054ef0 Blue Swirl
            if ((e2 & DESC_C_MASK) && dpl > rpl) {
283 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
284 20054ef0 Blue Swirl
            }
285 eaa728ee bellard
        } else if (seg_reg == R_SS) {
286 eaa728ee bellard
            /* SS must be writable data */
287 20054ef0 Blue Swirl
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) {
288 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
289 20054ef0 Blue Swirl
            }
290 20054ef0 Blue Swirl
            if (dpl != cpl || dpl != rpl) {
291 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
292 20054ef0 Blue Swirl
            }
293 eaa728ee bellard
        } else {
294 eaa728ee bellard
            /* not readable code */
295 20054ef0 Blue Swirl
            if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK)) {
296 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
297 20054ef0 Blue Swirl
            }
298 eaa728ee bellard
            /* if data or non conforming code, checks the rights */
299 eaa728ee bellard
            if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
300 20054ef0 Blue Swirl
                if (dpl < cpl || dpl < rpl) {
301 77b2bc2c Blue Swirl
                    raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
302 20054ef0 Blue Swirl
                }
303 eaa728ee bellard
            }
304 eaa728ee bellard
        }
305 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
306 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
307 20054ef0 Blue Swirl
        }
308 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector,
309 20054ef0 Blue Swirl
                               get_seg_base(e1, e2),
310 20054ef0 Blue Swirl
                               get_seg_limit(e1, e2),
311 20054ef0 Blue Swirl
                               e2);
312 eaa728ee bellard
    } else {
313 20054ef0 Blue Swirl
        if (seg_reg == R_SS || seg_reg == R_CS) {
314 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
315 20054ef0 Blue Swirl
        }
316 eaa728ee bellard
    }
317 eaa728ee bellard
}
318 eaa728ee bellard
319 eaa728ee bellard
#define SWITCH_TSS_JMP  0
320 eaa728ee bellard
#define SWITCH_TSS_IRET 1
321 eaa728ee bellard
#define SWITCH_TSS_CALL 2
322 eaa728ee bellard
323 eaa728ee bellard
/* XXX: restore CPU state in registers (PowerPC case) */
324 eaa728ee bellard
static void switch_tss(int tss_selector,
325 eaa728ee bellard
                       uint32_t e1, uint32_t e2, int source,
326 eaa728ee bellard
                       uint32_t next_eip)
327 eaa728ee bellard
{
328 eaa728ee bellard
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
329 eaa728ee bellard
    target_ulong tss_base;
330 eaa728ee bellard
    uint32_t new_regs[8], new_segs[6];
331 eaa728ee bellard
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
332 eaa728ee bellard
    uint32_t old_eflags, eflags_mask;
333 eaa728ee bellard
    SegmentCache *dt;
334 eaa728ee bellard
    int index;
335 eaa728ee bellard
    target_ulong ptr;
336 eaa728ee bellard
337 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
338 20054ef0 Blue Swirl
    LOG_PCALL("switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type,
339 20054ef0 Blue Swirl
              source);
340 eaa728ee bellard
341 eaa728ee bellard
    /* if task gate, we read the TSS segment and we load it */
342 eaa728ee bellard
    if (type == 5) {
343 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
344 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, tss_selector & 0xfffc);
345 20054ef0 Blue Swirl
        }
346 eaa728ee bellard
        tss_selector = e1 >> 16;
347 20054ef0 Blue Swirl
        if (tss_selector & 4) {
348 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc);
349 20054ef0 Blue Swirl
        }
350 20054ef0 Blue Swirl
        if (load_segment(&e1, &e2, tss_selector) != 0) {
351 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, tss_selector & 0xfffc);
352 20054ef0 Blue Swirl
        }
353 20054ef0 Blue Swirl
        if (e2 & DESC_S_MASK) {
354 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, tss_selector & 0xfffc);
355 20054ef0 Blue Swirl
        }
356 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
357 20054ef0 Blue Swirl
        if ((type & 7) != 1) {
358 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, tss_selector & 0xfffc);
359 20054ef0 Blue Swirl
        }
360 eaa728ee bellard
    }
361 eaa728ee bellard
362 20054ef0 Blue Swirl
    if (!(e2 & DESC_P_MASK)) {
363 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0B_NOSEG, tss_selector & 0xfffc);
364 20054ef0 Blue Swirl
    }
365 eaa728ee bellard
366 20054ef0 Blue Swirl
    if (type & 8) {
367 eaa728ee bellard
        tss_limit_max = 103;
368 20054ef0 Blue Swirl
    } else {
369 eaa728ee bellard
        tss_limit_max = 43;
370 20054ef0 Blue Swirl
    }
371 eaa728ee bellard
    tss_limit = get_seg_limit(e1, e2);
372 eaa728ee bellard
    tss_base = get_seg_base(e1, e2);
373 eaa728ee bellard
    if ((tss_selector & 4) != 0 ||
374 20054ef0 Blue Swirl
        tss_limit < tss_limit_max) {
375 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc);
376 20054ef0 Blue Swirl
    }
377 eaa728ee bellard
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
378 20054ef0 Blue Swirl
    if (old_type & 8) {
379 eaa728ee bellard
        old_tss_limit_max = 103;
380 20054ef0 Blue Swirl
    } else {
381 eaa728ee bellard
        old_tss_limit_max = 43;
382 20054ef0 Blue Swirl
    }
383 eaa728ee bellard
384 eaa728ee bellard
    /* read all the registers from the new TSS */
385 eaa728ee bellard
    if (type & 8) {
386 eaa728ee bellard
        /* 32 bit */
387 eaa728ee bellard
        new_cr3 = ldl_kernel(tss_base + 0x1c);
388 eaa728ee bellard
        new_eip = ldl_kernel(tss_base + 0x20);
389 eaa728ee bellard
        new_eflags = ldl_kernel(tss_base + 0x24);
390 20054ef0 Blue Swirl
        for (i = 0; i < 8; i++) {
391 eaa728ee bellard
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
392 20054ef0 Blue Swirl
        }
393 20054ef0 Blue Swirl
        for (i = 0; i < 6; i++) {
394 eaa728ee bellard
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
395 20054ef0 Blue Swirl
        }
396 eaa728ee bellard
        new_ldt = lduw_kernel(tss_base + 0x60);
397 eaa728ee bellard
        new_trap = ldl_kernel(tss_base + 0x64);
398 eaa728ee bellard
    } else {
399 eaa728ee bellard
        /* 16 bit */
400 eaa728ee bellard
        new_cr3 = 0;
401 eaa728ee bellard
        new_eip = lduw_kernel(tss_base + 0x0e);
402 eaa728ee bellard
        new_eflags = lduw_kernel(tss_base + 0x10);
403 20054ef0 Blue Swirl
        for (i = 0; i < 8; i++) {
404 eaa728ee bellard
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
405 20054ef0 Blue Swirl
        }
406 20054ef0 Blue Swirl
        for (i = 0; i < 4; i++) {
407 eaa728ee bellard
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
408 20054ef0 Blue Swirl
        }
409 eaa728ee bellard
        new_ldt = lduw_kernel(tss_base + 0x2a);
410 eaa728ee bellard
        new_segs[R_FS] = 0;
411 eaa728ee bellard
        new_segs[R_GS] = 0;
412 eaa728ee bellard
        new_trap = 0;
413 eaa728ee bellard
    }
414 4581cbcd Blue Swirl
    /* XXX: avoid a compiler warning, see
415 4581cbcd Blue Swirl
     http://support.amd.com/us/Processor_TechDocs/24593.pdf
416 4581cbcd Blue Swirl
     chapters 12.2.5 and 13.2.4 on how to implement TSS Trap bit */
417 4581cbcd Blue Swirl
    (void)new_trap;
418 eaa728ee bellard
419 eaa728ee bellard
    /* NOTE: we must avoid memory exceptions during the task switch,
420 eaa728ee bellard
       so we make dummy accesses before */
421 eaa728ee bellard
    /* XXX: it can still fail in some cases, so a bigger hack is
422 eaa728ee bellard
       necessary to valid the TLB after having done the accesses */
423 eaa728ee bellard
424 eaa728ee bellard
    v1 = ldub_kernel(env->tr.base);
425 eaa728ee bellard
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
426 eaa728ee bellard
    stb_kernel(env->tr.base, v1);
427 eaa728ee bellard
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
428 eaa728ee bellard
429 eaa728ee bellard
    /* clear busy bit (it is restartable) */
430 eaa728ee bellard
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
431 eaa728ee bellard
        target_ulong ptr;
432 eaa728ee bellard
        uint32_t e2;
433 20054ef0 Blue Swirl
434 eaa728ee bellard
        ptr = env->gdt.base + (env->tr.selector & ~7);
435 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
436 eaa728ee bellard
        e2 &= ~DESC_TSS_BUSY_MASK;
437 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
438 eaa728ee bellard
    }
439 997ff0d9 Blue Swirl
    old_eflags = cpu_compute_eflags(env);
440 20054ef0 Blue Swirl
    if (source == SWITCH_TSS_IRET) {
441 eaa728ee bellard
        old_eflags &= ~NT_MASK;
442 20054ef0 Blue Swirl
    }
443 eaa728ee bellard
444 eaa728ee bellard
    /* save the current state in the old TSS */
445 eaa728ee bellard
    if (type & 8) {
446 eaa728ee bellard
        /* 32 bit */
447 eaa728ee bellard
        stl_kernel(env->tr.base + 0x20, next_eip);
448 eaa728ee bellard
        stl_kernel(env->tr.base + 0x24, old_eflags);
449 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
450 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
451 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
452 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
453 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
454 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
455 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
456 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
457 20054ef0 Blue Swirl
        for (i = 0; i < 6; i++) {
458 eaa728ee bellard
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
459 20054ef0 Blue Swirl
        }
460 eaa728ee bellard
    } else {
461 eaa728ee bellard
        /* 16 bit */
462 eaa728ee bellard
        stw_kernel(env->tr.base + 0x0e, next_eip);
463 eaa728ee bellard
        stw_kernel(env->tr.base + 0x10, old_eflags);
464 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
465 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
466 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
467 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
468 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
469 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
470 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
471 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
472 20054ef0 Blue Swirl
        for (i = 0; i < 4; i++) {
473 eaa728ee bellard
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
474 20054ef0 Blue Swirl
        }
475 eaa728ee bellard
    }
476 eaa728ee bellard
477 eaa728ee bellard
    /* now if an exception occurs, it will occurs in the next task
478 eaa728ee bellard
       context */
479 eaa728ee bellard
480 eaa728ee bellard
    if (source == SWITCH_TSS_CALL) {
481 eaa728ee bellard
        stw_kernel(tss_base, env->tr.selector);
482 eaa728ee bellard
        new_eflags |= NT_MASK;
483 eaa728ee bellard
    }
484 eaa728ee bellard
485 eaa728ee bellard
    /* set busy bit */
486 eaa728ee bellard
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
487 eaa728ee bellard
        target_ulong ptr;
488 eaa728ee bellard
        uint32_t e2;
489 20054ef0 Blue Swirl
490 eaa728ee bellard
        ptr = env->gdt.base + (tss_selector & ~7);
491 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
492 eaa728ee bellard
        e2 |= DESC_TSS_BUSY_MASK;
493 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
494 eaa728ee bellard
    }
495 eaa728ee bellard
496 eaa728ee bellard
    /* set the new CPU state */
497 eaa728ee bellard
    /* from this point, any exception which occurs can give problems */
498 eaa728ee bellard
    env->cr[0] |= CR0_TS_MASK;
499 eaa728ee bellard
    env->hflags |= HF_TS_MASK;
500 eaa728ee bellard
    env->tr.selector = tss_selector;
501 eaa728ee bellard
    env->tr.base = tss_base;
502 eaa728ee bellard
    env->tr.limit = tss_limit;
503 eaa728ee bellard
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
504 eaa728ee bellard
505 eaa728ee bellard
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
506 eaa728ee bellard
        cpu_x86_update_cr3(env, new_cr3);
507 eaa728ee bellard
    }
508 eaa728ee bellard
509 eaa728ee bellard
    /* load all registers without an exception, then reload them with
510 eaa728ee bellard
       possible exception */
511 eaa728ee bellard
    env->eip = new_eip;
512 eaa728ee bellard
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
513 eaa728ee bellard
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
514 20054ef0 Blue Swirl
    if (!(type & 8)) {
515 eaa728ee bellard
        eflags_mask &= 0xffff;
516 20054ef0 Blue Swirl
    }
517 997ff0d9 Blue Swirl
    cpu_load_eflags(env, new_eflags, eflags_mask);
518 20054ef0 Blue Swirl
    /* XXX: what to do in 16 bit case? */
519 eaa728ee bellard
    EAX = new_regs[0];
520 eaa728ee bellard
    ECX = new_regs[1];
521 eaa728ee bellard
    EDX = new_regs[2];
522 eaa728ee bellard
    EBX = new_regs[3];
523 eaa728ee bellard
    ESP = new_regs[4];
524 eaa728ee bellard
    EBP = new_regs[5];
525 eaa728ee bellard
    ESI = new_regs[6];
526 eaa728ee bellard
    EDI = new_regs[7];
527 eaa728ee bellard
    if (new_eflags & VM_MASK) {
528 20054ef0 Blue Swirl
        for (i = 0; i < 6; i++) {
529 eaa728ee bellard
            load_seg_vm(i, new_segs[i]);
530 20054ef0 Blue Swirl
        }
531 eaa728ee bellard
        /* in vm86, CPL is always 3 */
532 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
533 eaa728ee bellard
    } else {
534 eaa728ee bellard
        /* CPL is set the RPL of CS */
535 eaa728ee bellard
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
536 eaa728ee bellard
        /* first just selectors as the rest may trigger exceptions */
537 20054ef0 Blue Swirl
        for (i = 0; i < 6; i++) {
538 eaa728ee bellard
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
539 20054ef0 Blue Swirl
        }
540 eaa728ee bellard
    }
541 eaa728ee bellard
542 eaa728ee bellard
    env->ldt.selector = new_ldt & ~4;
543 eaa728ee bellard
    env->ldt.base = 0;
544 eaa728ee bellard
    env->ldt.limit = 0;
545 eaa728ee bellard
    env->ldt.flags = 0;
546 eaa728ee bellard
547 eaa728ee bellard
    /* load the LDT */
548 20054ef0 Blue Swirl
    if (new_ldt & 4) {
549 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc);
550 20054ef0 Blue Swirl
    }
551 eaa728ee bellard
552 eaa728ee bellard
    if ((new_ldt & 0xfffc) != 0) {
553 eaa728ee bellard
        dt = &env->gdt;
554 eaa728ee bellard
        index = new_ldt & ~7;
555 20054ef0 Blue Swirl
        if ((index + 7) > dt->limit) {
556 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc);
557 20054ef0 Blue Swirl
        }
558 eaa728ee bellard
        ptr = dt->base + index;
559 eaa728ee bellard
        e1 = ldl_kernel(ptr);
560 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
561 20054ef0 Blue Swirl
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) {
562 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc);
563 20054ef0 Blue Swirl
        }
564 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
565 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, new_ldt & 0xfffc);
566 20054ef0 Blue Swirl
        }
567 eaa728ee bellard
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
568 eaa728ee bellard
    }
569 eaa728ee bellard
570 eaa728ee bellard
    /* load the segments */
571 eaa728ee bellard
    if (!(new_eflags & VM_MASK)) {
572 eaa728ee bellard
        tss_load_seg(R_CS, new_segs[R_CS]);
573 eaa728ee bellard
        tss_load_seg(R_SS, new_segs[R_SS]);
574 eaa728ee bellard
        tss_load_seg(R_ES, new_segs[R_ES]);
575 eaa728ee bellard
        tss_load_seg(R_DS, new_segs[R_DS]);
576 eaa728ee bellard
        tss_load_seg(R_FS, new_segs[R_FS]);
577 eaa728ee bellard
        tss_load_seg(R_GS, new_segs[R_GS]);
578 eaa728ee bellard
    }
579 eaa728ee bellard
580 eaa728ee bellard
    /* check that EIP is in the CS segment limits */
581 eaa728ee bellard
    if (new_eip > env->segs[R_CS].limit) {
582 20054ef0 Blue Swirl
        /* XXX: different exception if CALL? */
583 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
584 eaa728ee bellard
    }
585 01df040b aliguori
586 01df040b aliguori
#ifndef CONFIG_USER_ONLY
587 01df040b aliguori
    /* reset local breakpoints */
588 01df040b aliguori
    if (env->dr[7] & 0x55) {
589 01df040b aliguori
        for (i = 0; i < 4; i++) {
590 20054ef0 Blue Swirl
            if (hw_breakpoint_enabled(env->dr[7], i) == 0x1) {
591 01df040b aliguori
                hw_breakpoint_remove(env, i);
592 20054ef0 Blue Swirl
            }
593 01df040b aliguori
        }
594 01df040b aliguori
        env->dr[7] &= ~0x55;
595 01df040b aliguori
    }
596 01df040b aliguori
#endif
597 eaa728ee bellard
}
598 eaa728ee bellard
599 eaa728ee bellard
/* check if Port I/O is allowed in TSS */
600 eaa728ee bellard
static inline void check_io(int addr, int size)
601 eaa728ee bellard
{
602 eaa728ee bellard
    int io_offset, val, mask;
603 eaa728ee bellard
604 eaa728ee bellard
    /* TSS must be a valid 32 bit one */
605 eaa728ee bellard
    if (!(env->tr.flags & DESC_P_MASK) ||
606 eaa728ee bellard
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
607 20054ef0 Blue Swirl
        env->tr.limit < 103) {
608 eaa728ee bellard
        goto fail;
609 20054ef0 Blue Swirl
    }
610 eaa728ee bellard
    io_offset = lduw_kernel(env->tr.base + 0x66);
611 eaa728ee bellard
    io_offset += (addr >> 3);
612 eaa728ee bellard
    /* Note: the check needs two bytes */
613 20054ef0 Blue Swirl
    if ((io_offset + 1) > env->tr.limit) {
614 eaa728ee bellard
        goto fail;
615 20054ef0 Blue Swirl
    }
616 eaa728ee bellard
    val = lduw_kernel(env->tr.base + io_offset);
617 eaa728ee bellard
    val >>= (addr & 7);
618 eaa728ee bellard
    mask = (1 << size) - 1;
619 eaa728ee bellard
    /* all bits must be zero to allow the I/O */
620 eaa728ee bellard
    if ((val & mask) != 0) {
621 eaa728ee bellard
    fail:
622 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
623 eaa728ee bellard
    }
624 eaa728ee bellard
}
625 eaa728ee bellard
626 eaa728ee bellard
void helper_check_iob(uint32_t t0)
627 eaa728ee bellard
{
628 eaa728ee bellard
    check_io(t0, 1);
629 eaa728ee bellard
}
630 eaa728ee bellard
631 eaa728ee bellard
void helper_check_iow(uint32_t t0)
632 eaa728ee bellard
{
633 eaa728ee bellard
    check_io(t0, 2);
634 eaa728ee bellard
}
635 eaa728ee bellard
636 eaa728ee bellard
void helper_check_iol(uint32_t t0)
637 eaa728ee bellard
{
638 eaa728ee bellard
    check_io(t0, 4);
639 eaa728ee bellard
}
640 eaa728ee bellard
641 eaa728ee bellard
void helper_outb(uint32_t port, uint32_t data)
642 eaa728ee bellard
{
643 afcea8cb Blue Swirl
    cpu_outb(port, data & 0xff);
644 eaa728ee bellard
}
645 eaa728ee bellard
646 eaa728ee bellard
target_ulong helper_inb(uint32_t port)
647 eaa728ee bellard
{
648 afcea8cb Blue Swirl
    return cpu_inb(port);
649 eaa728ee bellard
}
650 eaa728ee bellard
651 eaa728ee bellard
void helper_outw(uint32_t port, uint32_t data)
652 eaa728ee bellard
{
653 afcea8cb Blue Swirl
    cpu_outw(port, data & 0xffff);
654 eaa728ee bellard
}
655 eaa728ee bellard
656 eaa728ee bellard
target_ulong helper_inw(uint32_t port)
657 eaa728ee bellard
{
658 afcea8cb Blue Swirl
    return cpu_inw(port);
659 eaa728ee bellard
}
660 eaa728ee bellard
661 eaa728ee bellard
void helper_outl(uint32_t port, uint32_t data)
662 eaa728ee bellard
{
663 afcea8cb Blue Swirl
    cpu_outl(port, data);
664 eaa728ee bellard
}
665 eaa728ee bellard
666 eaa728ee bellard
target_ulong helper_inl(uint32_t port)
667 eaa728ee bellard
{
668 afcea8cb Blue Swirl
    return cpu_inl(port);
669 eaa728ee bellard
}
670 eaa728ee bellard
671 eaa728ee bellard
static inline unsigned int get_sp_mask(unsigned int e2)
672 eaa728ee bellard
{
673 20054ef0 Blue Swirl
    if (e2 & DESC_B_MASK) {
674 eaa728ee bellard
        return 0xffffffff;
675 20054ef0 Blue Swirl
    } else {
676 eaa728ee bellard
        return 0xffff;
677 20054ef0 Blue Swirl
    }
678 eaa728ee bellard
}
679 eaa728ee bellard
680 20054ef0 Blue Swirl
static int exception_has_error_code(int intno)
681 2ed51f5b aliguori
{
682 20054ef0 Blue Swirl
    switch (intno) {
683 20054ef0 Blue Swirl
    case 8:
684 20054ef0 Blue Swirl
    case 10:
685 20054ef0 Blue Swirl
    case 11:
686 20054ef0 Blue Swirl
    case 12:
687 20054ef0 Blue Swirl
    case 13:
688 20054ef0 Blue Swirl
    case 14:
689 20054ef0 Blue Swirl
    case 17:
690 20054ef0 Blue Swirl
        return 1;
691 20054ef0 Blue Swirl
    }
692 20054ef0 Blue Swirl
    return 0;
693 2ed51f5b aliguori
}
694 2ed51f5b aliguori
695 eaa728ee bellard
#ifdef TARGET_X86_64
696 20054ef0 Blue Swirl
#define SET_ESP(val, sp_mask)                           \
697 20054ef0 Blue Swirl
    do {                                                \
698 20054ef0 Blue Swirl
        if ((sp_mask) == 0xffff) {                      \
699 20054ef0 Blue Swirl
            ESP = (ESP & ~0xffff) | ((val) & 0xffff);   \
700 20054ef0 Blue Swirl
        } else if ((sp_mask) == 0xffffffffLL) {         \
701 20054ef0 Blue Swirl
            ESP = (uint32_t)(val);                      \
702 20054ef0 Blue Swirl
        } else {                                        \
703 20054ef0 Blue Swirl
            ESP = (val);                                \
704 20054ef0 Blue Swirl
        }                                               \
705 20054ef0 Blue Swirl
    } while (0)
706 eaa728ee bellard
#else
707 20054ef0 Blue Swirl
#define SET_ESP(val, sp_mask)                           \
708 20054ef0 Blue Swirl
    do {                                                \
709 20054ef0 Blue Swirl
        ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask)); \
710 20054ef0 Blue Swirl
    } while (0)
711 eaa728ee bellard
#endif
712 eaa728ee bellard
713 c0a04f0e aliguori
/* in 64-bit machines, this can overflow. So this segment addition macro
714 c0a04f0e aliguori
 * can be used to trim the value to 32-bit whenever needed */
715 c0a04f0e aliguori
#define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
716 c0a04f0e aliguori
717 eaa728ee bellard
/* XXX: add a is_user flag to have proper security support */
718 20054ef0 Blue Swirl
#define PUSHW(ssp, sp, sp_mask, val)                    \
719 20054ef0 Blue Swirl
    {                                                   \
720 20054ef0 Blue Swirl
        sp -= 2;                                        \
721 20054ef0 Blue Swirl
        stw_kernel((ssp) + (sp & (sp_mask)), (val));    \
722 20054ef0 Blue Swirl
    }
723 eaa728ee bellard
724 20054ef0 Blue Swirl
#define PUSHL(ssp, sp, sp_mask, val)                                    \
725 20054ef0 Blue Swirl
    {                                                                   \
726 20054ef0 Blue Swirl
        sp -= 4;                                                        \
727 20054ef0 Blue Swirl
        stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));        \
728 20054ef0 Blue Swirl
    }
729 eaa728ee bellard
730 20054ef0 Blue Swirl
#define POPW(ssp, sp, sp_mask, val)                     \
731 20054ef0 Blue Swirl
    {                                                   \
732 20054ef0 Blue Swirl
        val = lduw_kernel((ssp) + (sp & (sp_mask)));    \
733 20054ef0 Blue Swirl
        sp += 2;                                        \
734 20054ef0 Blue Swirl
    }
735 eaa728ee bellard
736 20054ef0 Blue Swirl
#define POPL(ssp, sp, sp_mask, val)                             \
737 20054ef0 Blue Swirl
    {                                                           \
738 20054ef0 Blue Swirl
        val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask)); \
739 20054ef0 Blue Swirl
        sp += 4;                                                \
740 20054ef0 Blue Swirl
    }
741 eaa728ee bellard
742 eaa728ee bellard
/* protected mode interrupt */
743 eaa728ee bellard
static void do_interrupt_protected(int intno, int is_int, int error_code,
744 eaa728ee bellard
                                   unsigned int next_eip, int is_hw)
745 eaa728ee bellard
{
746 eaa728ee bellard
    SegmentCache *dt;
747 eaa728ee bellard
    target_ulong ptr, ssp;
748 eaa728ee bellard
    int type, dpl, selector, ss_dpl, cpl;
749 eaa728ee bellard
    int has_error_code, new_stack, shift;
750 1c918eba blueswir1
    uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
751 eaa728ee bellard
    uint32_t old_eip, sp_mask;
752 eaa728ee bellard
753 eaa728ee bellard
    has_error_code = 0;
754 20054ef0 Blue Swirl
    if (!is_int && !is_hw) {
755 20054ef0 Blue Swirl
        has_error_code = exception_has_error_code(intno);
756 20054ef0 Blue Swirl
    }
757 20054ef0 Blue Swirl
    if (is_int) {
758 eaa728ee bellard
        old_eip = next_eip;
759 20054ef0 Blue Swirl
    } else {
760 eaa728ee bellard
        old_eip = env->eip;
761 20054ef0 Blue Swirl
    }
762 eaa728ee bellard
763 eaa728ee bellard
    dt = &env->idt;
764 20054ef0 Blue Swirl
    if (intno * 8 + 7 > dt->limit) {
765 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
766 20054ef0 Blue Swirl
    }
767 eaa728ee bellard
    ptr = dt->base + intno * 8;
768 eaa728ee bellard
    e1 = ldl_kernel(ptr);
769 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
770 eaa728ee bellard
    /* check gate type */
771 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
772 20054ef0 Blue Swirl
    switch (type) {
773 eaa728ee bellard
    case 5: /* task gate */
774 eaa728ee bellard
        /* must do that check here to return the correct error code */
775 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
776 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
777 20054ef0 Blue Swirl
        }
778 eaa728ee bellard
        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
779 eaa728ee bellard
        if (has_error_code) {
780 eaa728ee bellard
            int type;
781 eaa728ee bellard
            uint32_t mask;
782 20054ef0 Blue Swirl
783 eaa728ee bellard
            /* push the error code */
784 eaa728ee bellard
            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
785 eaa728ee bellard
            shift = type >> 3;
786 20054ef0 Blue Swirl
            if (env->segs[R_SS].flags & DESC_B_MASK) {
787 eaa728ee bellard
                mask = 0xffffffff;
788 20054ef0 Blue Swirl
            } else {
789 eaa728ee bellard
                mask = 0xffff;
790 20054ef0 Blue Swirl
            }
791 eaa728ee bellard
            esp = (ESP - (2 << shift)) & mask;
792 eaa728ee bellard
            ssp = env->segs[R_SS].base + esp;
793 20054ef0 Blue Swirl
            if (shift) {
794 eaa728ee bellard
                stl_kernel(ssp, error_code);
795 20054ef0 Blue Swirl
            } else {
796 eaa728ee bellard
                stw_kernel(ssp, error_code);
797 20054ef0 Blue Swirl
            }
798 eaa728ee bellard
            SET_ESP(esp, mask);
799 eaa728ee bellard
        }
800 eaa728ee bellard
        return;
801 eaa728ee bellard
    case 6: /* 286 interrupt gate */
802 eaa728ee bellard
    case 7: /* 286 trap gate */
803 eaa728ee bellard
    case 14: /* 386 interrupt gate */
804 eaa728ee bellard
    case 15: /* 386 trap gate */
805 eaa728ee bellard
        break;
806 eaa728ee bellard
    default:
807 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
808 eaa728ee bellard
        break;
809 eaa728ee bellard
    }
810 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
811 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
812 1235fc06 ths
    /* check privilege if software int */
813 20054ef0 Blue Swirl
    if (is_int && dpl < cpl) {
814 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
815 20054ef0 Blue Swirl
    }
816 eaa728ee bellard
    /* check valid bit */
817 20054ef0 Blue Swirl
    if (!(e2 & DESC_P_MASK)) {
818 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0B_NOSEG, intno * 8 + 2);
819 20054ef0 Blue Swirl
    }
820 eaa728ee bellard
    selector = e1 >> 16;
821 eaa728ee bellard
    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
822 20054ef0 Blue Swirl
    if ((selector & 0xfffc) == 0) {
823 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
824 20054ef0 Blue Swirl
    }
825 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, selector) != 0) {
826 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
827 20054ef0 Blue Swirl
    }
828 20054ef0 Blue Swirl
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) {
829 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
830 20054ef0 Blue Swirl
    }
831 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
832 20054ef0 Blue Swirl
    if (dpl > cpl) {
833 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
834 20054ef0 Blue Swirl
    }
835 20054ef0 Blue Swirl
    if (!(e2 & DESC_P_MASK)) {
836 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
837 20054ef0 Blue Swirl
    }
838 eaa728ee bellard
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
839 eaa728ee bellard
        /* to inner privilege */
840 eaa728ee bellard
        get_ss_esp_from_tss(&ss, &esp, dpl);
841 20054ef0 Blue Swirl
        if ((ss & 0xfffc) == 0) {
842 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
843 20054ef0 Blue Swirl
        }
844 20054ef0 Blue Swirl
        if ((ss & 3) != dpl) {
845 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
846 20054ef0 Blue Swirl
        }
847 20054ef0 Blue Swirl
        if (load_segment(&ss_e1, &ss_e2, ss) != 0) {
848 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
849 20054ef0 Blue Swirl
        }
850 eaa728ee bellard
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
851 20054ef0 Blue Swirl
        if (ss_dpl != dpl) {
852 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
853 20054ef0 Blue Swirl
        }
854 eaa728ee bellard
        if (!(ss_e2 & DESC_S_MASK) ||
855 eaa728ee bellard
            (ss_e2 & DESC_CS_MASK) ||
856 20054ef0 Blue Swirl
            !(ss_e2 & DESC_W_MASK)) {
857 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
858 20054ef0 Blue Swirl
        }
859 20054ef0 Blue Swirl
        if (!(ss_e2 & DESC_P_MASK)) {
860 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
861 20054ef0 Blue Swirl
        }
862 eaa728ee bellard
        new_stack = 1;
863 eaa728ee bellard
        sp_mask = get_sp_mask(ss_e2);
864 eaa728ee bellard
        ssp = get_seg_base(ss_e1, ss_e2);
865 eaa728ee bellard
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
866 eaa728ee bellard
        /* to same privilege */
867 20054ef0 Blue Swirl
        if (env->eflags & VM_MASK) {
868 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
869 20054ef0 Blue Swirl
        }
870 eaa728ee bellard
        new_stack = 0;
871 eaa728ee bellard
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
872 eaa728ee bellard
        ssp = env->segs[R_SS].base;
873 eaa728ee bellard
        esp = ESP;
874 eaa728ee bellard
        dpl = cpl;
875 eaa728ee bellard
    } else {
876 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
877 eaa728ee bellard
        new_stack = 0; /* avoid warning */
878 eaa728ee bellard
        sp_mask = 0; /* avoid warning */
879 eaa728ee bellard
        ssp = 0; /* avoid warning */
880 eaa728ee bellard
        esp = 0; /* avoid warning */
881 eaa728ee bellard
    }
882 eaa728ee bellard
883 eaa728ee bellard
    shift = type >> 3;
884 eaa728ee bellard
885 eaa728ee bellard
#if 0
886 eaa728ee bellard
    /* XXX: check that enough room is available */
887 eaa728ee bellard
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
888 20054ef0 Blue Swirl
    if (env->eflags & VM_MASK) {
889 eaa728ee bellard
        push_size += 8;
890 20054ef0 Blue Swirl
    }
891 eaa728ee bellard
    push_size <<= shift;
892 eaa728ee bellard
#endif
893 eaa728ee bellard
    if (shift == 1) {
894 eaa728ee bellard
        if (new_stack) {
895 eaa728ee bellard
            if (env->eflags & VM_MASK) {
896 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
897 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
898 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
899 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
900 eaa728ee bellard
            }
901 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
902 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, ESP);
903 eaa728ee bellard
        }
904 997ff0d9 Blue Swirl
        PUSHL(ssp, esp, sp_mask, cpu_compute_eflags(env));
905 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
906 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, old_eip);
907 eaa728ee bellard
        if (has_error_code) {
908 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, error_code);
909 eaa728ee bellard
        }
910 eaa728ee bellard
    } else {
911 eaa728ee bellard
        if (new_stack) {
912 eaa728ee bellard
            if (env->eflags & VM_MASK) {
913 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
914 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
915 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
916 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
917 eaa728ee bellard
            }
918 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
919 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, ESP);
920 eaa728ee bellard
        }
921 997ff0d9 Blue Swirl
        PUSHW(ssp, esp, sp_mask, cpu_compute_eflags(env));
922 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
923 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, old_eip);
924 eaa728ee bellard
        if (has_error_code) {
925 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, error_code);
926 eaa728ee bellard
        }
927 eaa728ee bellard
    }
928 eaa728ee bellard
929 eaa728ee bellard
    if (new_stack) {
930 eaa728ee bellard
        if (env->eflags & VM_MASK) {
931 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
932 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
933 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
934 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
935 eaa728ee bellard
        }
936 eaa728ee bellard
        ss = (ss & ~3) | dpl;
937 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, ss,
938 eaa728ee bellard
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
939 eaa728ee bellard
    }
940 eaa728ee bellard
    SET_ESP(esp, sp_mask);
941 eaa728ee bellard
942 eaa728ee bellard
    selector = (selector & ~3) | dpl;
943 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, selector,
944 eaa728ee bellard
                   get_seg_base(e1, e2),
945 eaa728ee bellard
                   get_seg_limit(e1, e2),
946 eaa728ee bellard
                   e2);
947 eaa728ee bellard
    cpu_x86_set_cpl(env, dpl);
948 eaa728ee bellard
    env->eip = offset;
949 eaa728ee bellard
950 eaa728ee bellard
    /* interrupt gate clear IF mask */
951 eaa728ee bellard
    if ((type & 1) == 0) {
952 eaa728ee bellard
        env->eflags &= ~IF_MASK;
953 eaa728ee bellard
    }
954 eaa728ee bellard
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
955 eaa728ee bellard
}
956 eaa728ee bellard
957 eaa728ee bellard
#ifdef TARGET_X86_64
958 eaa728ee bellard
959 20054ef0 Blue Swirl
#define PUSHQ(sp, val)                          \
960 20054ef0 Blue Swirl
    {                                           \
961 20054ef0 Blue Swirl
        sp -= 8;                                \
962 20054ef0 Blue Swirl
        stq_kernel(sp, (val));                  \
963 20054ef0 Blue Swirl
    }
964 eaa728ee bellard
965 20054ef0 Blue Swirl
#define POPQ(sp, val)                           \
966 20054ef0 Blue Swirl
    {                                           \
967 20054ef0 Blue Swirl
        val = ldq_kernel(sp);                   \
968 20054ef0 Blue Swirl
        sp += 8;                                \
969 20054ef0 Blue Swirl
    }
970 eaa728ee bellard
971 eaa728ee bellard
static inline target_ulong get_rsp_from_tss(int level)
972 eaa728ee bellard
{
973 eaa728ee bellard
    int index;
974 eaa728ee bellard
975 eaa728ee bellard
#if 0
976 eaa728ee bellard
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
977 eaa728ee bellard
           env->tr.base, env->tr.limit);
978 eaa728ee bellard
#endif
979 eaa728ee bellard
980 20054ef0 Blue Swirl
    if (!(env->tr.flags & DESC_P_MASK)) {
981 eaa728ee bellard
        cpu_abort(env, "invalid tss");
982 20054ef0 Blue Swirl
    }
983 eaa728ee bellard
    index = 8 * level + 4;
984 20054ef0 Blue Swirl
    if ((index + 7) > env->tr.limit) {
985 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc);
986 20054ef0 Blue Swirl
    }
987 eaa728ee bellard
    return ldq_kernel(env->tr.base + index);
988 eaa728ee bellard
}
989 eaa728ee bellard
990 eaa728ee bellard
/* 64 bit interrupt */
991 eaa728ee bellard
static void do_interrupt64(int intno, int is_int, int error_code,
992 eaa728ee bellard
                           target_ulong next_eip, int is_hw)
993 eaa728ee bellard
{
994 eaa728ee bellard
    SegmentCache *dt;
995 eaa728ee bellard
    target_ulong ptr;
996 eaa728ee bellard
    int type, dpl, selector, cpl, ist;
997 eaa728ee bellard
    int has_error_code, new_stack;
998 eaa728ee bellard
    uint32_t e1, e2, e3, ss;
999 eaa728ee bellard
    target_ulong old_eip, esp, offset;
1000 eaa728ee bellard
1001 eaa728ee bellard
    has_error_code = 0;
1002 20054ef0 Blue Swirl
    if (!is_int && !is_hw) {
1003 20054ef0 Blue Swirl
        has_error_code = exception_has_error_code(intno);
1004 20054ef0 Blue Swirl
    }
1005 20054ef0 Blue Swirl
    if (is_int) {
1006 eaa728ee bellard
        old_eip = next_eip;
1007 20054ef0 Blue Swirl
    } else {
1008 eaa728ee bellard
        old_eip = env->eip;
1009 20054ef0 Blue Swirl
    }
1010 eaa728ee bellard
1011 eaa728ee bellard
    dt = &env->idt;
1012 20054ef0 Blue Swirl
    if (intno * 16 + 15 > dt->limit) {
1013 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
1014 20054ef0 Blue Swirl
    }
1015 eaa728ee bellard
    ptr = dt->base + intno * 16;
1016 eaa728ee bellard
    e1 = ldl_kernel(ptr);
1017 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
1018 eaa728ee bellard
    e3 = ldl_kernel(ptr + 8);
1019 eaa728ee bellard
    /* check gate type */
1020 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
1021 20054ef0 Blue Swirl
    switch (type) {
1022 eaa728ee bellard
    case 14: /* 386 interrupt gate */
1023 eaa728ee bellard
    case 15: /* 386 trap gate */
1024 eaa728ee bellard
        break;
1025 eaa728ee bellard
    default:
1026 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
1027 eaa728ee bellard
        break;
1028 eaa728ee bellard
    }
1029 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1030 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
1031 1235fc06 ths
    /* check privilege if software int */
1032 20054ef0 Blue Swirl
    if (is_int && dpl < cpl) {
1033 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);
1034 20054ef0 Blue Swirl
    }
1035 eaa728ee bellard
    /* check valid bit */
1036 20054ef0 Blue Swirl
    if (!(e2 & DESC_P_MASK)) {
1037 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0B_NOSEG, intno * 16 + 2);
1038 20054ef0 Blue Swirl
    }
1039 eaa728ee bellard
    selector = e1 >> 16;
1040 eaa728ee bellard
    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
1041 eaa728ee bellard
    ist = e2 & 7;
1042 20054ef0 Blue Swirl
    if ((selector & 0xfffc) == 0) {
1043 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
1044 20054ef0 Blue Swirl
    }
1045 eaa728ee bellard
1046 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, selector) != 0) {
1047 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
1048 20054ef0 Blue Swirl
    }
1049 20054ef0 Blue Swirl
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) {
1050 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
1051 20054ef0 Blue Swirl
    }
1052 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1053 20054ef0 Blue Swirl
    if (dpl > cpl) {
1054 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
1055 20054ef0 Blue Swirl
    }
1056 20054ef0 Blue Swirl
    if (!(e2 & DESC_P_MASK)) {
1057 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
1058 20054ef0 Blue Swirl
    }
1059 20054ef0 Blue Swirl
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK)) {
1060 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
1061 20054ef0 Blue Swirl
    }
1062 eaa728ee bellard
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
1063 eaa728ee bellard
        /* to inner privilege */
1064 20054ef0 Blue Swirl
        if (ist != 0) {
1065 eaa728ee bellard
            esp = get_rsp_from_tss(ist + 3);
1066 20054ef0 Blue Swirl
        } else {
1067 eaa728ee bellard
            esp = get_rsp_from_tss(dpl);
1068 20054ef0 Blue Swirl
        }
1069 eaa728ee bellard
        esp &= ~0xfLL; /* align stack */
1070 eaa728ee bellard
        ss = 0;
1071 eaa728ee bellard
        new_stack = 1;
1072 eaa728ee bellard
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
1073 eaa728ee bellard
        /* to same privilege */
1074 20054ef0 Blue Swirl
        if (env->eflags & VM_MASK) {
1075 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
1076 20054ef0 Blue Swirl
        }
1077 eaa728ee bellard
        new_stack = 0;
1078 20054ef0 Blue Swirl
        if (ist != 0) {
1079 eaa728ee bellard
            esp = get_rsp_from_tss(ist + 3);
1080 20054ef0 Blue Swirl
        } else {
1081 eaa728ee bellard
            esp = ESP;
1082 20054ef0 Blue Swirl
        }
1083 eaa728ee bellard
        esp &= ~0xfLL; /* align stack */
1084 eaa728ee bellard
        dpl = cpl;
1085 eaa728ee bellard
    } else {
1086 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
1087 eaa728ee bellard
        new_stack = 0; /* avoid warning */
1088 eaa728ee bellard
        esp = 0; /* avoid warning */
1089 eaa728ee bellard
    }
1090 eaa728ee bellard
1091 eaa728ee bellard
    PUSHQ(esp, env->segs[R_SS].selector);
1092 eaa728ee bellard
    PUSHQ(esp, ESP);
1093 997ff0d9 Blue Swirl
    PUSHQ(esp, cpu_compute_eflags(env));
1094 eaa728ee bellard
    PUSHQ(esp, env->segs[R_CS].selector);
1095 eaa728ee bellard
    PUSHQ(esp, old_eip);
1096 eaa728ee bellard
    if (has_error_code) {
1097 eaa728ee bellard
        PUSHQ(esp, error_code);
1098 eaa728ee bellard
    }
1099 eaa728ee bellard
1100 eaa728ee bellard
    if (new_stack) {
1101 eaa728ee bellard
        ss = 0 | dpl;
1102 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
1103 eaa728ee bellard
    }
1104 eaa728ee bellard
    ESP = esp;
1105 eaa728ee bellard
1106 eaa728ee bellard
    selector = (selector & ~3) | dpl;
1107 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, selector,
1108 eaa728ee bellard
                   get_seg_base(e1, e2),
1109 eaa728ee bellard
                   get_seg_limit(e1, e2),
1110 eaa728ee bellard
                   e2);
1111 eaa728ee bellard
    cpu_x86_set_cpl(env, dpl);
1112 eaa728ee bellard
    env->eip = offset;
1113 eaa728ee bellard
1114 eaa728ee bellard
    /* interrupt gate clear IF mask */
1115 eaa728ee bellard
    if ((type & 1) == 0) {
1116 eaa728ee bellard
        env->eflags &= ~IF_MASK;
1117 eaa728ee bellard
    }
1118 eaa728ee bellard
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
1119 eaa728ee bellard
}
1120 eaa728ee bellard
#endif
1121 eaa728ee bellard
1122 d9957a8b blueswir1
#ifdef TARGET_X86_64
1123 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
1124 eaa728ee bellard
void helper_syscall(int next_eip_addend)
1125 eaa728ee bellard
{
1126 eaa728ee bellard
    env->exception_index = EXCP_SYSCALL;
1127 eaa728ee bellard
    env->exception_next_eip = env->eip + next_eip_addend;
1128 1162c041 Blue Swirl
    cpu_loop_exit(env);
1129 eaa728ee bellard
}
1130 eaa728ee bellard
#else
1131 eaa728ee bellard
void helper_syscall(int next_eip_addend)
1132 eaa728ee bellard
{
1133 eaa728ee bellard
    int selector;
1134 eaa728ee bellard
1135 eaa728ee bellard
    if (!(env->efer & MSR_EFER_SCE)) {
1136 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP06_ILLOP, 0);
1137 eaa728ee bellard
    }
1138 eaa728ee bellard
    selector = (env->star >> 32) & 0xffff;
1139 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1140 eaa728ee bellard
        int code64;
1141 eaa728ee bellard
1142 eaa728ee bellard
        ECX = env->eip + next_eip_addend;
1143 997ff0d9 Blue Swirl
        env->regs[11] = cpu_compute_eflags(env);
1144 eaa728ee bellard
1145 eaa728ee bellard
        code64 = env->hflags & HF_CS64_MASK;
1146 eaa728ee bellard
1147 eaa728ee bellard
        cpu_x86_set_cpl(env, 0);
1148 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1149 eaa728ee bellard
                           0, 0xffffffff,
1150 eaa728ee bellard
                               DESC_G_MASK | DESC_P_MASK |
1151 eaa728ee bellard
                               DESC_S_MASK |
1152 20054ef0 Blue Swirl
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1153 20054ef0 Blue Swirl
                               DESC_L_MASK);
1154 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1155 eaa728ee bellard
                               0, 0xffffffff,
1156 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1157 eaa728ee bellard
                               DESC_S_MASK |
1158 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1159 eaa728ee bellard
        env->eflags &= ~env->fmask;
1160 997ff0d9 Blue Swirl
        cpu_load_eflags(env, env->eflags, 0);
1161 20054ef0 Blue Swirl
        if (code64) {
1162 eaa728ee bellard
            env->eip = env->lstar;
1163 20054ef0 Blue Swirl
        } else {
1164 eaa728ee bellard
            env->eip = env->cstar;
1165 20054ef0 Blue Swirl
        }
1166 d9957a8b blueswir1
    } else {
1167 eaa728ee bellard
        ECX = (uint32_t)(env->eip + next_eip_addend);
1168 eaa728ee bellard
1169 eaa728ee bellard
        cpu_x86_set_cpl(env, 0);
1170 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1171 eaa728ee bellard
                           0, 0xffffffff,
1172 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1173 eaa728ee bellard
                               DESC_S_MASK |
1174 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1175 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1176 eaa728ee bellard
                               0, 0xffffffff,
1177 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1178 eaa728ee bellard
                               DESC_S_MASK |
1179 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1180 eaa728ee bellard
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1181 eaa728ee bellard
        env->eip = (uint32_t)env->star;
1182 eaa728ee bellard
    }
1183 eaa728ee bellard
}
1184 eaa728ee bellard
#endif
1185 d9957a8b blueswir1
#endif
1186 eaa728ee bellard
1187 d9957a8b blueswir1
#ifdef TARGET_X86_64
1188 eaa728ee bellard
void helper_sysret(int dflag)
1189 eaa728ee bellard
{
1190 eaa728ee bellard
    int cpl, selector;
1191 eaa728ee bellard
1192 eaa728ee bellard
    if (!(env->efer & MSR_EFER_SCE)) {
1193 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP06_ILLOP, 0);
1194 eaa728ee bellard
    }
1195 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
1196 eaa728ee bellard
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1197 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
1198 eaa728ee bellard
    }
1199 eaa728ee bellard
    selector = (env->star >> 48) & 0xffff;
1200 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1201 eaa728ee bellard
        if (dflag == 2) {
1202 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1203 eaa728ee bellard
                                   0, 0xffffffff,
1204 eaa728ee bellard
                                   DESC_G_MASK | DESC_P_MASK |
1205 eaa728ee bellard
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1206 eaa728ee bellard
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1207 eaa728ee bellard
                                   DESC_L_MASK);
1208 eaa728ee bellard
            env->eip = ECX;
1209 eaa728ee bellard
        } else {
1210 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1211 eaa728ee bellard
                                   0, 0xffffffff,
1212 eaa728ee bellard
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1213 eaa728ee bellard
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1214 eaa728ee bellard
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1215 eaa728ee bellard
            env->eip = (uint32_t)ECX;
1216 eaa728ee bellard
        }
1217 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1218 eaa728ee bellard
                               0, 0xffffffff,
1219 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1220 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1221 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1222 997ff0d9 Blue Swirl
        cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
1223 997ff0d9 Blue Swirl
                        | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
1224 997ff0d9 Blue Swirl
                        NT_MASK);
1225 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
1226 d9957a8b blueswir1
    } else {
1227 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1228 eaa728ee bellard
                               0, 0xffffffff,
1229 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1230 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1231 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1232 eaa728ee bellard
        env->eip = (uint32_t)ECX;
1233 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1234 eaa728ee bellard
                               0, 0xffffffff,
1235 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1236 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1237 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1238 eaa728ee bellard
        env->eflags |= IF_MASK;
1239 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
1240 eaa728ee bellard
    }
1241 eaa728ee bellard
}
1242 d9957a8b blueswir1
#endif
1243 eaa728ee bellard
1244 eaa728ee bellard
/* real mode interrupt */
1245 eaa728ee bellard
static void do_interrupt_real(int intno, int is_int, int error_code,
1246 eaa728ee bellard
                              unsigned int next_eip)
1247 eaa728ee bellard
{
1248 eaa728ee bellard
    SegmentCache *dt;
1249 eaa728ee bellard
    target_ulong ptr, ssp;
1250 eaa728ee bellard
    int selector;
1251 eaa728ee bellard
    uint32_t offset, esp;
1252 eaa728ee bellard
    uint32_t old_cs, old_eip;
1253 eaa728ee bellard
1254 20054ef0 Blue Swirl
    /* real mode (simpler!) */
1255 eaa728ee bellard
    dt = &env->idt;
1256 20054ef0 Blue Swirl
    if (intno * 4 + 3 > dt->limit) {
1257 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, intno * 8 + 2);
1258 20054ef0 Blue Swirl
    }
1259 eaa728ee bellard
    ptr = dt->base + intno * 4;
1260 eaa728ee bellard
    offset = lduw_kernel(ptr);
1261 eaa728ee bellard
    selector = lduw_kernel(ptr + 2);
1262 eaa728ee bellard
    esp = ESP;
1263 eaa728ee bellard
    ssp = env->segs[R_SS].base;
1264 20054ef0 Blue Swirl
    if (is_int) {
1265 eaa728ee bellard
        old_eip = next_eip;
1266 20054ef0 Blue Swirl
    } else {
1267 eaa728ee bellard
        old_eip = env->eip;
1268 20054ef0 Blue Swirl
    }
1269 eaa728ee bellard
    old_cs = env->segs[R_CS].selector;
1270 20054ef0 Blue Swirl
    /* XXX: use SS segment size? */
1271 997ff0d9 Blue Swirl
    PUSHW(ssp, esp, 0xffff, cpu_compute_eflags(env));
1272 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, old_cs);
1273 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, old_eip);
1274 eaa728ee bellard
1275 eaa728ee bellard
    /* update processor state */
1276 eaa728ee bellard
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1277 eaa728ee bellard
    env->eip = offset;
1278 eaa728ee bellard
    env->segs[R_CS].selector = selector;
1279 eaa728ee bellard
    env->segs[R_CS].base = (selector << 4);
1280 eaa728ee bellard
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1281 eaa728ee bellard
}
1282 eaa728ee bellard
1283 e694d4e2 Blue Swirl
#if defined(CONFIG_USER_ONLY)
1284 eaa728ee bellard
/* fake user mode interrupt */
1285 e694d4e2 Blue Swirl
static void do_interrupt_user(int intno, int is_int, int error_code,
1286 e694d4e2 Blue Swirl
                              target_ulong next_eip)
1287 eaa728ee bellard
{
1288 eaa728ee bellard
    SegmentCache *dt;
1289 eaa728ee bellard
    target_ulong ptr;
1290 eaa728ee bellard
    int dpl, cpl, shift;
1291 eaa728ee bellard
    uint32_t e2;
1292 eaa728ee bellard
1293 eaa728ee bellard
    dt = &env->idt;
1294 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1295 eaa728ee bellard
        shift = 4;
1296 eaa728ee bellard
    } else {
1297 eaa728ee bellard
        shift = 3;
1298 eaa728ee bellard
    }
1299 eaa728ee bellard
    ptr = dt->base + (intno << shift);
1300 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
1301 eaa728ee bellard
1302 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1303 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
1304 1235fc06 ths
    /* check privilege if software int */
1305 20054ef0 Blue Swirl
    if (is_int && dpl < cpl) {
1306 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, (intno << shift) + 2);
1307 20054ef0 Blue Swirl
    }
1308 eaa728ee bellard
1309 eaa728ee bellard
    /* Since we emulate only user space, we cannot do more than
1310 eaa728ee bellard
       exiting the emulation with the suitable exception and error
1311 eaa728ee bellard
       code */
1312 20054ef0 Blue Swirl
    if (is_int) {
1313 eaa728ee bellard
        EIP = next_eip;
1314 20054ef0 Blue Swirl
    }
1315 eaa728ee bellard
}
1316 eaa728ee bellard
1317 e694d4e2 Blue Swirl
#else
1318 e694d4e2 Blue Swirl
1319 2ed51f5b aliguori
static void handle_even_inj(int intno, int is_int, int error_code,
1320 20054ef0 Blue Swirl
                            int is_hw, int rm)
1321 2ed51f5b aliguori
{
1322 20054ef0 Blue Swirl
    uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb,
1323 20054ef0 Blue Swirl
                                                          control.event_inj));
1324 20054ef0 Blue Swirl
1325 2ed51f5b aliguori
    if (!(event_inj & SVM_EVTINJ_VALID)) {
1326 20054ef0 Blue Swirl
        int type;
1327 20054ef0 Blue Swirl
1328 20054ef0 Blue Swirl
        if (is_int) {
1329 20054ef0 Blue Swirl
            type = SVM_EVTINJ_TYPE_SOFT;
1330 20054ef0 Blue Swirl
        } else {
1331 20054ef0 Blue Swirl
            type = SVM_EVTINJ_TYPE_EXEPT;
1332 20054ef0 Blue Swirl
        }
1333 20054ef0 Blue Swirl
        event_inj = intno | type | SVM_EVTINJ_VALID;
1334 20054ef0 Blue Swirl
        if (!rm && exception_has_error_code(intno)) {
1335 20054ef0 Blue Swirl
            event_inj |= SVM_EVTINJ_VALID_ERR;
1336 20054ef0 Blue Swirl
            stl_phys(env->vm_vmcb + offsetof(struct vmcb,
1337 20054ef0 Blue Swirl
                                             control.event_inj_err),
1338 20054ef0 Blue Swirl
                     error_code);
1339 20054ef0 Blue Swirl
        }
1340 20054ef0 Blue Swirl
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj),
1341 20054ef0 Blue Swirl
                 event_inj);
1342 2ed51f5b aliguori
    }
1343 2ed51f5b aliguori
}
1344 00ea18d1 aliguori
#endif
1345 2ed51f5b aliguori
1346 eaa728ee bellard
/*
1347 eaa728ee bellard
 * Begin execution of an interruption. is_int is TRUE if coming from
1348 eaa728ee bellard
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1349 eaa728ee bellard
 * instruction. It is only relevant if is_int is TRUE.
1350 eaa728ee bellard
 */
1351 e694d4e2 Blue Swirl
static void do_interrupt_all(int intno, int is_int, int error_code,
1352 e694d4e2 Blue Swirl
                             target_ulong next_eip, int is_hw)
1353 eaa728ee bellard
{
1354 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
1355 eaa728ee bellard
        if ((env->cr[0] & CR0_PE_MASK)) {
1356 eaa728ee bellard
            static int count;
1357 20054ef0 Blue Swirl
1358 20054ef0 Blue Swirl
            qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx
1359 20054ef0 Blue Swirl
                     " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1360 20054ef0 Blue Swirl
                     count, intno, error_code, is_int,
1361 20054ef0 Blue Swirl
                     env->hflags & HF_CPL_MASK,
1362 20054ef0 Blue Swirl
                     env->segs[R_CS].selector, EIP,
1363 20054ef0 Blue Swirl
                     (int)env->segs[R_CS].base + EIP,
1364 20054ef0 Blue Swirl
                     env->segs[R_SS].selector, ESP);
1365 eaa728ee bellard
            if (intno == 0x0e) {
1366 93fcfe39 aliguori
                qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
1367 eaa728ee bellard
            } else {
1368 93fcfe39 aliguori
                qemu_log(" EAX=" TARGET_FMT_lx, EAX);
1369 eaa728ee bellard
            }
1370 93fcfe39 aliguori
            qemu_log("\n");
1371 93fcfe39 aliguori
            log_cpu_state(env, X86_DUMP_CCOP);
1372 eaa728ee bellard
#if 0
1373 eaa728ee bellard
            {
1374 eaa728ee bellard
                int i;
1375 9bd5494e Adam Lackorzynski
                target_ulong ptr;
1376 20054ef0 Blue Swirl

1377 93fcfe39 aliguori
                qemu_log("       code=");
1378 eaa728ee bellard
                ptr = env->segs[R_CS].base + env->eip;
1379 20054ef0 Blue Swirl
                for (i = 0; i < 16; i++) {
1380 93fcfe39 aliguori
                    qemu_log(" %02x", ldub(ptr + i));
1381 eaa728ee bellard
                }
1382 93fcfe39 aliguori
                qemu_log("\n");
1383 eaa728ee bellard
            }
1384 eaa728ee bellard
#endif
1385 eaa728ee bellard
            count++;
1386 eaa728ee bellard
        }
1387 eaa728ee bellard
    }
1388 eaa728ee bellard
    if (env->cr[0] & CR0_PE_MASK) {
1389 00ea18d1 aliguori
#if !defined(CONFIG_USER_ONLY)
1390 20054ef0 Blue Swirl
        if (env->hflags & HF_SVMI_MASK) {
1391 2ed51f5b aliguori
            handle_even_inj(intno, is_int, error_code, is_hw, 0);
1392 20054ef0 Blue Swirl
        }
1393 00ea18d1 aliguori
#endif
1394 eb38c52c blueswir1
#ifdef TARGET_X86_64
1395 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
1396 eaa728ee bellard
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1397 eaa728ee bellard
        } else
1398 eaa728ee bellard
#endif
1399 eaa728ee bellard
        {
1400 eaa728ee bellard
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1401 eaa728ee bellard
        }
1402 eaa728ee bellard
    } else {
1403 00ea18d1 aliguori
#if !defined(CONFIG_USER_ONLY)
1404 20054ef0 Blue Swirl
        if (env->hflags & HF_SVMI_MASK) {
1405 2ed51f5b aliguori
            handle_even_inj(intno, is_int, error_code, is_hw, 1);
1406 20054ef0 Blue Swirl
        }
1407 00ea18d1 aliguori
#endif
1408 eaa728ee bellard
        do_interrupt_real(intno, is_int, error_code, next_eip);
1409 eaa728ee bellard
    }
1410 2ed51f5b aliguori
1411 00ea18d1 aliguori
#if !defined(CONFIG_USER_ONLY)
1412 2ed51f5b aliguori
    if (env->hflags & HF_SVMI_MASK) {
1413 20054ef0 Blue Swirl
        uint32_t event_inj = ldl_phys(env->vm_vmcb +
1414 20054ef0 Blue Swirl
                                      offsetof(struct vmcb,
1415 20054ef0 Blue Swirl
                                               control.event_inj));
1416 20054ef0 Blue Swirl
1417 20054ef0 Blue Swirl
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj),
1418 20054ef0 Blue Swirl
                 event_inj & ~SVM_EVTINJ_VALID);
1419 2ed51f5b aliguori
    }
1420 00ea18d1 aliguori
#endif
1421 eaa728ee bellard
}
1422 eaa728ee bellard
1423 317ac620 Andreas Färber
void do_interrupt(CPUX86State *env1)
1424 e694d4e2 Blue Swirl
{
1425 317ac620 Andreas Färber
    CPUX86State *saved_env;
1426 e694d4e2 Blue Swirl
1427 e694d4e2 Blue Swirl
    saved_env = env;
1428 e694d4e2 Blue Swirl
    env = env1;
1429 e694d4e2 Blue Swirl
#if defined(CONFIG_USER_ONLY)
1430 e694d4e2 Blue Swirl
    /* if user mode only, we simulate a fake exception
1431 e694d4e2 Blue Swirl
       which will be handled outside the cpu execution
1432 e694d4e2 Blue Swirl
       loop */
1433 e694d4e2 Blue Swirl
    do_interrupt_user(env->exception_index,
1434 e694d4e2 Blue Swirl
                      env->exception_is_int,
1435 e694d4e2 Blue Swirl
                      env->error_code,
1436 e694d4e2 Blue Swirl
                      env->exception_next_eip);
1437 e694d4e2 Blue Swirl
    /* successfully delivered */
1438 e694d4e2 Blue Swirl
    env->old_exception = -1;
1439 e694d4e2 Blue Swirl
#else
1440 e694d4e2 Blue Swirl
    /* simulate a real cpu exception. On i386, it can
1441 e694d4e2 Blue Swirl
       trigger new exceptions, but we do not handle
1442 e694d4e2 Blue Swirl
       double or triple faults yet. */
1443 e694d4e2 Blue Swirl
    do_interrupt_all(env->exception_index,
1444 e694d4e2 Blue Swirl
                     env->exception_is_int,
1445 e694d4e2 Blue Swirl
                     env->error_code,
1446 e694d4e2 Blue Swirl
                     env->exception_next_eip, 0);
1447 e694d4e2 Blue Swirl
    /* successfully delivered */
1448 e694d4e2 Blue Swirl
    env->old_exception = -1;
1449 e694d4e2 Blue Swirl
#endif
1450 e694d4e2 Blue Swirl
    env = saved_env;
1451 e694d4e2 Blue Swirl
}
1452 e694d4e2 Blue Swirl
1453 317ac620 Andreas Färber
void do_interrupt_x86_hardirq(CPUX86State *env1, int intno, int is_hw)
1454 e694d4e2 Blue Swirl
{
1455 317ac620 Andreas Färber
    CPUX86State *saved_env;
1456 e694d4e2 Blue Swirl
1457 e694d4e2 Blue Swirl
    saved_env = env;
1458 e694d4e2 Blue Swirl
    env = env1;
1459 e694d4e2 Blue Swirl
    do_interrupt_all(intno, 0, 0, 0, is_hw);
1460 e694d4e2 Blue Swirl
    env = saved_env;
1461 e694d4e2 Blue Swirl
}
1462 e694d4e2 Blue Swirl
1463 eaa728ee bellard
/* SMM support */
1464 eaa728ee bellard
1465 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
1466 eaa728ee bellard
1467 317ac620 Andreas Färber
void do_smm_enter(CPUX86State *env1)
1468 eaa728ee bellard
{
1469 eaa728ee bellard
}
1470 eaa728ee bellard
1471 eaa728ee bellard
void helper_rsm(void)
1472 eaa728ee bellard
{
1473 eaa728ee bellard
}
1474 eaa728ee bellard
1475 eaa728ee bellard
#else
1476 eaa728ee bellard
1477 eaa728ee bellard
#ifdef TARGET_X86_64
1478 eaa728ee bellard
#define SMM_REVISION_ID 0x00020064
1479 eaa728ee bellard
#else
1480 eaa728ee bellard
#define SMM_REVISION_ID 0x00020000
1481 eaa728ee bellard
#endif
1482 eaa728ee bellard
1483 317ac620 Andreas Färber
void do_smm_enter(CPUX86State *env1)
1484 eaa728ee bellard
{
1485 eaa728ee bellard
    target_ulong sm_state;
1486 eaa728ee bellard
    SegmentCache *dt;
1487 eaa728ee bellard
    int i, offset;
1488 317ac620 Andreas Färber
    CPUX86State *saved_env;
1489 e694d4e2 Blue Swirl
1490 e694d4e2 Blue Swirl
    saved_env = env;
1491 e694d4e2 Blue Swirl
    env = env1;
1492 eaa728ee bellard
1493 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
1494 93fcfe39 aliguori
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1495 eaa728ee bellard
1496 eaa728ee bellard
    env->hflags |= HF_SMM_MASK;
1497 eaa728ee bellard
    cpu_smm_update(env);
1498 eaa728ee bellard
1499 eaa728ee bellard
    sm_state = env->smbase + 0x8000;
1500 eaa728ee bellard
1501 eaa728ee bellard
#ifdef TARGET_X86_64
1502 20054ef0 Blue Swirl
    for (i = 0; i < 6; i++) {
1503 eaa728ee bellard
        dt = &env->segs[i];
1504 eaa728ee bellard
        offset = 0x7e00 + i * 16;
1505 eaa728ee bellard
        stw_phys(sm_state + offset, dt->selector);
1506 eaa728ee bellard
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1507 eaa728ee bellard
        stl_phys(sm_state + offset + 4, dt->limit);
1508 eaa728ee bellard
        stq_phys(sm_state + offset + 8, dt->base);
1509 eaa728ee bellard
    }
1510 eaa728ee bellard
1511 eaa728ee bellard
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1512 eaa728ee bellard
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1513 eaa728ee bellard
1514 eaa728ee bellard
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1515 eaa728ee bellard
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1516 eaa728ee bellard
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1517 eaa728ee bellard
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1518 eaa728ee bellard
1519 eaa728ee bellard
    stq_phys(sm_state + 0x7e88, env->idt.base);
1520 eaa728ee bellard
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1521 eaa728ee bellard
1522 eaa728ee bellard
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1523 eaa728ee bellard
    stq_phys(sm_state + 0x7e98, env->tr.base);
1524 eaa728ee bellard
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1525 eaa728ee bellard
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1526 eaa728ee bellard
1527 eaa728ee bellard
    stq_phys(sm_state + 0x7ed0, env->efer);
1528 eaa728ee bellard
1529 eaa728ee bellard
    stq_phys(sm_state + 0x7ff8, EAX);
1530 eaa728ee bellard
    stq_phys(sm_state + 0x7ff0, ECX);
1531 eaa728ee bellard
    stq_phys(sm_state + 0x7fe8, EDX);
1532 eaa728ee bellard
    stq_phys(sm_state + 0x7fe0, EBX);
1533 eaa728ee bellard
    stq_phys(sm_state + 0x7fd8, ESP);
1534 eaa728ee bellard
    stq_phys(sm_state + 0x7fd0, EBP);
1535 eaa728ee bellard
    stq_phys(sm_state + 0x7fc8, ESI);
1536 eaa728ee bellard
    stq_phys(sm_state + 0x7fc0, EDI);
1537 20054ef0 Blue Swirl
    for (i = 8; i < 16; i++) {
1538 eaa728ee bellard
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1539 20054ef0 Blue Swirl
    }
1540 eaa728ee bellard
    stq_phys(sm_state + 0x7f78, env->eip);
1541 997ff0d9 Blue Swirl
    stl_phys(sm_state + 0x7f70, cpu_compute_eflags(env));
1542 eaa728ee bellard
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1543 eaa728ee bellard
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1544 eaa728ee bellard
1545 eaa728ee bellard
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1546 eaa728ee bellard
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1547 eaa728ee bellard
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1548 eaa728ee bellard
1549 eaa728ee bellard
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1550 eaa728ee bellard
    stl_phys(sm_state + 0x7f00, env->smbase);
1551 eaa728ee bellard
#else
1552 eaa728ee bellard
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1553 eaa728ee bellard
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1554 997ff0d9 Blue Swirl
    stl_phys(sm_state + 0x7ff4, cpu_compute_eflags(env));
1555 eaa728ee bellard
    stl_phys(sm_state + 0x7ff0, env->eip);
1556 eaa728ee bellard
    stl_phys(sm_state + 0x7fec, EDI);
1557 eaa728ee bellard
    stl_phys(sm_state + 0x7fe8, ESI);
1558 eaa728ee bellard
    stl_phys(sm_state + 0x7fe4, EBP);
1559 eaa728ee bellard
    stl_phys(sm_state + 0x7fe0, ESP);
1560 eaa728ee bellard
    stl_phys(sm_state + 0x7fdc, EBX);
1561 eaa728ee bellard
    stl_phys(sm_state + 0x7fd8, EDX);
1562 eaa728ee bellard
    stl_phys(sm_state + 0x7fd4, ECX);
1563 eaa728ee bellard
    stl_phys(sm_state + 0x7fd0, EAX);
1564 eaa728ee bellard
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1565 eaa728ee bellard
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1566 eaa728ee bellard
1567 eaa728ee bellard
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1568 eaa728ee bellard
    stl_phys(sm_state + 0x7f64, env->tr.base);
1569 eaa728ee bellard
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1570 eaa728ee bellard
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1571 eaa728ee bellard
1572 eaa728ee bellard
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1573 eaa728ee bellard
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1574 eaa728ee bellard
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1575 eaa728ee bellard
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1576 eaa728ee bellard
1577 eaa728ee bellard
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1578 eaa728ee bellard
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1579 eaa728ee bellard
1580 eaa728ee bellard
    stl_phys(sm_state + 0x7f58, env->idt.base);
1581 eaa728ee bellard
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1582 eaa728ee bellard
1583 20054ef0 Blue Swirl
    for (i = 0; i < 6; i++) {
1584 eaa728ee bellard
        dt = &env->segs[i];
1585 20054ef0 Blue Swirl
        if (i < 3) {
1586 eaa728ee bellard
            offset = 0x7f84 + i * 12;
1587 20054ef0 Blue Swirl
        } else {
1588 eaa728ee bellard
            offset = 0x7f2c + (i - 3) * 12;
1589 20054ef0 Blue Swirl
        }
1590 eaa728ee bellard
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1591 eaa728ee bellard
        stl_phys(sm_state + offset + 8, dt->base);
1592 eaa728ee bellard
        stl_phys(sm_state + offset + 4, dt->limit);
1593 eaa728ee bellard
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1594 eaa728ee bellard
    }
1595 eaa728ee bellard
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1596 eaa728ee bellard
1597 eaa728ee bellard
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1598 eaa728ee bellard
    stl_phys(sm_state + 0x7ef8, env->smbase);
1599 eaa728ee bellard
#endif
1600 eaa728ee bellard
    /* init SMM cpu state */
1601 eaa728ee bellard
1602 eaa728ee bellard
#ifdef TARGET_X86_64
1603 5efc27bb bellard
    cpu_load_efer(env, 0);
1604 eaa728ee bellard
#endif
1605 997ff0d9 Blue Swirl
    cpu_load_eflags(env, 0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C |
1606 997ff0d9 Blue Swirl
                              DF_MASK));
1607 eaa728ee bellard
    env->eip = 0x00008000;
1608 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1609 eaa728ee bellard
                           0xffffffff, 0);
1610 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1611 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1612 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1613 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1614 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1615 eaa728ee bellard
1616 eaa728ee bellard
    cpu_x86_update_cr0(env,
1617 20054ef0 Blue Swirl
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK |
1618 20054ef0 Blue Swirl
                                      CR0_PG_MASK));
1619 eaa728ee bellard
    cpu_x86_update_cr4(env, 0);
1620 eaa728ee bellard
    env->dr[7] = 0x00000400;
1621 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
1622 e694d4e2 Blue Swirl
    env = saved_env;
1623 eaa728ee bellard
}
1624 eaa728ee bellard
1625 eaa728ee bellard
void helper_rsm(void)
1626 eaa728ee bellard
{
1627 eaa728ee bellard
    target_ulong sm_state;
1628 eaa728ee bellard
    int i, offset;
1629 eaa728ee bellard
    uint32_t val;
1630 eaa728ee bellard
1631 eaa728ee bellard
    sm_state = env->smbase + 0x8000;
1632 eaa728ee bellard
#ifdef TARGET_X86_64
1633 5efc27bb bellard
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1634 eaa728ee bellard
1635 20054ef0 Blue Swirl
    for (i = 0; i < 6; i++) {
1636 eaa728ee bellard
        offset = 0x7e00 + i * 16;
1637 eaa728ee bellard
        cpu_x86_load_seg_cache(env, i,
1638 eaa728ee bellard
                               lduw_phys(sm_state + offset),
1639 eaa728ee bellard
                               ldq_phys(sm_state + offset + 8),
1640 eaa728ee bellard
                               ldl_phys(sm_state + offset + 4),
1641 20054ef0 Blue Swirl
                               (lduw_phys(sm_state + offset + 2) &
1642 20054ef0 Blue Swirl
                                0xf0ff) << 8);
1643 eaa728ee bellard
    }
1644 eaa728ee bellard
1645 eaa728ee bellard
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1646 eaa728ee bellard
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1647 eaa728ee bellard
1648 eaa728ee bellard
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1649 eaa728ee bellard
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1650 eaa728ee bellard
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1651 eaa728ee bellard
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1652 eaa728ee bellard
1653 eaa728ee bellard
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1654 eaa728ee bellard
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1655 eaa728ee bellard
1656 eaa728ee bellard
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1657 eaa728ee bellard
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1658 eaa728ee bellard
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1659 eaa728ee bellard
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1660 eaa728ee bellard
1661 eaa728ee bellard
    EAX = ldq_phys(sm_state + 0x7ff8);
1662 eaa728ee bellard
    ECX = ldq_phys(sm_state + 0x7ff0);
1663 eaa728ee bellard
    EDX = ldq_phys(sm_state + 0x7fe8);
1664 eaa728ee bellard
    EBX = ldq_phys(sm_state + 0x7fe0);
1665 eaa728ee bellard
    ESP = ldq_phys(sm_state + 0x7fd8);
1666 eaa728ee bellard
    EBP = ldq_phys(sm_state + 0x7fd0);
1667 eaa728ee bellard
    ESI = ldq_phys(sm_state + 0x7fc8);
1668 eaa728ee bellard
    EDI = ldq_phys(sm_state + 0x7fc0);
1669 20054ef0 Blue Swirl
    for (i = 8; i < 16; i++) {
1670 eaa728ee bellard
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1671 20054ef0 Blue Swirl
    }
1672 eaa728ee bellard
    env->eip = ldq_phys(sm_state + 0x7f78);
1673 997ff0d9 Blue Swirl
    cpu_load_eflags(env, ldl_phys(sm_state + 0x7f70),
1674 997ff0d9 Blue Swirl
                    ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1675 eaa728ee bellard
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1676 eaa728ee bellard
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1677 eaa728ee bellard
1678 eaa728ee bellard
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1679 eaa728ee bellard
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1680 eaa728ee bellard
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1681 eaa728ee bellard
1682 eaa728ee bellard
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1683 eaa728ee bellard
    if (val & 0x20000) {
1684 eaa728ee bellard
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1685 eaa728ee bellard
    }
1686 eaa728ee bellard
#else
1687 eaa728ee bellard
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1688 eaa728ee bellard
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1689 997ff0d9 Blue Swirl
    cpu_load_eflags(env, ldl_phys(sm_state + 0x7ff4),
1690 997ff0d9 Blue Swirl
                    ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1691 eaa728ee bellard
    env->eip = ldl_phys(sm_state + 0x7ff0);
1692 eaa728ee bellard
    EDI = ldl_phys(sm_state + 0x7fec);
1693 eaa728ee bellard
    ESI = ldl_phys(sm_state + 0x7fe8);
1694 eaa728ee bellard
    EBP = ldl_phys(sm_state + 0x7fe4);
1695 eaa728ee bellard
    ESP = ldl_phys(sm_state + 0x7fe0);
1696 eaa728ee bellard
    EBX = ldl_phys(sm_state + 0x7fdc);
1697 eaa728ee bellard
    EDX = ldl_phys(sm_state + 0x7fd8);
1698 eaa728ee bellard
    ECX = ldl_phys(sm_state + 0x7fd4);
1699 eaa728ee bellard
    EAX = ldl_phys(sm_state + 0x7fd0);
1700 eaa728ee bellard
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1701 eaa728ee bellard
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1702 eaa728ee bellard
1703 eaa728ee bellard
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1704 eaa728ee bellard
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1705 eaa728ee bellard
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1706 eaa728ee bellard
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1707 eaa728ee bellard
1708 eaa728ee bellard
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1709 eaa728ee bellard
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1710 eaa728ee bellard
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1711 eaa728ee bellard
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1712 eaa728ee bellard
1713 eaa728ee bellard
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1714 eaa728ee bellard
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1715 eaa728ee bellard
1716 eaa728ee bellard
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1717 eaa728ee bellard
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1718 eaa728ee bellard
1719 20054ef0 Blue Swirl
    for (i = 0; i < 6; i++) {
1720 20054ef0 Blue Swirl
        if (i < 3) {
1721 eaa728ee bellard
            offset = 0x7f84 + i * 12;
1722 20054ef0 Blue Swirl
        } else {
1723 eaa728ee bellard
            offset = 0x7f2c + (i - 3) * 12;
1724 20054ef0 Blue Swirl
        }
1725 eaa728ee bellard
        cpu_x86_load_seg_cache(env, i,
1726 eaa728ee bellard
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1727 eaa728ee bellard
                               ldl_phys(sm_state + offset + 8),
1728 eaa728ee bellard
                               ldl_phys(sm_state + offset + 4),
1729 eaa728ee bellard
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1730 eaa728ee bellard
    }
1731 eaa728ee bellard
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1732 eaa728ee bellard
1733 eaa728ee bellard
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1734 eaa728ee bellard
    if (val & 0x20000) {
1735 eaa728ee bellard
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1736 eaa728ee bellard
    }
1737 eaa728ee bellard
#endif
1738 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
1739 eaa728ee bellard
    env->hflags &= ~HF_SMM_MASK;
1740 eaa728ee bellard
    cpu_smm_update(env);
1741 eaa728ee bellard
1742 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
1743 93fcfe39 aliguori
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1744 eaa728ee bellard
}
1745 eaa728ee bellard
1746 eaa728ee bellard
#endif /* !CONFIG_USER_ONLY */
1747 eaa728ee bellard
1748 eaa728ee bellard
1749 eaa728ee bellard
/* division, flags are undefined */
1750 eaa728ee bellard
1751 eaa728ee bellard
void helper_divb_AL(target_ulong t0)
1752 eaa728ee bellard
{
1753 eaa728ee bellard
    unsigned int num, den, q, r;
1754 eaa728ee bellard
1755 eaa728ee bellard
    num = (EAX & 0xffff);
1756 eaa728ee bellard
    den = (t0 & 0xff);
1757 eaa728ee bellard
    if (den == 0) {
1758 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1759 eaa728ee bellard
    }
1760 eaa728ee bellard
    q = (num / den);
1761 20054ef0 Blue Swirl
    if (q > 0xff) {
1762 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1763 20054ef0 Blue Swirl
    }
1764 eaa728ee bellard
    q &= 0xff;
1765 eaa728ee bellard
    r = (num % den) & 0xff;
1766 eaa728ee bellard
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1767 eaa728ee bellard
}
1768 eaa728ee bellard
1769 eaa728ee bellard
void helper_idivb_AL(target_ulong t0)
1770 eaa728ee bellard
{
1771 eaa728ee bellard
    int num, den, q, r;
1772 eaa728ee bellard
1773 eaa728ee bellard
    num = (int16_t)EAX;
1774 eaa728ee bellard
    den = (int8_t)t0;
1775 eaa728ee bellard
    if (den == 0) {
1776 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1777 eaa728ee bellard
    }
1778 eaa728ee bellard
    q = (num / den);
1779 20054ef0 Blue Swirl
    if (q != (int8_t)q) {
1780 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1781 20054ef0 Blue Swirl
    }
1782 eaa728ee bellard
    q &= 0xff;
1783 eaa728ee bellard
    r = (num % den) & 0xff;
1784 eaa728ee bellard
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1785 eaa728ee bellard
}
1786 eaa728ee bellard
1787 eaa728ee bellard
void helper_divw_AX(target_ulong t0)
1788 eaa728ee bellard
{
1789 eaa728ee bellard
    unsigned int num, den, q, r;
1790 eaa728ee bellard
1791 eaa728ee bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1792 eaa728ee bellard
    den = (t0 & 0xffff);
1793 eaa728ee bellard
    if (den == 0) {
1794 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1795 eaa728ee bellard
    }
1796 eaa728ee bellard
    q = (num / den);
1797 20054ef0 Blue Swirl
    if (q > 0xffff) {
1798 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1799 20054ef0 Blue Swirl
    }
1800 eaa728ee bellard
    q &= 0xffff;
1801 eaa728ee bellard
    r = (num % den) & 0xffff;
1802 eaa728ee bellard
    EAX = (EAX & ~0xffff) | q;
1803 eaa728ee bellard
    EDX = (EDX & ~0xffff) | r;
1804 eaa728ee bellard
}
1805 eaa728ee bellard
1806 eaa728ee bellard
void helper_idivw_AX(target_ulong t0)
1807 eaa728ee bellard
{
1808 eaa728ee bellard
    int num, den, q, r;
1809 eaa728ee bellard
1810 eaa728ee bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1811 eaa728ee bellard
    den = (int16_t)t0;
1812 eaa728ee bellard
    if (den == 0) {
1813 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1814 eaa728ee bellard
    }
1815 eaa728ee bellard
    q = (num / den);
1816 20054ef0 Blue Swirl
    if (q != (int16_t)q) {
1817 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1818 20054ef0 Blue Swirl
    }
1819 eaa728ee bellard
    q &= 0xffff;
1820 eaa728ee bellard
    r = (num % den) & 0xffff;
1821 eaa728ee bellard
    EAX = (EAX & ~0xffff) | q;
1822 eaa728ee bellard
    EDX = (EDX & ~0xffff) | r;
1823 eaa728ee bellard
}
1824 eaa728ee bellard
1825 eaa728ee bellard
void helper_divl_EAX(target_ulong t0)
1826 eaa728ee bellard
{
1827 eaa728ee bellard
    unsigned int den, r;
1828 eaa728ee bellard
    uint64_t num, q;
1829 eaa728ee bellard
1830 eaa728ee bellard
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1831 eaa728ee bellard
    den = t0;
1832 eaa728ee bellard
    if (den == 0) {
1833 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1834 eaa728ee bellard
    }
1835 eaa728ee bellard
    q = (num / den);
1836 eaa728ee bellard
    r = (num % den);
1837 20054ef0 Blue Swirl
    if (q > 0xffffffff) {
1838 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1839 20054ef0 Blue Swirl
    }
1840 eaa728ee bellard
    EAX = (uint32_t)q;
1841 eaa728ee bellard
    EDX = (uint32_t)r;
1842 eaa728ee bellard
}
1843 eaa728ee bellard
1844 eaa728ee bellard
void helper_idivl_EAX(target_ulong t0)
1845 eaa728ee bellard
{
1846 eaa728ee bellard
    int den, r;
1847 eaa728ee bellard
    int64_t num, q;
1848 eaa728ee bellard
1849 eaa728ee bellard
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1850 eaa728ee bellard
    den = t0;
1851 eaa728ee bellard
    if (den == 0) {
1852 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1853 eaa728ee bellard
    }
1854 eaa728ee bellard
    q = (num / den);
1855 eaa728ee bellard
    r = (num % den);
1856 20054ef0 Blue Swirl
    if (q != (int32_t)q) {
1857 77b2bc2c Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
1858 20054ef0 Blue Swirl
    }
1859 eaa728ee bellard
    EAX = (uint32_t)q;
1860 eaa728ee bellard
    EDX = (uint32_t)r;
1861 eaa728ee bellard
}
1862 eaa728ee bellard
1863 eaa728ee bellard
/* bcd */
1864 eaa728ee bellard
1865 eaa728ee bellard
/* XXX: exception */
1866 eaa728ee bellard
void helper_aam(int base)
1867 eaa728ee bellard
{
1868 eaa728ee bellard
    int al, ah;
1869 20054ef0 Blue Swirl
1870 eaa728ee bellard
    al = EAX & 0xff;
1871 eaa728ee bellard
    ah = al / base;
1872 eaa728ee bellard
    al = al % base;
1873 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1874 eaa728ee bellard
    CC_DST = al;
1875 eaa728ee bellard
}
1876 eaa728ee bellard
1877 eaa728ee bellard
void helper_aad(int base)
1878 eaa728ee bellard
{
1879 eaa728ee bellard
    int al, ah;
1880 20054ef0 Blue Swirl
1881 eaa728ee bellard
    al = EAX & 0xff;
1882 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1883 eaa728ee bellard
    al = ((ah * base) + al) & 0xff;
1884 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al;
1885 eaa728ee bellard
    CC_DST = al;
1886 eaa728ee bellard
}
1887 eaa728ee bellard
1888 eaa728ee bellard
void helper_aaa(void)
1889 eaa728ee bellard
{
1890 eaa728ee bellard
    int icarry;
1891 eaa728ee bellard
    int al, ah, af;
1892 eaa728ee bellard
    int eflags;
1893 eaa728ee bellard
1894 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1895 eaa728ee bellard
    af = eflags & CC_A;
1896 eaa728ee bellard
    al = EAX & 0xff;
1897 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1898 eaa728ee bellard
1899 eaa728ee bellard
    icarry = (al > 0xf9);
1900 20054ef0 Blue Swirl
    if (((al & 0x0f) > 9) || af) {
1901 eaa728ee bellard
        al = (al + 6) & 0x0f;
1902 eaa728ee bellard
        ah = (ah + 1 + icarry) & 0xff;
1903 eaa728ee bellard
        eflags |= CC_C | CC_A;
1904 eaa728ee bellard
    } else {
1905 eaa728ee bellard
        eflags &= ~(CC_C | CC_A);
1906 eaa728ee bellard
        al &= 0x0f;
1907 eaa728ee bellard
    }
1908 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1909 eaa728ee bellard
    CC_SRC = eflags;
1910 eaa728ee bellard
}
1911 eaa728ee bellard
1912 eaa728ee bellard
void helper_aas(void)
1913 eaa728ee bellard
{
1914 eaa728ee bellard
    int icarry;
1915 eaa728ee bellard
    int al, ah, af;
1916 eaa728ee bellard
    int eflags;
1917 eaa728ee bellard
1918 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1919 eaa728ee bellard
    af = eflags & CC_A;
1920 eaa728ee bellard
    al = EAX & 0xff;
1921 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1922 eaa728ee bellard
1923 eaa728ee bellard
    icarry = (al < 6);
1924 20054ef0 Blue Swirl
    if (((al & 0x0f) > 9) || af) {
1925 eaa728ee bellard
        al = (al - 6) & 0x0f;
1926 eaa728ee bellard
        ah = (ah - 1 - icarry) & 0xff;
1927 eaa728ee bellard
        eflags |= CC_C | CC_A;
1928 eaa728ee bellard
    } else {
1929 eaa728ee bellard
        eflags &= ~(CC_C | CC_A);
1930 eaa728ee bellard
        al &= 0x0f;
1931 eaa728ee bellard
    }
1932 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1933 eaa728ee bellard
    CC_SRC = eflags;
1934 eaa728ee bellard
}
1935 eaa728ee bellard
1936 eaa728ee bellard
void helper_daa(void)
1937 eaa728ee bellard
{
1938 c6bfc164 Boris Figovsky
    int old_al, al, af, cf;
1939 eaa728ee bellard
    int eflags;
1940 eaa728ee bellard
1941 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1942 eaa728ee bellard
    cf = eflags & CC_C;
1943 eaa728ee bellard
    af = eflags & CC_A;
1944 c6bfc164 Boris Figovsky
    old_al = al = EAX & 0xff;
1945 eaa728ee bellard
1946 eaa728ee bellard
    eflags = 0;
1947 20054ef0 Blue Swirl
    if (((al & 0x0f) > 9) || af) {
1948 eaa728ee bellard
        al = (al + 6) & 0xff;
1949 eaa728ee bellard
        eflags |= CC_A;
1950 eaa728ee bellard
    }
1951 c6bfc164 Boris Figovsky
    if ((old_al > 0x99) || cf) {
1952 eaa728ee bellard
        al = (al + 0x60) & 0xff;
1953 eaa728ee bellard
        eflags |= CC_C;
1954 eaa728ee bellard
    }
1955 eaa728ee bellard
    EAX = (EAX & ~0xff) | al;
1956 eaa728ee bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1957 eaa728ee bellard
    eflags |= (al == 0) << 6; /* zf */
1958 eaa728ee bellard
    eflags |= parity_table[al]; /* pf */
1959 eaa728ee bellard
    eflags |= (al & 0x80); /* sf */
1960 eaa728ee bellard
    CC_SRC = eflags;
1961 eaa728ee bellard
}
1962 eaa728ee bellard
1963 eaa728ee bellard
void helper_das(void)
1964 eaa728ee bellard
{
1965 eaa728ee bellard
    int al, al1, af, cf;
1966 eaa728ee bellard
    int eflags;
1967 eaa728ee bellard
1968 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1969 eaa728ee bellard
    cf = eflags & CC_C;
1970 eaa728ee bellard
    af = eflags & CC_A;
1971 eaa728ee bellard
    al = EAX & 0xff;
1972 eaa728ee bellard
1973 eaa728ee bellard
    eflags = 0;
1974 eaa728ee bellard
    al1 = al;
1975 20054ef0 Blue Swirl
    if (((al & 0x0f) > 9) || af) {
1976 eaa728ee bellard
        eflags |= CC_A;
1977 20054ef0 Blue Swirl
        if (al < 6 || cf) {
1978 eaa728ee bellard
            eflags |= CC_C;
1979 20054ef0 Blue Swirl
        }
1980 eaa728ee bellard
        al = (al - 6) & 0xff;
1981 eaa728ee bellard
    }
1982 eaa728ee bellard
    if ((al1 > 0x99) || cf) {
1983 eaa728ee bellard
        al = (al - 0x60) & 0xff;
1984 eaa728ee bellard
        eflags |= CC_C;
1985 eaa728ee bellard
    }
1986 eaa728ee bellard
    EAX = (EAX & ~0xff) | al;
1987 eaa728ee bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1988 eaa728ee bellard
    eflags |= (al == 0) << 6; /* zf */
1989 eaa728ee bellard
    eflags |= parity_table[al]; /* pf */
1990 eaa728ee bellard
    eflags |= (al & 0x80); /* sf */
1991 eaa728ee bellard
    CC_SRC = eflags;
1992 eaa728ee bellard
}
1993 eaa728ee bellard
1994 eaa728ee bellard
void helper_into(int next_eip_addend)
1995 eaa728ee bellard
{
1996 eaa728ee bellard
    int eflags;
1997 20054ef0 Blue Swirl
1998 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1999 eaa728ee bellard
    if (eflags & CC_O) {
2000 77b2bc2c Blue Swirl
        raise_interrupt(env, EXCP04_INTO, 1, 0, next_eip_addend);
2001 eaa728ee bellard
    }
2002 eaa728ee bellard
}
2003 eaa728ee bellard
2004 eaa728ee bellard
void helper_cmpxchg8b(target_ulong a0)
2005 eaa728ee bellard
{
2006 eaa728ee bellard
    uint64_t d;
2007 eaa728ee bellard
    int eflags;
2008 eaa728ee bellard
2009 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
2010 eaa728ee bellard
    d = ldq(a0);
2011 eaa728ee bellard
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
2012 eaa728ee bellard
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
2013 eaa728ee bellard
        eflags |= CC_Z;
2014 eaa728ee bellard
    } else {
2015 278ed7c3 bellard
        /* always do the store */
2016 20054ef0 Blue Swirl
        stq(a0, d);
2017 eaa728ee bellard
        EDX = (uint32_t)(d >> 32);
2018 eaa728ee bellard
        EAX = (uint32_t)d;
2019 eaa728ee bellard
        eflags &= ~CC_Z;
2020 eaa728ee bellard
    }
2021 eaa728ee bellard
    CC_SRC = eflags;
2022 eaa728ee bellard
}
2023 eaa728ee bellard
2024 eaa728ee bellard
#ifdef TARGET_X86_64
2025 eaa728ee bellard
void helper_cmpxchg16b(target_ulong a0)
2026 eaa728ee bellard
{
2027 eaa728ee bellard
    uint64_t d0, d1;
2028 eaa728ee bellard
    int eflags;
2029 eaa728ee bellard
2030 20054ef0 Blue Swirl
    if ((a0 & 0xf) != 0) {
2031 77b2bc2c Blue Swirl
        raise_exception(env, EXCP0D_GPF);
2032 20054ef0 Blue Swirl
    }
2033 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
2034 eaa728ee bellard
    d0 = ldq(a0);
2035 eaa728ee bellard
    d1 = ldq(a0 + 8);
2036 eaa728ee bellard
    if (d0 == EAX && d1 == EDX) {
2037 eaa728ee bellard
        stq(a0, EBX);
2038 eaa728ee bellard
        stq(a0 + 8, ECX);
2039 eaa728ee bellard
        eflags |= CC_Z;
2040 eaa728ee bellard
    } else {
2041 278ed7c3 bellard
        /* always do the store */
2042 20054ef0 Blue Swirl
        stq(a0, d0);
2043 20054ef0 Blue Swirl
        stq(a0 + 8, d1);
2044 eaa728ee bellard
        EDX = d1;
2045 eaa728ee bellard
        EAX = d0;
2046 eaa728ee bellard
        eflags &= ~CC_Z;
2047 eaa728ee bellard
    }
2048 eaa728ee bellard
    CC_SRC = eflags;
2049 eaa728ee bellard
}
2050 eaa728ee bellard
#endif
2051 eaa728ee bellard
2052 eaa728ee bellard
void helper_single_step(void)
2053 eaa728ee bellard
{
2054 01df040b aliguori
#ifndef CONFIG_USER_ONLY
2055 01df040b aliguori
    check_hw_breakpoints(env, 1);
2056 01df040b aliguori
    env->dr[6] |= DR6_BS;
2057 01df040b aliguori
#endif
2058 77b2bc2c Blue Swirl
    raise_exception(env, EXCP01_DB);
2059 eaa728ee bellard
}
2060 eaa728ee bellard
2061 eaa728ee bellard
void helper_cpuid(void)
2062 eaa728ee bellard
{
2063 6fd805e1 aliguori
    uint32_t eax, ebx, ecx, edx;
2064 eaa728ee bellard
2065 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
2066 e737b32a balrog
2067 e00b6f80 aliguori
    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
2068 6fd805e1 aliguori
    EAX = eax;
2069 6fd805e1 aliguori
    EBX = ebx;
2070 6fd805e1 aliguori
    ECX = ecx;
2071 6fd805e1 aliguori
    EDX = edx;
2072 eaa728ee bellard
}
2073 eaa728ee bellard
2074 eaa728ee bellard
void helper_enter_level(int level, int data32, target_ulong t1)
2075 eaa728ee bellard
{
2076 eaa728ee bellard
    target_ulong ssp;
2077 eaa728ee bellard
    uint32_t esp_mask, esp, ebp;
2078 eaa728ee bellard
2079 eaa728ee bellard
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2080 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2081 eaa728ee bellard
    ebp = EBP;
2082 eaa728ee bellard
    esp = ESP;
2083 eaa728ee bellard
    if (data32) {
2084 eaa728ee bellard
        /* 32 bit */
2085 eaa728ee bellard
        esp -= 4;
2086 eaa728ee bellard
        while (--level) {
2087 eaa728ee bellard
            esp -= 4;
2088 eaa728ee bellard
            ebp -= 4;
2089 eaa728ee bellard
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
2090 eaa728ee bellard
        }
2091 eaa728ee bellard
        esp -= 4;
2092 eaa728ee bellard
        stl(ssp + (esp & esp_mask), t1);
2093 eaa728ee bellard
    } else {
2094 eaa728ee bellard
        /* 16 bit */
2095 eaa728ee bellard
        esp -= 2;
2096 eaa728ee bellard
        while (--level) {
2097 eaa728ee bellard
            esp -= 2;
2098 eaa728ee bellard
            ebp -= 2;
2099 eaa728ee bellard
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
2100 eaa728ee bellard
        }
2101 eaa728ee bellard
        esp -= 2;
2102 eaa728ee bellard
        stw(ssp + (esp & esp_mask), t1);
2103 eaa728ee bellard
    }
2104 eaa728ee bellard
}
2105 eaa728ee bellard
2106 eaa728ee bellard
#ifdef TARGET_X86_64
2107 eaa728ee bellard
void helper_enter64_level(int level, int data64, target_ulong t1)
2108 eaa728ee bellard
{
2109 eaa728ee bellard
    target_ulong esp, ebp;
2110 20054ef0 Blue Swirl
2111 eaa728ee bellard
    ebp = EBP;
2112 eaa728ee bellard
    esp = ESP;
2113 eaa728ee bellard
2114 eaa728ee bellard
    if (data64) {
2115 eaa728ee bellard
        /* 64 bit */
2116 eaa728ee bellard
        esp -= 8;
2117 eaa728ee bellard
        while (--level) {
2118 eaa728ee bellard
            esp -= 8;
2119 eaa728ee bellard
            ebp -= 8;
2120 eaa728ee bellard
            stq(esp, ldq(ebp));
2121 eaa728ee bellard
        }
2122 eaa728ee bellard
        esp -= 8;
2123 eaa728ee bellard
        stq(esp, t1);
2124 eaa728ee bellard
    } else {
2125 eaa728ee bellard
        /* 16 bit */
2126 eaa728ee bellard
        esp -= 2;
2127 eaa728ee bellard
        while (--level) {
2128 eaa728ee bellard
            esp -= 2;
2129 eaa728ee bellard
            ebp -= 2;
2130 eaa728ee bellard
            stw(esp, lduw(ebp));
2131 eaa728ee bellard
        }
2132 eaa728ee bellard
        esp -= 2;
2133 eaa728ee bellard
        stw(esp, t1);
2134 eaa728ee bellard
    }
2135 eaa728ee bellard
}
2136 eaa728ee bellard
#endif
2137 eaa728ee bellard
2138 eaa728ee bellard
void helper_lldt(int selector)
2139 eaa728ee bellard
{
2140 eaa728ee bellard
    SegmentCache *dt;
2141 eaa728ee bellard
    uint32_t e1, e2;
2142 eaa728ee bellard
    int index, entry_limit;
2143 eaa728ee bellard
    target_ulong ptr;
2144 eaa728ee bellard
2145 eaa728ee bellard
    selector &= 0xffff;
2146 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2147 eaa728ee bellard
        /* XXX: NULL selector case: invalid LDT */
2148 eaa728ee bellard
        env->ldt.base = 0;
2149 eaa728ee bellard
        env->ldt.limit = 0;
2150 eaa728ee bellard
    } else {
2151 20054ef0 Blue Swirl
        if (selector & 0x4) {
2152 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2153 20054ef0 Blue Swirl
        }
2154 eaa728ee bellard
        dt = &env->gdt;
2155 eaa728ee bellard
        index = selector & ~7;
2156 eaa728ee bellard
#ifdef TARGET_X86_64
2157 20054ef0 Blue Swirl
        if (env->hflags & HF_LMA_MASK) {
2158 eaa728ee bellard
            entry_limit = 15;
2159 20054ef0 Blue Swirl
        } else
2160 eaa728ee bellard
#endif
2161 20054ef0 Blue Swirl
        {
2162 eaa728ee bellard
            entry_limit = 7;
2163 20054ef0 Blue Swirl
        }
2164 20054ef0 Blue Swirl
        if ((index + entry_limit) > dt->limit) {
2165 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2166 20054ef0 Blue Swirl
        }
2167 eaa728ee bellard
        ptr = dt->base + index;
2168 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2169 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2170 20054ef0 Blue Swirl
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) {
2171 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2172 20054ef0 Blue Swirl
        }
2173 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
2174 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
2175 20054ef0 Blue Swirl
        }
2176 eaa728ee bellard
#ifdef TARGET_X86_64
2177 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
2178 eaa728ee bellard
            uint32_t e3;
2179 20054ef0 Blue Swirl
2180 eaa728ee bellard
            e3 = ldl_kernel(ptr + 8);
2181 eaa728ee bellard
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2182 eaa728ee bellard
            env->ldt.base |= (target_ulong)e3 << 32;
2183 eaa728ee bellard
        } else
2184 eaa728ee bellard
#endif
2185 eaa728ee bellard
        {
2186 eaa728ee bellard
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2187 eaa728ee bellard
        }
2188 eaa728ee bellard
    }
2189 eaa728ee bellard
    env->ldt.selector = selector;
2190 eaa728ee bellard
}
2191 eaa728ee bellard
2192 eaa728ee bellard
void helper_ltr(int selector)
2193 eaa728ee bellard
{
2194 eaa728ee bellard
    SegmentCache *dt;
2195 eaa728ee bellard
    uint32_t e1, e2;
2196 eaa728ee bellard
    int index, type, entry_limit;
2197 eaa728ee bellard
    target_ulong ptr;
2198 eaa728ee bellard
2199 eaa728ee bellard
    selector &= 0xffff;
2200 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2201 eaa728ee bellard
        /* NULL selector case: invalid TR */
2202 eaa728ee bellard
        env->tr.base = 0;
2203 eaa728ee bellard
        env->tr.limit = 0;
2204 eaa728ee bellard
        env->tr.flags = 0;
2205 eaa728ee bellard
    } else {
2206 20054ef0 Blue Swirl
        if (selector & 0x4) {
2207 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2208 20054ef0 Blue Swirl
        }
2209 eaa728ee bellard
        dt = &env->gdt;
2210 eaa728ee bellard
        index = selector & ~7;
2211 eaa728ee bellard
#ifdef TARGET_X86_64
2212 20054ef0 Blue Swirl
        if (env->hflags & HF_LMA_MASK) {
2213 eaa728ee bellard
            entry_limit = 15;
2214 20054ef0 Blue Swirl
        } else
2215 eaa728ee bellard
#endif
2216 20054ef0 Blue Swirl
        {
2217 eaa728ee bellard
            entry_limit = 7;
2218 20054ef0 Blue Swirl
        }
2219 20054ef0 Blue Swirl
        if ((index + entry_limit) > dt->limit) {
2220 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2221 20054ef0 Blue Swirl
        }
2222 eaa728ee bellard
        ptr = dt->base + index;
2223 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2224 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2225 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2226 eaa728ee bellard
        if ((e2 & DESC_S_MASK) ||
2227 20054ef0 Blue Swirl
            (type != 1 && type != 9)) {
2228 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2229 20054ef0 Blue Swirl
        }
2230 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
2231 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
2232 20054ef0 Blue Swirl
        }
2233 eaa728ee bellard
#ifdef TARGET_X86_64
2234 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
2235 eaa728ee bellard
            uint32_t e3, e4;
2236 20054ef0 Blue Swirl
2237 eaa728ee bellard
            e3 = ldl_kernel(ptr + 8);
2238 eaa728ee bellard
            e4 = ldl_kernel(ptr + 12);
2239 20054ef0 Blue Swirl
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf) {
2240 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2241 20054ef0 Blue Swirl
            }
2242 eaa728ee bellard
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2243 eaa728ee bellard
            env->tr.base |= (target_ulong)e3 << 32;
2244 eaa728ee bellard
        } else
2245 eaa728ee bellard
#endif
2246 eaa728ee bellard
        {
2247 eaa728ee bellard
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2248 eaa728ee bellard
        }
2249 eaa728ee bellard
        e2 |= DESC_TSS_BUSY_MASK;
2250 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
2251 eaa728ee bellard
    }
2252 eaa728ee bellard
    env->tr.selector = selector;
2253 eaa728ee bellard
}
2254 eaa728ee bellard
2255 eaa728ee bellard
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2256 eaa728ee bellard
void helper_load_seg(int seg_reg, int selector)
2257 eaa728ee bellard
{
2258 eaa728ee bellard
    uint32_t e1, e2;
2259 eaa728ee bellard
    int cpl, dpl, rpl;
2260 eaa728ee bellard
    SegmentCache *dt;
2261 eaa728ee bellard
    int index;
2262 eaa728ee bellard
    target_ulong ptr;
2263 eaa728ee bellard
2264 eaa728ee bellard
    selector &= 0xffff;
2265 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2266 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2267 eaa728ee bellard
        /* null selector case */
2268 eaa728ee bellard
        if (seg_reg == R_SS
2269 eaa728ee bellard
#ifdef TARGET_X86_64
2270 eaa728ee bellard
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2271 eaa728ee bellard
#endif
2272 20054ef0 Blue Swirl
            ) {
2273 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, 0);
2274 20054ef0 Blue Swirl
        }
2275 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2276 eaa728ee bellard
    } else {
2277 eaa728ee bellard
2278 20054ef0 Blue Swirl
        if (selector & 0x4) {
2279 eaa728ee bellard
            dt = &env->ldt;
2280 20054ef0 Blue Swirl
        } else {
2281 eaa728ee bellard
            dt = &env->gdt;
2282 20054ef0 Blue Swirl
        }
2283 eaa728ee bellard
        index = selector & ~7;
2284 20054ef0 Blue Swirl
        if ((index + 7) > dt->limit) {
2285 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2286 20054ef0 Blue Swirl
        }
2287 eaa728ee bellard
        ptr = dt->base + index;
2288 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2289 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2290 eaa728ee bellard
2291 20054ef0 Blue Swirl
        if (!(e2 & DESC_S_MASK)) {
2292 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2293 20054ef0 Blue Swirl
        }
2294 eaa728ee bellard
        rpl = selector & 3;
2295 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2296 eaa728ee bellard
        if (seg_reg == R_SS) {
2297 eaa728ee bellard
            /* must be writable segment */
2298 20054ef0 Blue Swirl
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) {
2299 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2300 20054ef0 Blue Swirl
            }
2301 20054ef0 Blue Swirl
            if (rpl != cpl || dpl != cpl) {
2302 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2303 20054ef0 Blue Swirl
            }
2304 eaa728ee bellard
        } else {
2305 eaa728ee bellard
            /* must be readable segment */
2306 20054ef0 Blue Swirl
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
2307 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2308 20054ef0 Blue Swirl
            }
2309 eaa728ee bellard
2310 eaa728ee bellard
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2311 eaa728ee bellard
                /* if not conforming code, test rights */
2312 20054ef0 Blue Swirl
                if (dpl < cpl || dpl < rpl) {
2313 77b2bc2c Blue Swirl
                    raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2314 20054ef0 Blue Swirl
                }
2315 eaa728ee bellard
            }
2316 eaa728ee bellard
        }
2317 eaa728ee bellard
2318 eaa728ee bellard
        if (!(e2 & DESC_P_MASK)) {
2319 20054ef0 Blue Swirl
            if (seg_reg == R_SS) {
2320 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0C_STACK, selector & 0xfffc);
2321 20054ef0 Blue Swirl
            } else {
2322 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
2323 20054ef0 Blue Swirl
            }
2324 eaa728ee bellard
        }
2325 eaa728ee bellard
2326 eaa728ee bellard
        /* set the access bit if not already set */
2327 eaa728ee bellard
        if (!(e2 & DESC_A_MASK)) {
2328 eaa728ee bellard
            e2 |= DESC_A_MASK;
2329 eaa728ee bellard
            stl_kernel(ptr + 4, e2);
2330 eaa728ee bellard
        }
2331 eaa728ee bellard
2332 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2333 eaa728ee bellard
                       get_seg_base(e1, e2),
2334 eaa728ee bellard
                       get_seg_limit(e1, e2),
2335 eaa728ee bellard
                       e2);
2336 eaa728ee bellard
#if 0
2337 93fcfe39 aliguori
        qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2338 eaa728ee bellard
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2339 eaa728ee bellard
#endif
2340 eaa728ee bellard
    }
2341 eaa728ee bellard
}
2342 eaa728ee bellard
2343 eaa728ee bellard
/* protected mode jump */
2344 eaa728ee bellard
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2345 eaa728ee bellard
                           int next_eip_addend)
2346 eaa728ee bellard
{
2347 eaa728ee bellard
    int gate_cs, type;
2348 eaa728ee bellard
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2349 eaa728ee bellard
    target_ulong next_eip;
2350 eaa728ee bellard
2351 20054ef0 Blue Swirl
    if ((new_cs & 0xfffc) == 0) {
2352 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
2353 20054ef0 Blue Swirl
    }
2354 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, new_cs) != 0) {
2355 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2356 20054ef0 Blue Swirl
    }
2357 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2358 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
2359 20054ef0 Blue Swirl
        if (!(e2 & DESC_CS_MASK)) {
2360 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2361 20054ef0 Blue Swirl
        }
2362 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2363 eaa728ee bellard
        if (e2 & DESC_C_MASK) {
2364 eaa728ee bellard
            /* conforming code segment */
2365 20054ef0 Blue Swirl
            if (dpl > cpl) {
2366 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2367 20054ef0 Blue Swirl
            }
2368 eaa728ee bellard
        } else {
2369 eaa728ee bellard
            /* non conforming code segment */
2370 eaa728ee bellard
            rpl = new_cs & 3;
2371 20054ef0 Blue Swirl
            if (rpl > cpl) {
2372 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2373 20054ef0 Blue Swirl
            }
2374 20054ef0 Blue Swirl
            if (dpl != cpl) {
2375 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2376 20054ef0 Blue Swirl
            }
2377 eaa728ee bellard
        }
2378 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
2379 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc);
2380 20054ef0 Blue Swirl
        }
2381 eaa728ee bellard
        limit = get_seg_limit(e1, e2);
2382 eaa728ee bellard
        if (new_eip > limit &&
2383 20054ef0 Blue Swirl
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK)) {
2384 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2385 20054ef0 Blue Swirl
        }
2386 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2387 eaa728ee bellard
                       get_seg_base(e1, e2), limit, e2);
2388 eaa728ee bellard
        EIP = new_eip;
2389 eaa728ee bellard
    } else {
2390 eaa728ee bellard
        /* jump to call or task gate */
2391 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2392 eaa728ee bellard
        rpl = new_cs & 3;
2393 eaa728ee bellard
        cpl = env->hflags & HF_CPL_MASK;
2394 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2395 20054ef0 Blue Swirl
        switch (type) {
2396 eaa728ee bellard
        case 1: /* 286 TSS */
2397 eaa728ee bellard
        case 9: /* 386 TSS */
2398 eaa728ee bellard
        case 5: /* task gate */
2399 20054ef0 Blue Swirl
            if (dpl < cpl || dpl < rpl) {
2400 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2401 20054ef0 Blue Swirl
            }
2402 eaa728ee bellard
            next_eip = env->eip + next_eip_addend;
2403 eaa728ee bellard
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2404 eaa728ee bellard
            CC_OP = CC_OP_EFLAGS;
2405 eaa728ee bellard
            break;
2406 eaa728ee bellard
        case 4: /* 286 call gate */
2407 eaa728ee bellard
        case 12: /* 386 call gate */
2408 20054ef0 Blue Swirl
            if ((dpl < cpl) || (dpl < rpl)) {
2409 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2410 20054ef0 Blue Swirl
            }
2411 20054ef0 Blue Swirl
            if (!(e2 & DESC_P_MASK)) {
2412 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc);
2413 20054ef0 Blue Swirl
            }
2414 eaa728ee bellard
            gate_cs = e1 >> 16;
2415 eaa728ee bellard
            new_eip = (e1 & 0xffff);
2416 20054ef0 Blue Swirl
            if (type == 12) {
2417 eaa728ee bellard
                new_eip |= (e2 & 0xffff0000);
2418 20054ef0 Blue Swirl
            }
2419 20054ef0 Blue Swirl
            if (load_segment(&e1, &e2, gate_cs) != 0) {
2420 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc);
2421 20054ef0 Blue Swirl
            }
2422 eaa728ee bellard
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2423 eaa728ee bellard
            /* must be code segment */
2424 eaa728ee bellard
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2425 20054ef0 Blue Swirl
                 (DESC_S_MASK | DESC_CS_MASK))) {
2426 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc);
2427 20054ef0 Blue Swirl
            }
2428 eaa728ee bellard
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2429 20054ef0 Blue Swirl
                (!(e2 & DESC_C_MASK) && (dpl != cpl))) {
2430 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc);
2431 20054ef0 Blue Swirl
            }
2432 20054ef0 Blue Swirl
            if (!(e2 & DESC_P_MASK)) {
2433 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, gate_cs & 0xfffc);
2434 20054ef0 Blue Swirl
            }
2435 eaa728ee bellard
            limit = get_seg_limit(e1, e2);
2436 20054ef0 Blue Swirl
            if (new_eip > limit) {
2437 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, 0);
2438 20054ef0 Blue Swirl
            }
2439 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2440 eaa728ee bellard
                                   get_seg_base(e1, e2), limit, e2);
2441 eaa728ee bellard
            EIP = new_eip;
2442 eaa728ee bellard
            break;
2443 eaa728ee bellard
        default:
2444 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2445 eaa728ee bellard
            break;
2446 eaa728ee bellard
        }
2447 eaa728ee bellard
    }
2448 eaa728ee bellard
}
2449 eaa728ee bellard
2450 eaa728ee bellard
/* real mode call */
2451 eaa728ee bellard
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2452 eaa728ee bellard
                       int shift, int next_eip)
2453 eaa728ee bellard
{
2454 eaa728ee bellard
    int new_eip;
2455 eaa728ee bellard
    uint32_t esp, esp_mask;
2456 eaa728ee bellard
    target_ulong ssp;
2457 eaa728ee bellard
2458 eaa728ee bellard
    new_eip = new_eip1;
2459 eaa728ee bellard
    esp = ESP;
2460 eaa728ee bellard
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2461 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2462 eaa728ee bellard
    if (shift) {
2463 eaa728ee bellard
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2464 eaa728ee bellard
        PUSHL(ssp, esp, esp_mask, next_eip);
2465 eaa728ee bellard
    } else {
2466 eaa728ee bellard
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2467 eaa728ee bellard
        PUSHW(ssp, esp, esp_mask, next_eip);
2468 eaa728ee bellard
    }
2469 eaa728ee bellard
2470 eaa728ee bellard
    SET_ESP(esp, esp_mask);
2471 eaa728ee bellard
    env->eip = new_eip;
2472 eaa728ee bellard
    env->segs[R_CS].selector = new_cs;
2473 eaa728ee bellard
    env->segs[R_CS].base = (new_cs << 4);
2474 eaa728ee bellard
}
2475 eaa728ee bellard
2476 eaa728ee bellard
/* protected mode call */
2477 20054ef0 Blue Swirl
void helper_lcall_protected(int new_cs, target_ulong new_eip,
2478 eaa728ee bellard
                            int shift, int next_eip_addend)
2479 eaa728ee bellard
{
2480 eaa728ee bellard
    int new_stack, i;
2481 eaa728ee bellard
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2482 1c918eba blueswir1
    uint32_t ss = 0, ss_e1 = 0, ss_e2 = 0, sp, type, ss_dpl, sp_mask;
2483 eaa728ee bellard
    uint32_t val, limit, old_sp_mask;
2484 eaa728ee bellard
    target_ulong ssp, old_ssp, next_eip;
2485 eaa728ee bellard
2486 eaa728ee bellard
    next_eip = env->eip + next_eip_addend;
2487 d12d51d5 aliguori
    LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
2488 d12d51d5 aliguori
    LOG_PCALL_STATE(env);
2489 20054ef0 Blue Swirl
    if ((new_cs & 0xfffc) == 0) {
2490 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
2491 20054ef0 Blue Swirl
    }
2492 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, new_cs) != 0) {
2493 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2494 20054ef0 Blue Swirl
    }
2495 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2496 d12d51d5 aliguori
    LOG_PCALL("desc=%08x:%08x\n", e1, e2);
2497 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
2498 20054ef0 Blue Swirl
        if (!(e2 & DESC_CS_MASK)) {
2499 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2500 20054ef0 Blue Swirl
        }
2501 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2502 eaa728ee bellard
        if (e2 & DESC_C_MASK) {
2503 eaa728ee bellard
            /* conforming code segment */
2504 20054ef0 Blue Swirl
            if (dpl > cpl) {
2505 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2506 20054ef0 Blue Swirl
            }
2507 eaa728ee bellard
        } else {
2508 eaa728ee bellard
            /* non conforming code segment */
2509 eaa728ee bellard
            rpl = new_cs & 3;
2510 20054ef0 Blue Swirl
            if (rpl > cpl) {
2511 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2512 20054ef0 Blue Swirl
            }
2513 20054ef0 Blue Swirl
            if (dpl != cpl) {
2514 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2515 20054ef0 Blue Swirl
            }
2516 eaa728ee bellard
        }
2517 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
2518 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc);
2519 20054ef0 Blue Swirl
        }
2520 eaa728ee bellard
2521 eaa728ee bellard
#ifdef TARGET_X86_64
2522 eaa728ee bellard
        /* XXX: check 16/32 bit cases in long mode */
2523 eaa728ee bellard
        if (shift == 2) {
2524 eaa728ee bellard
            target_ulong rsp;
2525 20054ef0 Blue Swirl
2526 eaa728ee bellard
            /* 64 bit case */
2527 eaa728ee bellard
            rsp = ESP;
2528 eaa728ee bellard
            PUSHQ(rsp, env->segs[R_CS].selector);
2529 eaa728ee bellard
            PUSHQ(rsp, next_eip);
2530 eaa728ee bellard
            /* from this point, not restartable */
2531 eaa728ee bellard
            ESP = rsp;
2532 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2533 eaa728ee bellard
                                   get_seg_base(e1, e2),
2534 eaa728ee bellard
                                   get_seg_limit(e1, e2), e2);
2535 eaa728ee bellard
            EIP = new_eip;
2536 eaa728ee bellard
        } else
2537 eaa728ee bellard
#endif
2538 eaa728ee bellard
        {
2539 eaa728ee bellard
            sp = ESP;
2540 eaa728ee bellard
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2541 eaa728ee bellard
            ssp = env->segs[R_SS].base;
2542 eaa728ee bellard
            if (shift) {
2543 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2544 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, next_eip);
2545 eaa728ee bellard
            } else {
2546 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2547 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, next_eip);
2548 eaa728ee bellard
            }
2549 eaa728ee bellard
2550 eaa728ee bellard
            limit = get_seg_limit(e1, e2);
2551 20054ef0 Blue Swirl
            if (new_eip > limit) {
2552 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2553 20054ef0 Blue Swirl
            }
2554 eaa728ee bellard
            /* from this point, not restartable */
2555 eaa728ee bellard
            SET_ESP(sp, sp_mask);
2556 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2557 eaa728ee bellard
                                   get_seg_base(e1, e2), limit, e2);
2558 eaa728ee bellard
            EIP = new_eip;
2559 eaa728ee bellard
        }
2560 eaa728ee bellard
    } else {
2561 eaa728ee bellard
        /* check gate type */
2562 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2563 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2564 eaa728ee bellard
        rpl = new_cs & 3;
2565 20054ef0 Blue Swirl
        switch (type) {
2566 eaa728ee bellard
        case 1: /* available 286 TSS */
2567 eaa728ee bellard
        case 9: /* available 386 TSS */
2568 eaa728ee bellard
        case 5: /* task gate */
2569 20054ef0 Blue Swirl
            if (dpl < cpl || dpl < rpl) {
2570 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2571 20054ef0 Blue Swirl
            }
2572 eaa728ee bellard
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2573 eaa728ee bellard
            CC_OP = CC_OP_EFLAGS;
2574 eaa728ee bellard
            return;
2575 eaa728ee bellard
        case 4: /* 286 call gate */
2576 eaa728ee bellard
        case 12: /* 386 call gate */
2577 eaa728ee bellard
            break;
2578 eaa728ee bellard
        default:
2579 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2580 eaa728ee bellard
            break;
2581 eaa728ee bellard
        }
2582 eaa728ee bellard
        shift = type >> 3;
2583 eaa728ee bellard
2584 20054ef0 Blue Swirl
        if (dpl < cpl || dpl < rpl) {
2585 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2586 20054ef0 Blue Swirl
        }
2587 eaa728ee bellard
        /* check valid bit */
2588 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
2589 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG,  new_cs & 0xfffc);
2590 20054ef0 Blue Swirl
        }
2591 eaa728ee bellard
        selector = e1 >> 16;
2592 eaa728ee bellard
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2593 eaa728ee bellard
        param_count = e2 & 0x1f;
2594 20054ef0 Blue Swirl
        if ((selector & 0xfffc) == 0) {
2595 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, 0);
2596 20054ef0 Blue Swirl
        }
2597 eaa728ee bellard
2598 20054ef0 Blue Swirl
        if (load_segment(&e1, &e2, selector) != 0) {
2599 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2600 20054ef0 Blue Swirl
        }
2601 20054ef0 Blue Swirl
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) {
2602 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2603 20054ef0 Blue Swirl
        }
2604 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2605 20054ef0 Blue Swirl
        if (dpl > cpl) {
2606 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
2607 20054ef0 Blue Swirl
        }
2608 20054ef0 Blue Swirl
        if (!(e2 & DESC_P_MASK)) {
2609 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);
2610 20054ef0 Blue Swirl
        }
2611 eaa728ee bellard
2612 eaa728ee bellard
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2613 eaa728ee bellard
            /* to inner privilege */
2614 eaa728ee bellard
            get_ss_esp_from_tss(&ss, &sp, dpl);
2615 20054ef0 Blue Swirl
            LOG_PCALL("new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx
2616 20054ef0 Blue Swirl
                      "\n",
2617 20054ef0 Blue Swirl
                      ss, sp, param_count, ESP);
2618 20054ef0 Blue Swirl
            if ((ss & 0xfffc) == 0) {
2619 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
2620 20054ef0 Blue Swirl
            }
2621 20054ef0 Blue Swirl
            if ((ss & 3) != dpl) {
2622 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
2623 20054ef0 Blue Swirl
            }
2624 20054ef0 Blue Swirl
            if (load_segment(&ss_e1, &ss_e2, ss) != 0) {
2625 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
2626 20054ef0 Blue Swirl
            }
2627 eaa728ee bellard
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2628 20054ef0 Blue Swirl
            if (ss_dpl != dpl) {
2629 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
2630 20054ef0 Blue Swirl
            }
2631 eaa728ee bellard
            if (!(ss_e2 & DESC_S_MASK) ||
2632 eaa728ee bellard
                (ss_e2 & DESC_CS_MASK) ||
2633 20054ef0 Blue Swirl
                !(ss_e2 & DESC_W_MASK)) {
2634 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
2635 20054ef0 Blue Swirl
            }
2636 20054ef0 Blue Swirl
            if (!(ss_e2 & DESC_P_MASK)) {
2637 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0A_TSS, ss & 0xfffc);
2638 20054ef0 Blue Swirl
            }
2639 eaa728ee bellard
2640 20054ef0 Blue Swirl
            /* push_size = ((param_count * 2) + 8) << shift; */
2641 eaa728ee bellard
2642 eaa728ee bellard
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2643 eaa728ee bellard
            old_ssp = env->segs[R_SS].base;
2644 eaa728ee bellard
2645 eaa728ee bellard
            sp_mask = get_sp_mask(ss_e2);
2646 eaa728ee bellard
            ssp = get_seg_base(ss_e1, ss_e2);
2647 eaa728ee bellard
            if (shift) {
2648 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2649 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, ESP);
2650 20054ef0 Blue Swirl
                for (i = param_count - 1; i >= 0; i--) {
2651 eaa728ee bellard
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2652 eaa728ee bellard
                    PUSHL(ssp, sp, sp_mask, val);
2653 eaa728ee bellard
                }
2654 eaa728ee bellard
            } else {
2655 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2656 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, ESP);
2657 20054ef0 Blue Swirl
                for (i = param_count - 1; i >= 0; i--) {
2658 eaa728ee bellard
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2659 eaa728ee bellard
                    PUSHW(ssp, sp, sp_mask, val);
2660 eaa728ee bellard
                }
2661 eaa728ee bellard
            }
2662 eaa728ee bellard
            new_stack = 1;
2663 eaa728ee bellard
        } else {
2664 eaa728ee bellard
            /* to same privilege */
2665 eaa728ee bellard
            sp = ESP;
2666 eaa728ee bellard
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2667 eaa728ee bellard
            ssp = env->segs[R_SS].base;
2668 20054ef0 Blue Swirl
            /* push_size = (4 << shift); */
2669 eaa728ee bellard
            new_stack = 0;
2670 eaa728ee bellard
        }
2671 eaa728ee bellard
2672 eaa728ee bellard
        if (shift) {
2673 eaa728ee bellard
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2674 eaa728ee bellard
            PUSHL(ssp, sp, sp_mask, next_eip);
2675 eaa728ee bellard
        } else {
2676 eaa728ee bellard
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2677 eaa728ee bellard
            PUSHW(ssp, sp, sp_mask, next_eip);
2678 eaa728ee bellard
        }
2679 eaa728ee bellard
2680 eaa728ee bellard
        /* from this point, not restartable */
2681 eaa728ee bellard
2682 eaa728ee bellard
        if (new_stack) {
2683 eaa728ee bellard
            ss = (ss & ~3) | dpl;
2684 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_SS, ss,
2685 eaa728ee bellard
                                   ssp,
2686 eaa728ee bellard
                                   get_seg_limit(ss_e1, ss_e2),
2687 eaa728ee bellard
                                   ss_e2);
2688 eaa728ee bellard
        }
2689 eaa728ee bellard
2690 eaa728ee bellard
        selector = (selector & ~3) | dpl;
2691 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector,
2692 eaa728ee bellard
                       get_seg_base(e1, e2),
2693 eaa728ee bellard
                       get_seg_limit(e1, e2),
2694 eaa728ee bellard
                       e2);
2695 eaa728ee bellard
        cpu_x86_set_cpl(env, dpl);
2696 eaa728ee bellard
        SET_ESP(sp, sp_mask);
2697 eaa728ee bellard
        EIP = offset;
2698 eaa728ee bellard
    }
2699 eaa728ee bellard
}
2700 eaa728ee bellard
2701 eaa728ee bellard
/* real and vm86 mode iret */
2702 eaa728ee bellard
void helper_iret_real(int shift)
2703 eaa728ee bellard
{
2704 eaa728ee bellard
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2705 eaa728ee bellard
    target_ulong ssp;
2706 eaa728ee bellard
    int eflags_mask;
2707 eaa728ee bellard
2708 20054ef0 Blue Swirl
    sp_mask = 0xffff; /* XXXX: use SS segment size? */
2709 eaa728ee bellard
    sp = ESP;
2710 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2711 eaa728ee bellard
    if (shift == 1) {
2712 eaa728ee bellard
        /* 32 bits */
2713 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_eip);
2714 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_cs);
2715 eaa728ee bellard
        new_cs &= 0xffff;
2716 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_eflags);
2717 eaa728ee bellard
    } else {
2718 eaa728ee bellard
        /* 16 bits */
2719 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_eip);
2720 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_cs);
2721 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_eflags);
2722 eaa728ee bellard
    }
2723 eaa728ee bellard
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2724 bdadc0b5 malc
    env->segs[R_CS].selector = new_cs;
2725 bdadc0b5 malc
    env->segs[R_CS].base = (new_cs << 4);
2726 eaa728ee bellard
    env->eip = new_eip;
2727 20054ef0 Blue Swirl
    if (env->eflags & VM_MASK) {
2728 20054ef0 Blue Swirl
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK |
2729 20054ef0 Blue Swirl
            NT_MASK;
2730 20054ef0 Blue Swirl
    } else {
2731 20054ef0 Blue Swirl
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK |
2732 20054ef0 Blue Swirl
            RF_MASK | NT_MASK;
2733 20054ef0 Blue Swirl
    }
2734 20054ef0 Blue Swirl
    if (shift == 0) {
2735 eaa728ee bellard
        eflags_mask &= 0xffff;
2736 20054ef0 Blue Swirl
    }
2737 997ff0d9 Blue Swirl
    cpu_load_eflags(env, new_eflags, eflags_mask);
2738 db620f46 bellard
    env->hflags2 &= ~HF2_NMI_MASK;
2739 eaa728ee bellard
}
2740 eaa728ee bellard
2741 eaa728ee bellard
static inline void validate_seg(int seg_reg, int cpl)
2742 eaa728ee bellard
{
2743 eaa728ee bellard
    int dpl;
2744 eaa728ee bellard
    uint32_t e2;
2745 eaa728ee bellard
2746 eaa728ee bellard
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2747 eaa728ee bellard
       they may still contain a valid base. I would be interested to
2748 eaa728ee bellard
       know how a real x86_64 CPU behaves */
2749 eaa728ee bellard
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2750 20054ef0 Blue Swirl
        (env->segs[seg_reg].selector & 0xfffc) == 0) {
2751 eaa728ee bellard
        return;
2752 20054ef0 Blue Swirl
    }
2753 eaa728ee bellard
2754 eaa728ee bellard
    e2 = env->segs[seg_reg].flags;
2755 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2756 eaa728ee bellard
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2757 eaa728ee bellard
        /* data or non conforming code segment */
2758 eaa728ee bellard
        if (dpl < cpl) {
2759 eaa728ee bellard
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2760 eaa728ee bellard
        }
2761 eaa728ee bellard
    }
2762 eaa728ee bellard
}
2763 eaa728ee bellard
2764 eaa728ee bellard
/* protected mode iret */
2765 eaa728ee bellard
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2766 eaa728ee bellard
{
2767 eaa728ee bellard
    uint32_t new_cs, new_eflags, new_ss;
2768 eaa728ee bellard
    uint32_t new_es, new_ds, new_fs, new_gs;
2769 eaa728ee bellard
    uint32_t e1, e2, ss_e1, ss_e2;
2770 eaa728ee bellard
    int cpl, dpl, rpl, eflags_mask, iopl;
2771 eaa728ee bellard
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2772 eaa728ee bellard
2773 eaa728ee bellard
#ifdef TARGET_X86_64
2774 20054ef0 Blue Swirl
    if (shift == 2) {
2775 eaa728ee bellard
        sp_mask = -1;
2776 20054ef0 Blue Swirl
    } else
2777 eaa728ee bellard
#endif
2778 20054ef0 Blue Swirl
    {
2779 eaa728ee bellard
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2780 20054ef0 Blue Swirl
    }
2781 eaa728ee bellard
    sp = ESP;
2782 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2783 eaa728ee bellard
    new_eflags = 0; /* avoid warning */
2784 eaa728ee bellard
#ifdef TARGET_X86_64
2785 eaa728ee bellard
    if (shift == 2) {
2786 eaa728ee bellard
        POPQ(sp, new_eip);
2787 eaa728ee bellard
        POPQ(sp, new_cs);
2788 eaa728ee bellard
        new_cs &= 0xffff;
2789 eaa728ee bellard
        if (is_iret) {
2790 eaa728ee bellard
            POPQ(sp, new_eflags);
2791 eaa728ee bellard
        }
2792 eaa728ee bellard
    } else
2793 eaa728ee bellard
#endif
2794 20054ef0 Blue Swirl
    {
2795 20054ef0 Blue Swirl
        if (shift == 1) {
2796 20054ef0 Blue Swirl
            /* 32 bits */
2797 20054ef0 Blue Swirl
            POPL(ssp, sp, sp_mask, new_eip);
2798 20054ef0 Blue Swirl
            POPL(ssp, sp, sp_mask, new_cs);
2799 20054ef0 Blue Swirl
            new_cs &= 0xffff;
2800 20054ef0 Blue Swirl
            if (is_iret) {
2801 20054ef0 Blue Swirl
                POPL(ssp, sp, sp_mask, new_eflags);
2802 20054ef0 Blue Swirl
                if (new_eflags & VM_MASK) {
2803 20054ef0 Blue Swirl
                    goto return_to_vm86;
2804 20054ef0 Blue Swirl
                }
2805 20054ef0 Blue Swirl
            }
2806 20054ef0 Blue Swirl
        } else {
2807 20054ef0 Blue Swirl
            /* 16 bits */
2808 20054ef0 Blue Swirl
            POPW(ssp, sp, sp_mask, new_eip);
2809 20054ef0 Blue Swirl
            POPW(ssp, sp, sp_mask, new_cs);
2810 20054ef0 Blue Swirl
            if (is_iret) {
2811 20054ef0 Blue Swirl
                POPW(ssp, sp, sp_mask, new_eflags);
2812 20054ef0 Blue Swirl
            }
2813 eaa728ee bellard
        }
2814 eaa728ee bellard
    }
2815 d12d51d5 aliguori
    LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2816 d12d51d5 aliguori
              new_cs, new_eip, shift, addend);
2817 d12d51d5 aliguori
    LOG_PCALL_STATE(env);
2818 20054ef0 Blue Swirl
    if ((new_cs & 0xfffc) == 0) {
2819 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2820 20054ef0 Blue Swirl
    }
2821 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, new_cs) != 0) {
2822 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2823 20054ef0 Blue Swirl
    }
2824 eaa728ee bellard
    if (!(e2 & DESC_S_MASK) ||
2825 20054ef0 Blue Swirl
        !(e2 & DESC_CS_MASK)) {
2826 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2827 20054ef0 Blue Swirl
    }
2828 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2829 eaa728ee bellard
    rpl = new_cs & 3;
2830 20054ef0 Blue Swirl
    if (rpl < cpl) {
2831 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2832 20054ef0 Blue Swirl
    }
2833 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2834 eaa728ee bellard
    if (e2 & DESC_C_MASK) {
2835 20054ef0 Blue Swirl
        if (dpl > rpl) {
2836 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2837 20054ef0 Blue Swirl
        }
2838 eaa728ee bellard
    } else {
2839 20054ef0 Blue Swirl
        if (dpl != rpl) {
2840 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
2841 20054ef0 Blue Swirl
        }
2842 eaa728ee bellard
    }
2843 20054ef0 Blue Swirl
    if (!(e2 & DESC_P_MASK)) {
2844 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc);
2845 20054ef0 Blue Swirl
    }
2846 eaa728ee bellard
2847 eaa728ee bellard
    sp += addend;
2848 eaa728ee bellard
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2849 eaa728ee bellard
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2850 1235fc06 ths
        /* return to same privilege level */
2851 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2852 eaa728ee bellard
                       get_seg_base(e1, e2),
2853 eaa728ee bellard
                       get_seg_limit(e1, e2),
2854 eaa728ee bellard
                       e2);
2855 eaa728ee bellard
    } else {
2856 eaa728ee bellard
        /* return to different privilege level */
2857 eaa728ee bellard
#ifdef TARGET_X86_64
2858 eaa728ee bellard
        if (shift == 2) {
2859 eaa728ee bellard
            POPQ(sp, new_esp);
2860 eaa728ee bellard
            POPQ(sp, new_ss);
2861 eaa728ee bellard
            new_ss &= 0xffff;
2862 eaa728ee bellard
        } else
2863 eaa728ee bellard
#endif
2864 20054ef0 Blue Swirl
        {
2865 20054ef0 Blue Swirl
            if (shift == 1) {
2866 20054ef0 Blue Swirl
                /* 32 bits */
2867 20054ef0 Blue Swirl
                POPL(ssp, sp, sp_mask, new_esp);
2868 20054ef0 Blue Swirl
                POPL(ssp, sp, sp_mask, new_ss);
2869 20054ef0 Blue Swirl
                new_ss &= 0xffff;
2870 20054ef0 Blue Swirl
            } else {
2871 20054ef0 Blue Swirl
                /* 16 bits */
2872 20054ef0 Blue Swirl
                POPW(ssp, sp, sp_mask, new_esp);
2873 20054ef0 Blue Swirl
                POPW(ssp, sp, sp_mask, new_ss);
2874 20054ef0 Blue Swirl
            }
2875 eaa728ee bellard
        }
2876 d12d51d5 aliguori
        LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",
2877 20054ef0 Blue Swirl
                  new_ss, new_esp);
2878 eaa728ee bellard
        if ((new_ss & 0xfffc) == 0) {
2879 eaa728ee bellard
#ifdef TARGET_X86_64
2880 20054ef0 Blue Swirl
            /* NULL ss is allowed in long mode if cpl != 3 */
2881 20054ef0 Blue Swirl
            /* XXX: test CS64? */
2882 eaa728ee bellard
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2883 eaa728ee bellard
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2884 eaa728ee bellard
                                       0, 0xffffffff,
2885 eaa728ee bellard
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2886 eaa728ee bellard
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2887 eaa728ee bellard
                                       DESC_W_MASK | DESC_A_MASK);
2888 20054ef0 Blue Swirl
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed? */
2889 eaa728ee bellard
            } else
2890 eaa728ee bellard
#endif
2891 eaa728ee bellard
            {
2892 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, 0);
2893 eaa728ee bellard
            }
2894 eaa728ee bellard
        } else {
2895 20054ef0 Blue Swirl
            if ((new_ss & 3) != rpl) {
2896 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);
2897 20054ef0 Blue Swirl
            }
2898 20054ef0 Blue Swirl
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0) {
2899 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);
2900 20054ef0 Blue Swirl
            }
2901 eaa728ee bellard
            if (!(ss_e2 & DESC_S_MASK) ||
2902 eaa728ee bellard
                (ss_e2 & DESC_CS_MASK) ||
2903 20054ef0 Blue Swirl
                !(ss_e2 & DESC_W_MASK)) {
2904 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);
2905 20054ef0 Blue Swirl
            }
2906 eaa728ee bellard
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2907 20054ef0 Blue Swirl
            if (dpl != rpl) {
2908 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);
2909 20054ef0 Blue Swirl
            }
2910 20054ef0 Blue Swirl
            if (!(ss_e2 & DESC_P_MASK)) {
2911 77b2bc2c Blue Swirl
                raise_exception_err(env, EXCP0B_NOSEG, new_ss & 0xfffc);
2912 20054ef0 Blue Swirl
            }
2913 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2914 eaa728ee bellard
                                   get_seg_base(ss_e1, ss_e2),
2915 eaa728ee bellard
                                   get_seg_limit(ss_e1, ss_e2),
2916 eaa728ee bellard
                                   ss_e2);
2917 eaa728ee bellard
        }
2918 eaa728ee bellard
2919 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2920 eaa728ee bellard
                       get_seg_base(e1, e2),
2921 eaa728ee bellard
                       get_seg_limit(e1, e2),
2922 eaa728ee bellard
                       e2);
2923 eaa728ee bellard
        cpu_x86_set_cpl(env, rpl);
2924 eaa728ee bellard
        sp = new_esp;
2925 eaa728ee bellard
#ifdef TARGET_X86_64
2926 20054ef0 Blue Swirl
        if (env->hflags & HF_CS64_MASK) {
2927 eaa728ee bellard
            sp_mask = -1;
2928 20054ef0 Blue Swirl
        } else
2929 eaa728ee bellard
#endif
2930 20054ef0 Blue Swirl
        {
2931 eaa728ee bellard
            sp_mask = get_sp_mask(ss_e2);
2932 20054ef0 Blue Swirl
        }
2933 eaa728ee bellard
2934 eaa728ee bellard
        /* validate data segments */
2935 eaa728ee bellard
        validate_seg(R_ES, rpl);
2936 eaa728ee bellard
        validate_seg(R_DS, rpl);
2937 eaa728ee bellard
        validate_seg(R_FS, rpl);
2938 eaa728ee bellard
        validate_seg(R_GS, rpl);
2939 eaa728ee bellard
2940 eaa728ee bellard
        sp += addend;
2941 eaa728ee bellard
    }
2942 eaa728ee bellard
    SET_ESP(sp, sp_mask);
2943 eaa728ee bellard
    env->eip = new_eip;
2944 eaa728ee bellard
    if (is_iret) {
2945 eaa728ee bellard
        /* NOTE: 'cpl' is the _old_ CPL */
2946 eaa728ee bellard
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2947 20054ef0 Blue Swirl
        if (cpl == 0) {
2948 eaa728ee bellard
            eflags_mask |= IOPL_MASK;
2949 20054ef0 Blue Swirl
        }
2950 eaa728ee bellard
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2951 20054ef0 Blue Swirl
        if (cpl <= iopl) {
2952 eaa728ee bellard
            eflags_mask |= IF_MASK;
2953 20054ef0 Blue Swirl
        }
2954 20054ef0 Blue Swirl
        if (shift == 0) {
2955 eaa728ee bellard
            eflags_mask &= 0xffff;
2956 20054ef0 Blue Swirl
        }
2957 997ff0d9 Blue Swirl
        cpu_load_eflags(env, new_eflags, eflags_mask);
2958 eaa728ee bellard
    }
2959 eaa728ee bellard
    return;
2960 eaa728ee bellard
2961 eaa728ee bellard
 return_to_vm86:
2962 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_esp);
2963 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_ss);
2964 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_es);
2965 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_ds);
2966 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_fs);
2967 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_gs);
2968 eaa728ee bellard
2969 eaa728ee bellard
    /* modify processor state */
2970 997ff0d9 Blue Swirl
    cpu_load_eflags(env, new_eflags, TF_MASK | AC_MASK | ID_MASK |
2971 997ff0d9 Blue Swirl
                    IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK |
2972 997ff0d9 Blue Swirl
                    VIP_MASK);
2973 eaa728ee bellard
    load_seg_vm(R_CS, new_cs & 0xffff);
2974 eaa728ee bellard
    cpu_x86_set_cpl(env, 3);
2975 eaa728ee bellard
    load_seg_vm(R_SS, new_ss & 0xffff);
2976 eaa728ee bellard
    load_seg_vm(R_ES, new_es & 0xffff);
2977 eaa728ee bellard
    load_seg_vm(R_DS, new_ds & 0xffff);
2978 eaa728ee bellard
    load_seg_vm(R_FS, new_fs & 0xffff);
2979 eaa728ee bellard
    load_seg_vm(R_GS, new_gs & 0xffff);
2980 eaa728ee bellard
2981 eaa728ee bellard
    env->eip = new_eip & 0xffff;
2982 eaa728ee bellard
    ESP = new_esp;
2983 eaa728ee bellard
}
2984 eaa728ee bellard
2985 eaa728ee bellard
void helper_iret_protected(int shift, int next_eip)
2986 eaa728ee bellard
{
2987 eaa728ee bellard
    int tss_selector, type;
2988 eaa728ee bellard
    uint32_t e1, e2;
2989 eaa728ee bellard
2990 eaa728ee bellard
    /* specific case for TSS */
2991 eaa728ee bellard
    if (env->eflags & NT_MASK) {
2992 eaa728ee bellard
#ifdef TARGET_X86_64
2993 20054ef0 Blue Swirl
        if (env->hflags & HF_LMA_MASK) {
2994 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0D_GPF, 0);
2995 20054ef0 Blue Swirl
        }
2996 eaa728ee bellard
#endif
2997 eaa728ee bellard
        tss_selector = lduw_kernel(env->tr.base + 0);
2998 20054ef0 Blue Swirl
        if (tss_selector & 4) {
2999 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc);
3000 20054ef0 Blue Swirl
        }
3001 20054ef0 Blue Swirl
        if (load_segment(&e1, &e2, tss_selector) != 0) {
3002 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc);
3003 20054ef0 Blue Swirl
        }
3004 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
3005 eaa728ee bellard
        /* NOTE: we check both segment and busy TSS */
3006 20054ef0 Blue Swirl
        if (type != 3) {
3007 77b2bc2c Blue Swirl
            raise_exception_err(env, EXCP0A_TSS, tss_selector & 0xfffc);
3008 20054ef0 Blue Swirl
        }
3009 eaa728ee bellard
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
3010 eaa728ee bellard
    } else {
3011 eaa728ee bellard
        helper_ret_protected(shift, 1, 0);
3012 eaa728ee bellard
    }
3013 db620f46 bellard
    env->hflags2 &= ~HF2_NMI_MASK;
3014 eaa728ee bellard
}
3015 eaa728ee bellard
3016 eaa728ee bellard
void helper_lret_protected(int shift, int addend)
3017 eaa728ee bellard
{
3018 eaa728ee bellard
    helper_ret_protected(shift, 0, addend);
3019 eaa728ee bellard
}
3020 eaa728ee bellard
3021 eaa728ee bellard
void helper_sysenter(void)
3022 eaa728ee bellard
{
3023 eaa728ee bellard
    if (env->sysenter_cs == 0) {
3024 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
3025 eaa728ee bellard
    }
3026 eaa728ee bellard
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
3027 eaa728ee bellard
    cpu_x86_set_cpl(env, 0);
3028 2436b61a balrog
3029 2436b61a balrog
#ifdef TARGET_X86_64
3030 2436b61a balrog
    if (env->hflags & HF_LMA_MASK) {
3031 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
3032 2436b61a balrog
                               0, 0xffffffff,
3033 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3034 2436b61a balrog
                               DESC_S_MASK |
3035 20054ef0 Blue Swirl
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
3036 20054ef0 Blue Swirl
                               DESC_L_MASK);
3037 2436b61a balrog
    } else
3038 2436b61a balrog
#endif
3039 2436b61a balrog
    {
3040 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
3041 2436b61a balrog
                               0, 0xffffffff,
3042 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3043 2436b61a balrog
                               DESC_S_MASK |
3044 2436b61a balrog
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
3045 2436b61a balrog
    }
3046 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
3047 eaa728ee bellard
                           0, 0xffffffff,
3048 eaa728ee bellard
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3049 eaa728ee bellard
                           DESC_S_MASK |
3050 eaa728ee bellard
                           DESC_W_MASK | DESC_A_MASK);
3051 eaa728ee bellard
    ESP = env->sysenter_esp;
3052 eaa728ee bellard
    EIP = env->sysenter_eip;
3053 eaa728ee bellard
}
3054 eaa728ee bellard
3055 2436b61a balrog
void helper_sysexit(int dflag)
3056 eaa728ee bellard
{
3057 eaa728ee bellard
    int cpl;
3058 eaa728ee bellard
3059 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3060 eaa728ee bellard
    if (env->sysenter_cs == 0 || cpl != 0) {
3061 77b2bc2c Blue Swirl
        raise_exception_err(env, EXCP0D_GPF, 0);
3062 eaa728ee bellard
    }
3063 eaa728ee bellard
    cpu_x86_set_cpl(env, 3);
3064 2436b61a balrog
#ifdef TARGET_X86_64
3065 2436b61a balrog
    if (dflag == 2) {
3066 20054ef0 Blue Swirl
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) |
3067 20054ef0 Blue Swirl
                               3, 0, 0xffffffff,
3068 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3069 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3070 20054ef0 Blue Swirl
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
3071 20054ef0 Blue Swirl
                               DESC_L_MASK);
3072 20054ef0 Blue Swirl
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) |
3073 20054ef0 Blue Swirl
                               3, 0, 0xffffffff,
3074 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3075 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3076 2436b61a balrog
                               DESC_W_MASK | DESC_A_MASK);
3077 2436b61a balrog
    } else
3078 2436b61a balrog
#endif
3079 2436b61a balrog
    {
3080 20054ef0 Blue Swirl
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) |
3081 20054ef0 Blue Swirl
                               3, 0, 0xffffffff,
3082 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3083 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3084 2436b61a balrog
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
3085 20054ef0 Blue Swirl
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) |
3086 20054ef0 Blue Swirl
                               3, 0, 0xffffffff,
3087 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
3088 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
3089 2436b61a balrog
                               DESC_W_MASK | DESC_A_MASK);
3090 2436b61a balrog
    }
3091 eaa728ee bellard
    ESP = ECX;
3092 eaa728ee bellard
    EIP = EDX;
3093 eaa728ee bellard
}
3094 eaa728ee bellard
3095 872929aa bellard
#if defined(CONFIG_USER_ONLY)
3096 872929aa bellard
target_ulong helper_read_crN(int reg)
3097 eaa728ee bellard
{
3098 872929aa bellard
    return 0;
3099 872929aa bellard
}
3100 872929aa bellard
3101 872929aa bellard
void helper_write_crN(int reg, target_ulong t0)
3102 872929aa bellard
{
3103 872929aa bellard
}
3104 01df040b aliguori
3105 01df040b aliguori
void helper_movl_drN_T0(int reg, target_ulong t0)
3106 01df040b aliguori
{
3107 01df040b aliguori
}
3108 872929aa bellard
#else
3109 872929aa bellard
target_ulong helper_read_crN(int reg)
3110 872929aa bellard
{
3111 872929aa bellard
    target_ulong val;
3112 872929aa bellard
3113 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
3114 20054ef0 Blue Swirl
    switch (reg) {
3115 872929aa bellard
    default:
3116 872929aa bellard
        val = env->cr[reg];
3117 872929aa bellard
        break;
3118 872929aa bellard
    case 8:
3119 db620f46 bellard
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
3120 4a942cea Blue Swirl
            val = cpu_get_apic_tpr(env->apic_state);
3121 db620f46 bellard
        } else {
3122 db620f46 bellard
            val = env->v_tpr;
3123 db620f46 bellard
        }
3124 872929aa bellard
        break;
3125 872929aa bellard
    }
3126 872929aa bellard
    return val;
3127 872929aa bellard
}
3128 872929aa bellard
3129 872929aa bellard
void helper_write_crN(int reg, target_ulong t0)
3130 872929aa bellard
{
3131 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
3132 20054ef0 Blue Swirl
    switch (reg) {
3133 eaa728ee bellard
    case 0:
3134 eaa728ee bellard
        cpu_x86_update_cr0(env, t0);
3135 eaa728ee bellard
        break;
3136 eaa728ee bellard
    case 3:
3137 eaa728ee bellard
        cpu_x86_update_cr3(env, t0);
3138 eaa728ee bellard
        break;
3139 eaa728ee bellard
    case 4:
3140 eaa728ee bellard
        cpu_x86_update_cr4(env, t0);
3141 eaa728ee bellard
        break;
3142 eaa728ee bellard
    case 8:
3143 db620f46 bellard
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
3144 4a942cea Blue Swirl
            cpu_set_apic_tpr(env->apic_state, t0);
3145 db620f46 bellard
        }
3146 db620f46 bellard
        env->v_tpr = t0 & 0x0f;
3147 eaa728ee bellard
        break;
3148 eaa728ee bellard
    default:
3149 eaa728ee bellard
        env->cr[reg] = t0;
3150 eaa728ee bellard
        break;
3151 eaa728ee bellard
    }
3152 eaa728ee bellard
}
3153 01df040b aliguori
3154 01df040b aliguori
void helper_movl_drN_T0(int reg, target_ulong t0)
3155 01df040b aliguori
{
3156 01df040b aliguori
    int i;
3157 01df040b aliguori
3158 01df040b aliguori
    if (reg < 4) {
3159 01df040b aliguori
        hw_breakpoint_remove(env, reg);
3160 01df040b aliguori
        env->dr[reg] = t0;
3161 01df040b aliguori
        hw_breakpoint_insert(env, reg);
3162 01df040b aliguori
    } else if (reg == 7) {
3163 20054ef0 Blue Swirl
        for (i = 0; i < 4; i++) {
3164 01df040b aliguori
            hw_breakpoint_remove(env, i);
3165 20054ef0 Blue Swirl
        }
3166 01df040b aliguori
        env->dr[7] = t0;
3167 20054ef0 Blue Swirl
        for (i = 0; i < 4; i++) {
3168 01df040b aliguori
            hw_breakpoint_insert(env, i);
3169 20054ef0 Blue Swirl
        }
3170 20054ef0 Blue Swirl
    } else {
3171 01df040b aliguori
        env->dr[reg] = t0;
3172 20054ef0 Blue Swirl
    }
3173 01df040b aliguori
}
3174 872929aa bellard
#endif
3175 eaa728ee bellard
3176 eaa728ee bellard
void helper_lmsw(target_ulong t0)
3177 eaa728ee bellard
{
3178 eaa728ee bellard
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
3179 eaa728ee bellard
       if already set to one. */
3180 eaa728ee bellard
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
3181 872929aa bellard
    helper_write_crN(0, t0);
3182 eaa728ee bellard
}
3183 eaa728ee bellard
3184 eaa728ee bellard
void helper_clts(void)
3185 eaa728ee bellard
{
3186 eaa728ee bellard
    env->cr[0] &= ~CR0_TS_MASK;
3187 eaa728ee bellard
    env->hflags &= ~HF_TS_MASK;
3188 eaa728ee bellard
}
3189 eaa728ee bellard
3190 eaa728ee bellard
void helper_invlpg(target_ulong addr)
3191 eaa728ee bellard
{
3192 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
3193 914178d3 bellard
    tlb_flush_page(env, addr);
3194 eaa728ee bellard
}
3195 eaa728ee bellard
3196 eaa728ee bellard
void helper_rdtsc(void)
3197 eaa728ee bellard
{
3198 eaa728ee bellard
    uint64_t val;
3199 eaa728ee bellard
3200 eaa728ee bellard
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3201 77b2bc2c Blue Swirl
        raise_exception(env, EXCP0D_GPF);
3202 eaa728ee bellard
    }
3203 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
3204 872929aa bellard
3205 33c263df bellard
    val = cpu_get_tsc(env) + env->tsc_offset;
3206 eaa728ee bellard
    EAX = (uint32_t)(val);
3207 eaa728ee bellard
    EDX = (uint32_t)(val >> 32);
3208 eaa728ee bellard
}
3209 eaa728ee bellard
3210 1b050077 Andre Przywara
void helper_rdtscp(void)
3211 1b050077 Andre Przywara
{
3212 1b050077 Andre Przywara
    helper_rdtsc();
3213 1b050077 Andre Przywara
    ECX = (uint32_t)(env->tsc_aux);
3214 1b050077 Andre Przywara
}
3215 1b050077 Andre Przywara
3216 eaa728ee bellard
void helper_rdpmc(void)
3217 eaa728ee bellard
{
3218 eaa728ee bellard
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3219 77b2bc2c Blue Swirl
        raise_exception(env, EXCP0D_GPF);
3220 eaa728ee bellard
    }
3221 eaa728ee bellard
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3222 20054ef0 Blue Swirl
3223 eaa728ee bellard
    /* currently unimplemented */
3224 71547a3b Blue Swirl
    qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
3225 77b2bc2c Blue Swirl
    raise_exception_err(env, EXCP06_ILLOP, 0);
3226 eaa728ee bellard
}
3227 eaa728ee bellard
3228 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
3229 eaa728ee bellard
void helper_wrmsr(void)
3230 eaa728ee bellard
{
3231 eaa728ee bellard
}
3232 eaa728ee bellard
3233 eaa728ee bellard
void helper_rdmsr(void)
3234 eaa728ee bellard
{
3235 eaa728ee bellard
}
3236 eaa728ee bellard
#else
3237 eaa728ee bellard
void helper_wrmsr(void)
3238 eaa728ee bellard
{
3239 eaa728ee bellard
    uint64_t val;
3240 eaa728ee bellard
3241 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3242 872929aa bellard
3243 eaa728ee bellard
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3244 eaa728ee bellard
3245 20054ef0 Blue Swirl
    switch ((uint32_t)ECX) {
3246 eaa728ee bellard
    case MSR_IA32_SYSENTER_CS:
3247 eaa728ee bellard
        env->sysenter_cs = val & 0xffff;
3248 eaa728ee bellard
        break;
3249 eaa728ee bellard
    case MSR_IA32_SYSENTER_ESP:
3250 eaa728ee bellard
        env->sysenter_esp = val;
3251 eaa728ee bellard
        break;
3252 eaa728ee bellard
    case MSR_IA32_SYSENTER_EIP:
3253 eaa728ee bellard
        env->sysenter_eip = val;
3254 eaa728ee bellard
        break;
3255 eaa728ee bellard
    case MSR_IA32_APICBASE:
3256 4a942cea Blue Swirl
        cpu_set_apic_base(env->apic_state, val);
3257 eaa728ee bellard
        break;
3258 eaa728ee bellard
    case MSR_EFER:
3259 eaa728ee bellard
        {
3260 eaa728ee bellard
            uint64_t update_mask;
3261 20054ef0 Blue Swirl
3262 eaa728ee bellard
            update_mask = 0;
3263 20054ef0 Blue Swirl
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL) {
3264 eaa728ee bellard
                update_mask |= MSR_EFER_SCE;
3265 20054ef0 Blue Swirl
            }
3266 20054ef0 Blue Swirl
            if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
3267 eaa728ee bellard
                update_mask |= MSR_EFER_LME;
3268 20054ef0 Blue Swirl
            }
3269 20054ef0 Blue Swirl
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR) {
3270 eaa728ee bellard
                update_mask |= MSR_EFER_FFXSR;
3271 20054ef0 Blue Swirl
            }
3272 20054ef0 Blue Swirl
            if (env->cpuid_ext2_features & CPUID_EXT2_NX) {
3273 eaa728ee bellard
                update_mask |= MSR_EFER_NXE;
3274 20054ef0 Blue Swirl
            }
3275 20054ef0 Blue Swirl
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
3276 5efc27bb bellard
                update_mask |= MSR_EFER_SVME;
3277 20054ef0 Blue Swirl
            }
3278 20054ef0 Blue Swirl
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR) {
3279 eef26553 aliguori
                update_mask |= MSR_EFER_FFXSR;
3280 20054ef0 Blue Swirl
            }
3281 5efc27bb bellard
            cpu_load_efer(env, (env->efer & ~update_mask) |
3282 5efc27bb bellard
                          (val & update_mask));
3283 eaa728ee bellard
        }
3284 eaa728ee bellard
        break;
3285 eaa728ee bellard
    case MSR_STAR:
3286 eaa728ee bellard
        env->star = val;
3287 eaa728ee bellard
        break;
3288 eaa728ee bellard
    case MSR_PAT:
3289 eaa728ee bellard
        env->pat = val;
3290 eaa728ee bellard
        break;
3291 eaa728ee bellard
    case MSR_VM_HSAVE_PA:
3292 eaa728ee bellard
        env->vm_hsave = val;
3293 eaa728ee bellard
        break;
3294 eaa728ee bellard
#ifdef TARGET_X86_64
3295 eaa728ee bellard
    case MSR_LSTAR:
3296 eaa728ee bellard
        env->lstar = val;
3297 eaa728ee bellard
        break;
3298 eaa728ee bellard
    case MSR_CSTAR:
3299 eaa728ee bellard
        env->cstar = val;
3300 eaa728ee bellard
        break;
3301 eaa728ee bellard
    case MSR_FMASK:
3302 eaa728ee bellard
        env->fmask = val;
3303 eaa728ee bellard
        break;
3304 eaa728ee bellard
    case MSR_FSBASE:
3305 eaa728ee bellard
        env->segs[R_FS].base = val;
3306 eaa728ee bellard
        break;
3307 eaa728ee bellard
    case MSR_GSBASE:
3308 eaa728ee bellard
        env->segs[R_GS].base = val;
3309 eaa728ee bellard
        break;
3310 eaa728ee bellard
    case MSR_KERNELGSBASE:
3311 eaa728ee bellard
        env->kernelgsbase = val;
3312 eaa728ee bellard
        break;
3313 eaa728ee bellard
#endif
3314 165d9b82 aliguori
    case MSR_MTRRphysBase(0):
3315 165d9b82 aliguori
    case MSR_MTRRphysBase(1):
3316 165d9b82 aliguori
    case MSR_MTRRphysBase(2):
3317 165d9b82 aliguori
    case MSR_MTRRphysBase(3):
3318 165d9b82 aliguori
    case MSR_MTRRphysBase(4):
3319 165d9b82 aliguori
    case MSR_MTRRphysBase(5):
3320 165d9b82 aliguori
    case MSR_MTRRphysBase(6):
3321 165d9b82 aliguori
    case MSR_MTRRphysBase(7):
3322 165d9b82 aliguori
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
3323 165d9b82 aliguori
        break;
3324 165d9b82 aliguori
    case MSR_MTRRphysMask(0):
3325 165d9b82 aliguori
    case MSR_MTRRphysMask(1):
3326 165d9b82 aliguori
    case MSR_MTRRphysMask(2):
3327 165d9b82 aliguori
    case MSR_MTRRphysMask(3):
3328 165d9b82 aliguori
    case MSR_MTRRphysMask(4):
3329 165d9b82 aliguori
    case MSR_MTRRphysMask(5):
3330 165d9b82 aliguori
    case MSR_MTRRphysMask(6):
3331 165d9b82 aliguori
    case MSR_MTRRphysMask(7):
3332 165d9b82 aliguori
        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
3333 165d9b82 aliguori
        break;
3334 165d9b82 aliguori
    case MSR_MTRRfix64K_00000:
3335 165d9b82 aliguori
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
3336 165d9b82 aliguori
        break;
3337 165d9b82 aliguori
    case MSR_MTRRfix16K_80000:
3338 165d9b82 aliguori
    case MSR_MTRRfix16K_A0000:
3339 165d9b82 aliguori
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
3340 165d9b82 aliguori
        break;
3341 165d9b82 aliguori
    case MSR_MTRRfix4K_C0000:
3342 165d9b82 aliguori
    case MSR_MTRRfix4K_C8000:
3343 165d9b82 aliguori
    case MSR_MTRRfix4K_D0000:
3344 165d9b82 aliguori
    case MSR_MTRRfix4K_D8000:
3345 165d9b82 aliguori
    case MSR_MTRRfix4K_E0000:
3346 165d9b82 aliguori
    case MSR_MTRRfix4K_E8000:
3347 165d9b82 aliguori
    case MSR_MTRRfix4K_F0000:
3348 165d9b82 aliguori
    case MSR_MTRRfix4K_F8000:
3349 165d9b82 aliguori
        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
3350 165d9b82 aliguori
        break;
3351 165d9b82 aliguori
    case MSR_MTRRdefType:
3352 165d9b82 aliguori
        env->mtrr_deftype = val;
3353 165d9b82 aliguori
        break;
3354 79c4f6b0 Huang Ying
    case MSR_MCG_STATUS:
3355 79c4f6b0 Huang Ying
        env->mcg_status = val;
3356 79c4f6b0 Huang Ying
        break;
3357 79c4f6b0 Huang Ying
    case MSR_MCG_CTL:
3358 79c4f6b0 Huang Ying
        if ((env->mcg_cap & MCG_CTL_P)
3359 20054ef0 Blue Swirl
            && (val == 0 || val == ~(uint64_t)0)) {
3360 79c4f6b0 Huang Ying
            env->mcg_ctl = val;
3361 20054ef0 Blue Swirl
        }
3362 79c4f6b0 Huang Ying
        break;
3363 1b050077 Andre Przywara
    case MSR_TSC_AUX:
3364 1b050077 Andre Przywara
        env->tsc_aux = val;
3365 1b050077 Andre Przywara
        break;
3366 21e87c46 Avi Kivity
    case MSR_IA32_MISC_ENABLE:
3367 21e87c46 Avi Kivity
        env->msr_ia32_misc_enable = val;
3368 21e87c46 Avi Kivity
        break;
3369 eaa728ee bellard
    default:
3370 79c4f6b0 Huang Ying
        if ((uint32_t)ECX >= MSR_MC0_CTL
3371 79c4f6b0 Huang Ying
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3372 79c4f6b0 Huang Ying
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3373 79c4f6b0 Huang Ying
            if ((offset & 0x3) != 0
3374 20054ef0 Blue Swirl
                || (val == 0 || val == ~(uint64_t)0)) {
3375 79c4f6b0 Huang Ying
                env->mce_banks[offset] = val;
3376 20054ef0 Blue Swirl
            }
3377 79c4f6b0 Huang Ying
            break;
3378 79c4f6b0 Huang Ying
        }
3379 20054ef0 Blue Swirl
        /* XXX: exception? */
3380 eaa728ee bellard
        break;
3381 eaa728ee bellard
    }
3382 eaa728ee bellard
}
3383 eaa728ee bellard
3384 eaa728ee bellard
void helper_rdmsr(void)
3385 eaa728ee bellard
{
3386 eaa728ee bellard
    uint64_t val;
3387 872929aa bellard
3388 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3389 872929aa bellard
3390 20054ef0 Blue Swirl
    switch ((uint32_t)ECX) {
3391 eaa728ee bellard
    case MSR_IA32_SYSENTER_CS:
3392 eaa728ee bellard
        val = env->sysenter_cs;
3393 eaa728ee bellard
        break;
3394 eaa728ee bellard
    case MSR_IA32_SYSENTER_ESP:
3395 eaa728ee bellard
        val = env->sysenter_esp;
3396 eaa728ee bellard
        break;
3397 eaa728ee bellard
    case MSR_IA32_SYSENTER_EIP:
3398 eaa728ee bellard
        val = env->sysenter_eip;
3399 eaa728ee bellard
        break;
3400 eaa728ee bellard
    case MSR_IA32_APICBASE:
3401 4a942cea Blue Swirl
        val = cpu_get_apic_base(env->apic_state);
3402 eaa728ee bellard
        break;
3403 eaa728ee bellard
    case MSR_EFER:
3404 eaa728ee bellard
        val = env->efer;
3405 eaa728ee bellard
        break;
3406 eaa728ee bellard
    case MSR_STAR:
3407 eaa728ee bellard
        val = env->star;
3408 eaa728ee bellard
        break;
3409 eaa728ee bellard
    case MSR_PAT:
3410 eaa728ee bellard
        val = env->pat;
3411 eaa728ee bellard
        break;
3412 eaa728ee bellard
    case MSR_VM_HSAVE_PA:
3413 eaa728ee bellard
        val = env->vm_hsave;
3414 eaa728ee bellard
        break;
3415 d5e49a81 balrog
    case MSR_IA32_PERF_STATUS:
3416 d5e49a81 balrog
        /* tsc_increment_by_tick */
3417 d5e49a81 balrog
        val = 1000ULL;
3418 d5e49a81 balrog
        /* CPU multiplier */
3419 d5e49a81 balrog
        val |= (((uint64_t)4ULL) << 40);
3420 d5e49a81 balrog
        break;
3421 eaa728ee bellard
#ifdef TARGET_X86_64
3422 eaa728ee bellard
    case MSR_LSTAR:
3423 eaa728ee bellard
        val = env->lstar;
3424 eaa728ee bellard
        break;
3425 eaa728ee bellard
    case MSR_CSTAR:
3426 eaa728ee bellard
        val = env->cstar;
3427 eaa728ee bellard
        break;
3428 eaa728ee bellard
    case MSR_FMASK:
3429 eaa728ee bellard
        val = env->fmask;
3430 eaa728ee bellard
        break;
3431 eaa728ee bellard
    case MSR_FSBASE:
3432 eaa728ee bellard
        val = env->segs[R_FS].base;
3433 eaa728ee bellard
        break;
3434 eaa728ee bellard
    case MSR_GSBASE:
3435 eaa728ee bellard
        val = env->segs[R_GS].base;
3436 eaa728ee bellard
        break;
3437 eaa728ee bellard
    case MSR_KERNELGSBASE:
3438 eaa728ee bellard
        val = env->kernelgsbase;
3439 eaa728ee bellard
        break;
3440 1b050077 Andre Przywara
    case MSR_TSC_AUX:
3441 1b050077 Andre Przywara
        val = env->tsc_aux;
3442 1b050077 Andre Przywara
        break;
3443 eaa728ee bellard
#endif
3444 165d9b82 aliguori
    case MSR_MTRRphysBase(0):
3445 165d9b82 aliguori
    case MSR_MTRRphysBase(1):
3446 165d9b82 aliguori
    case MSR_MTRRphysBase(2):
3447 165d9b82 aliguori
    case MSR_MTRRphysBase(3):
3448 165d9b82 aliguori
    case MSR_MTRRphysBase(4):
3449 165d9b82 aliguori
    case MSR_MTRRphysBase(5):
3450 165d9b82 aliguori
    case MSR_MTRRphysBase(6):
3451 165d9b82 aliguori
    case MSR_MTRRphysBase(7):
3452 165d9b82 aliguori
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;
3453 165d9b82 aliguori
        break;
3454 165d9b82 aliguori
    case MSR_MTRRphysMask(0):
3455 165d9b82 aliguori
    case MSR_MTRRphysMask(1):
3456 165d9b82 aliguori
    case MSR_MTRRphysMask(2):
3457 165d9b82 aliguori
    case MSR_MTRRphysMask(3):
3458 165d9b82 aliguori
    case MSR_MTRRphysMask(4):
3459 165d9b82 aliguori
    case MSR_MTRRphysMask(5):
3460 165d9b82 aliguori
    case MSR_MTRRphysMask(6):
3461 165d9b82 aliguori
    case MSR_MTRRphysMask(7):
3462 165d9b82 aliguori
        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;
3463 165d9b82 aliguori
        break;
3464 165d9b82 aliguori
    case MSR_MTRRfix64K_00000:
3465 165d9b82 aliguori
        val = env->mtrr_fixed[0];
3466 165d9b82 aliguori
        break;
3467 165d9b82 aliguori
    case MSR_MTRRfix16K_80000:
3468 165d9b82 aliguori
    case MSR_MTRRfix16K_A0000:
3469 165d9b82 aliguori
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];
3470 165d9b82 aliguori
        break;
3471 165d9b82 aliguori
    case MSR_MTRRfix4K_C0000:
3472 165d9b82 aliguori
    case MSR_MTRRfix4K_C8000:
3473 165d9b82 aliguori
    case MSR_MTRRfix4K_D0000:
3474 165d9b82 aliguori
    case MSR_MTRRfix4K_D8000:
3475 165d9b82 aliguori
    case MSR_MTRRfix4K_E0000:
3476 165d9b82 aliguori
    case MSR_MTRRfix4K_E8000:
3477 165d9b82 aliguori
    case MSR_MTRRfix4K_F0000:
3478 165d9b82 aliguori
    case MSR_MTRRfix4K_F8000:
3479 165d9b82 aliguori
        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];
3480 165d9b82 aliguori
        break;
3481 165d9b82 aliguori
    case MSR_MTRRdefType:
3482 165d9b82 aliguori
        val = env->mtrr_deftype;
3483 165d9b82 aliguori
        break;
3484 dd5e3b17 aliguori
    case MSR_MTRRcap:
3485 20054ef0 Blue Swirl
        if (env->cpuid_features & CPUID_MTRR) {
3486 20054ef0 Blue Swirl
            val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT |
3487 20054ef0 Blue Swirl
                MSR_MTRRcap_WC_SUPPORTED;
3488 20054ef0 Blue Swirl
        } else {
3489 20054ef0 Blue Swirl
            /* XXX: exception? */
3490 dd5e3b17 aliguori
            val = 0;
3491 20054ef0 Blue Swirl
        }
3492 dd5e3b17 aliguori
        break;
3493 79c4f6b0 Huang Ying
    case MSR_MCG_CAP:
3494 79c4f6b0 Huang Ying
        val = env->mcg_cap;
3495 79c4f6b0 Huang Ying
        break;
3496 79c4f6b0 Huang Ying
    case MSR_MCG_CTL:
3497 20054ef0 Blue Swirl
        if (env->mcg_cap & MCG_CTL_P) {
3498 79c4f6b0 Huang Ying
            val = env->mcg_ctl;
3499 20054ef0 Blue Swirl
        } else {
3500 79c4f6b0 Huang Ying
            val = 0;
3501 20054ef0 Blue Swirl
        }
3502 79c4f6b0 Huang Ying
        break;
3503 79c4f6b0 Huang Ying
    case MSR_MCG_STATUS:
3504 79c4f6b0 Huang Ying
        val = env->mcg_status;
3505 79c4f6b0 Huang Ying
        break;
3506 21e87c46 Avi Kivity
    case MSR_IA32_MISC_ENABLE:
3507 21e87c46 Avi Kivity
        val = env->msr_ia32_misc_enable;
3508 21e87c46 Avi Kivity
        break;
3509 eaa728ee bellard
    default:
3510 79c4f6b0 Huang Ying
        if ((uint32_t)ECX >= MSR_MC0_CTL
3511 79c4f6b0 Huang Ying
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3512 79c4f6b0 Huang Ying
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3513 79c4f6b0 Huang Ying
            val = env->mce_banks[offset];
3514 79c4f6b0 Huang Ying
            break;
3515 79c4f6b0 Huang Ying
        }
3516 20054ef0 Blue Swirl
        /* XXX: exception? */
3517 eaa728ee bellard
        val = 0;
3518 eaa728ee bellard
        break;
3519 eaa728ee bellard
    }
3520 eaa728ee bellard
    EAX = (uint32_t)(val);
3521 eaa728ee bellard
    EDX = (uint32_t)(val >> 32);
3522 eaa728ee bellard
}
3523 eaa728ee bellard
#endif
3524 eaa728ee bellard
3525 eaa728ee bellard
target_ulong helper_lsl(target_ulong selector1)
3526 eaa728ee bellard
{
3527 eaa728ee bellard
    unsigned int limit;
3528 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3529 eaa728ee bellard
    int rpl, dpl, cpl, type;
3530 eaa728ee bellard
3531 eaa728ee bellard
    selector = selector1 & 0xffff;
3532 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3533 20054ef0 Blue Swirl
    if ((selector & 0xfffc) == 0) {
3534 dc1ded53 aliguori
        goto fail;
3535 20054ef0 Blue Swirl
    }
3536 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, selector) != 0) {
3537 eaa728ee bellard
        goto fail;
3538 20054ef0 Blue Swirl
    }
3539 eaa728ee bellard
    rpl = selector & 3;
3540 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3541 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3542 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
3543 eaa728ee bellard
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3544 eaa728ee bellard
            /* conforming */
3545 eaa728ee bellard
        } else {
3546 20054ef0 Blue Swirl
            if (dpl < cpl || dpl < rpl) {
3547 eaa728ee bellard
                goto fail;
3548 20054ef0 Blue Swirl
            }
3549 eaa728ee bellard
        }
3550 eaa728ee bellard
    } else {
3551 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3552 20054ef0 Blue Swirl
        switch (type) {
3553 eaa728ee bellard
        case 1:
3554 eaa728ee bellard
        case 2:
3555 eaa728ee bellard
        case 3:
3556 eaa728ee bellard
        case 9:
3557 eaa728ee bellard
        case 11:
3558 eaa728ee bellard
            break;
3559 eaa728ee bellard
        default:
3560 eaa728ee bellard
            goto fail;
3561 eaa728ee bellard
        }
3562 eaa728ee bellard
        if (dpl < cpl || dpl < rpl) {
3563 eaa728ee bellard
        fail:
3564 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3565 eaa728ee bellard
            return 0;
3566 eaa728ee bellard
        }
3567 eaa728ee bellard
    }
3568 eaa728ee bellard
    limit = get_seg_limit(e1, e2);
3569 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3570 eaa728ee bellard
    return limit;
3571 eaa728ee bellard
}
3572 eaa728ee bellard
3573 eaa728ee bellard
target_ulong helper_lar(target_ulong selector1)
3574 eaa728ee bellard
{
3575 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3576 eaa728ee bellard
    int rpl, dpl, cpl, type;
3577 eaa728ee bellard
3578 eaa728ee bellard
    selector = selector1 & 0xffff;
3579 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3580 20054ef0 Blue Swirl
    if ((selector & 0xfffc) == 0) {
3581 eaa728ee bellard
        goto fail;
3582 20054ef0 Blue Swirl
    }
3583 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, selector) != 0) {
3584 eaa728ee bellard
        goto fail;
3585 20054ef0 Blue Swirl
    }
3586 eaa728ee bellard
    rpl = selector & 3;
3587 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3588 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3589 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
3590 eaa728ee bellard
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3591 eaa728ee bellard
            /* conforming */
3592 eaa728ee bellard
        } else {
3593 20054ef0 Blue Swirl
            if (dpl < cpl || dpl < rpl) {
3594 eaa728ee bellard
                goto fail;
3595 20054ef0 Blue Swirl
            }
3596 eaa728ee bellard
        }
3597 eaa728ee bellard
    } else {
3598 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3599 20054ef0 Blue Swirl
        switch (type) {
3600 eaa728ee bellard
        case 1:
3601 eaa728ee bellard
        case 2:
3602 eaa728ee bellard
        case 3:
3603 eaa728ee bellard
        case 4:
3604 eaa728ee bellard
        case 5:
3605 eaa728ee bellard
        case 9:
3606 eaa728ee bellard
        case 11:
3607 eaa728ee bellard
        case 12:
3608 eaa728ee bellard
            break;
3609 eaa728ee bellard
        default:
3610 eaa728ee bellard
            goto fail;
3611 eaa728ee bellard
        }
3612 eaa728ee bellard
        if (dpl < cpl || dpl < rpl) {
3613 eaa728ee bellard
        fail:
3614 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3615 eaa728ee bellard
            return 0;
3616 eaa728ee bellard
        }
3617 eaa728ee bellard
    }
3618 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3619 eaa728ee bellard
    return e2 & 0x00f0ff00;
3620 eaa728ee bellard
}
3621 eaa728ee bellard
3622 eaa728ee bellard
void helper_verr(target_ulong selector1)
3623 eaa728ee bellard
{
3624 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3625 eaa728ee bellard
    int rpl, dpl, cpl;
3626 eaa728ee bellard
3627 eaa728ee bellard
    selector = selector1 & 0xffff;
3628 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3629 20054ef0 Blue Swirl
    if ((selector & 0xfffc) == 0) {
3630 eaa728ee bellard
        goto fail;
3631 20054ef0 Blue Swirl
    }
3632 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, selector) != 0) {
3633 eaa728ee bellard
        goto fail;
3634 20054ef0 Blue Swirl
    }
3635 20054ef0 Blue Swirl
    if (!(e2 & DESC_S_MASK)) {
3636 eaa728ee bellard
        goto fail;
3637 20054ef0 Blue Swirl
    }
3638 eaa728ee bellard
    rpl = selector & 3;
3639 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3640 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3641 eaa728ee bellard
    if (e2 & DESC_CS_MASK) {
3642 20054ef0 Blue Swirl
        if (!(e2 & DESC_R_MASK)) {
3643 eaa728ee bellard
            goto fail;
3644 20054ef0 Blue Swirl
        }
3645 eaa728ee bellard
        if (!(e2 & DESC_C_MASK)) {
3646 20054ef0 Blue Swirl
            if (dpl < cpl || dpl < rpl) {
3647 eaa728ee bellard
                goto fail;
3648 20054ef0 Blue Swirl
            }
3649 eaa728ee bellard
        }
3650 eaa728ee bellard
    } else {
3651 eaa728ee bellard
        if (dpl < cpl || dpl < rpl) {
3652 eaa728ee bellard
        fail:
3653 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3654 eaa728ee bellard
            return;
3655 eaa728ee bellard
        }
3656 eaa728ee bellard
    }
3657 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3658 eaa728ee bellard
}
3659 eaa728ee bellard
3660 eaa728ee bellard
void helper_verw(target_ulong selector1)
3661 eaa728ee bellard
{
3662 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3663 eaa728ee bellard
    int rpl, dpl, cpl;
3664 eaa728ee bellard
3665 eaa728ee bellard
    selector = selector1 & 0xffff;
3666 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3667 20054ef0 Blue Swirl
    if ((selector & 0xfffc) == 0) {
3668 eaa728ee bellard
        goto fail;
3669 20054ef0 Blue Swirl
    }
3670 20054ef0 Blue Swirl
    if (load_segment(&e1, &e2, selector) != 0) {
3671 eaa728ee bellard
        goto fail;
3672 20054ef0 Blue Swirl
    }
3673 20054ef0 Blue Swirl
    if (!(e2 & DESC_S_MASK)) {
3674 eaa728ee bellard
        goto fail;
3675 20054ef0 Blue Swirl
    }
3676 eaa728ee bellard
    rpl = selector & 3;
3677 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3678 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3679 eaa728ee bellard
    if (e2 & DESC_CS_MASK) {
3680 eaa728ee bellard
        goto fail;
3681 eaa728ee bellard
    } else {
3682 20054ef0 Blue Swirl
        if (dpl < cpl || dpl < rpl) {
3683 eaa728ee bellard
            goto fail;
3684 20054ef0 Blue Swirl
        }
3685 eaa728ee bellard
        if (!(e2 & DESC_W_MASK)) {
3686 eaa728ee bellard
        fail:
3687 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3688 eaa728ee bellard
            return;
3689 eaa728ee bellard
        }
3690 eaa728ee bellard
    }
3691 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3692 eaa728ee bellard
}
3693 eaa728ee bellard
3694 f299f437 Blue Swirl
#if defined(CONFIG_USER_ONLY)
3695 f299f437 Blue Swirl
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
3696 eaa728ee bellard
{
3697 f299f437 Blue Swirl
    CPUX86State *saved_env;
3698 eaa728ee bellard
3699 f299f437 Blue Swirl
    saved_env = env;
3700 f299f437 Blue Swirl
    env = s;
3701 f299f437 Blue Swirl
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
3702 f299f437 Blue Swirl
        selector &= 0xffff;
3703 f299f437 Blue Swirl
        cpu_x86_load_seg_cache(env, seg_reg, selector,
3704 f299f437 Blue Swirl
                               (selector << 4), 0xffff, 0);
3705 f299f437 Blue Swirl
    } else {
3706 f299f437 Blue Swirl
        helper_load_seg(seg_reg, selector);
3707 13822781 Aurelien Jarno
    }
3708 f299f437 Blue Swirl
    env = saved_env;
3709 eaa728ee bellard
}
3710 eaa728ee bellard
#endif
3711 20054ef0 Blue Swirl
3712 f299f437 Blue Swirl
#ifdef TARGET_X86_64
3713 f299f437 Blue Swirl
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3714 eaa728ee bellard
{
3715 f299f437 Blue Swirl
    *plow += a;
3716 f299f437 Blue Swirl
    /* carry test */
3717 f299f437 Blue Swirl
    if (*plow < a) {
3718 f299f437 Blue Swirl
        (*phigh)++;
3719 f299f437 Blue Swirl
    }
3720 f299f437 Blue Swirl
    *phigh += b;
3721 eaa728ee bellard
}
3722 eaa728ee bellard
3723 f299f437 Blue Swirl
static void neg128(uint64_t *plow, uint64_t *phigh)
3724 eaa728ee bellard
{
3725 f299f437 Blue Swirl
    *plow = ~*plow;
3726 f299f437 Blue Swirl
    *phigh = ~*phigh;
3727 f299f437 Blue Swirl
    add128(plow, phigh, 1, 0);
3728 eaa728ee bellard
}
3729 eaa728ee bellard
3730 f299f437 Blue Swirl
/* return TRUE if overflow */
3731 f299f437 Blue Swirl
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3732 eaa728ee bellard
{
3733 f299f437 Blue Swirl
    uint64_t q, r, a1, a0;
3734 f299f437 Blue Swirl
    int i, qb, ab;
3735 20054ef0 Blue Swirl
3736 f299f437 Blue Swirl
    a0 = *plow;
3737 f299f437 Blue Swirl
    a1 = *phigh;
3738 f299f437 Blue Swirl
    if (a1 == 0) {
3739 f299f437 Blue Swirl
        q = a0 / b;
3740 f299f437 Blue Swirl
        r = a0 % b;
3741 f299f437 Blue Swirl
        *plow = q;
3742 f299f437 Blue Swirl
        *phigh = r;
3743 f299f437 Blue Swirl
    } else {
3744 f299f437 Blue Swirl
        if (a1 >= b) {
3745 f299f437 Blue Swirl
            return 1;
3746 f299f437 Blue Swirl
        }
3747 f299f437 Blue Swirl
        /* XXX: use a better algorithm */
3748 f299f437 Blue Swirl
        for (i = 0; i < 64; i++) {
3749 f299f437 Blue Swirl
            ab = a1 >> 63;
3750 f299f437 Blue Swirl
            a1 = (a1 << 1) | (a0 >> 63);
3751 f299f437 Blue Swirl
            if (ab || a1 >= b) {
3752 f299f437 Blue Swirl
                a1 -= b;
3753 f299f437 Blue Swirl
                qb = 1;
3754 f299f437 Blue Swirl
            } else {
3755 f299f437 Blue Swirl
                qb = 0;
3756 f299f437 Blue Swirl
            }
3757 f299f437 Blue Swirl
            a0 = (a0 << 1) | qb;
3758 f299f437 Blue Swirl
        }
3759 f299f437 Blue Swirl
#if defined(DEBUG_MULDIV)
3760 f299f437 Blue Swirl
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64
3761 f299f437 Blue Swirl
               ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
3762 f299f437 Blue Swirl
               *phigh, *plow, b, a0, a1);
3763 f299f437 Blue Swirl
#endif
3764 f299f437 Blue Swirl
        *plow = a0;
3765 f299f437 Blue Swirl
        *phigh = a1;
3766 f299f437 Blue Swirl
    }
3767 f299f437 Blue Swirl
    return 0;
3768 eaa728ee bellard
}
3769 eaa728ee bellard
3770 f299f437 Blue Swirl
/* return TRUE if overflow */
3771 f299f437 Blue Swirl
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
3772 eaa728ee bellard
{
3773 f299f437 Blue Swirl
    int sa, sb;
3774 20054ef0 Blue Swirl
3775 f299f437 Blue Swirl
    sa = ((int64_t)*phigh < 0);
3776 f299f437 Blue Swirl
    if (sa) {
3777 f299f437 Blue Swirl
        neg128(plow, phigh);
3778 f299f437 Blue Swirl
    }
3779 f299f437 Blue Swirl
    sb = (b < 0);
3780 f299f437 Blue Swirl
    if (sb) {
3781 f299f437 Blue Swirl
        b = -b;
3782 f299f437 Blue Swirl
    }
3783 f299f437 Blue Swirl
    if (div64(plow, phigh, b) != 0) {
3784 f299f437 Blue Swirl
        return 1;
3785 f299f437 Blue Swirl
    }
3786 f299f437 Blue Swirl
    if (sa ^ sb) {
3787 f299f437 Blue Swirl
        if (*plow > (1ULL << 63)) {
3788 f299f437 Blue Swirl
            return 1;
3789 f299f437 Blue Swirl
        }
3790 f299f437 Blue Swirl
        *plow = -*plow;
3791 f299f437 Blue Swirl
    } else {
3792 f299f437 Blue Swirl
        if (*plow >= (1ULL << 63)) {
3793 f299f437 Blue Swirl
            return 1;
3794 f299f437 Blue Swirl
        }
3795 f299f437 Blue Swirl
    }
3796 f299f437 Blue Swirl
    if (sa) {
3797 f299f437 Blue Swirl
        *phigh = -*phigh;
3798 f299f437 Blue Swirl
    }
3799 f299f437 Blue Swirl
    return 0;
3800 eaa728ee bellard
}
3801 eaa728ee bellard
3802 f299f437 Blue Swirl
void helper_mulq_EAX_T0(target_ulong t0)
3803 eaa728ee bellard
{
3804 f299f437 Blue Swirl
    uint64_t r0, r1;
3805 20054ef0 Blue Swirl
3806 f299f437 Blue Swirl
    mulu64(&r0, &r1, EAX, t0);
3807 f299f437 Blue Swirl
    EAX = r0;
3808 f299f437 Blue Swirl
    EDX = r1;
3809 f299f437 Blue Swirl
    CC_DST = r0;
3810 f299f437 Blue Swirl
    CC_SRC = r1;
3811 eaa728ee bellard
}
3812 eaa728ee bellard
3813 f299f437 Blue Swirl
void helper_imulq_EAX_T0(target_ulong t0)
3814 eaa728ee bellard
{
3815 f299f437 Blue Swirl
    uint64_t r0, r1;
3816 20054ef0 Blue Swirl
3817 f299f437 Blue Swirl
    muls64(&r0, &r1, EAX, t0);
3818 f299f437 Blue Swirl
    EAX = r0;
3819 f299f437 Blue Swirl
    EDX = r1;
3820 f299f437 Blue Swirl
    CC_DST = r0;
3821 f299f437 Blue Swirl
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3822 eaa728ee bellard
}
3823 eaa728ee bellard
3824 f299f437 Blue Swirl
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
3825 eaa728ee bellard
{
3826 f299f437 Blue Swirl
    uint64_t r0, r1;
3827 20054ef0 Blue Swirl
3828 f299f437 Blue Swirl
    muls64(&r0, &r1, t0, t1);
3829 f299f437 Blue Swirl
    CC_DST = r0;
3830 f299f437 Blue Swirl
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3831 f299f437 Blue Swirl
    return r0;
3832 eaa728ee bellard
}
3833 eaa728ee bellard
3834 f299f437 Blue Swirl
void helper_divq_EAX(target_ulong t0)
3835 eaa728ee bellard
{
3836 f299f437 Blue Swirl
    uint64_t r0, r1;
3837 20054ef0 Blue Swirl
3838 f299f437 Blue Swirl
    if (t0 == 0) {
3839 f299f437 Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
3840 f299f437 Blue Swirl
    }
3841 f299f437 Blue Swirl
    r0 = EAX;
3842 f299f437 Blue Swirl
    r1 = EDX;
3843 f299f437 Blue Swirl
    if (div64(&r0, &r1, t0)) {
3844 f299f437 Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
3845 f299f437 Blue Swirl
    }
3846 f299f437 Blue Swirl
    EAX = r0;
3847 f299f437 Blue Swirl
    EDX = r1;
3848 eaa728ee bellard
}
3849 eaa728ee bellard
3850 f299f437 Blue Swirl
void helper_idivq_EAX(target_ulong t0)
3851 eaa728ee bellard
{
3852 f299f437 Blue Swirl
    uint64_t r0, r1;
3853 20054ef0 Blue Swirl
3854 f299f437 Blue Swirl
    if (t0 == 0) {
3855 f299f437 Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
3856 20054ef0 Blue Swirl
    }
3857 f299f437 Blue Swirl
    r0 = EAX;
3858 f299f437 Blue Swirl
    r1 = EDX;
3859 f299f437 Blue Swirl
    if (idiv64(&r0, &r1, t0)) {
3860 f299f437 Blue Swirl
        raise_exception(env, EXCP00_DIVZ);
3861 f299f437 Blue Swirl
    }
3862 f299f437 Blue Swirl
    EAX = r0;
3863 f299f437 Blue Swirl
    EDX = r1;
3864 eaa728ee bellard
}
3865 f299f437 Blue Swirl
#endif
3866 eaa728ee bellard
3867 f299f437 Blue Swirl
static void do_hlt(void)
3868 eaa728ee bellard
{
3869 f299f437 Blue Swirl
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
3870 f299f437 Blue Swirl
    env->halted = 1;
3871 f299f437 Blue Swirl
    env->exception_index = EXCP_HLT;
3872 f299f437 Blue Swirl
    cpu_loop_exit(env);
3873 eaa728ee bellard
}
3874 eaa728ee bellard
3875 f299f437 Blue Swirl
void helper_hlt(int next_eip_addend)
3876 eaa728ee bellard
{
3877 f299f437 Blue Swirl
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
3878 f299f437 Blue Swirl
    EIP += next_eip_addend;
3879 20054ef0 Blue Swirl
3880 f299f437 Blue Swirl
    do_hlt();
3881 eaa728ee bellard
}
3882 eaa728ee bellard
3883 f299f437 Blue Swirl
void helper_monitor(target_ulong ptr)
3884 eaa728ee bellard
{
3885 f299f437 Blue Swirl
    if ((uint32_t)ECX != 0) {
3886 f299f437 Blue Swirl
        raise_exception(env, EXCP0D_GPF);
3887 20054ef0 Blue Swirl
    }
3888 f299f437 Blue Swirl
    /* XXX: store address? */
3889 f299f437 Blue Swirl
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
3890 eaa728ee bellard
}
3891 eaa728ee bellard
3892 f299f437 Blue Swirl
void helper_mwait(int next_eip_addend)
3893 eaa728ee bellard
{
3894 f299f437 Blue Swirl
    if ((uint32_t)ECX != 0) {
3895 f299f437 Blue Swirl
        raise_exception(env, EXCP0D_GPF);
3896 f299f437 Blue Swirl
    }
3897 f299f437 Blue Swirl
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
3898 f299f437 Blue Swirl
    EIP += next_eip_addend;
3899 20054ef0 Blue Swirl
3900 f299f437 Blue Swirl
    /* XXX: not complete but not completely erroneous */
3901 f299f437 Blue Swirl
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
3902 f299f437 Blue Swirl
        /* more than one CPU: do not sleep because another CPU may
3903 f299f437 Blue Swirl
           wake this one */
3904 f299f437 Blue Swirl
    } else {
3905 f299f437 Blue Swirl
        do_hlt();
3906 f299f437 Blue Swirl
    }
3907 eaa728ee bellard
}
3908 eaa728ee bellard
3909 f299f437 Blue Swirl
void helper_debug(void)
3910 eaa728ee bellard
{
3911 f299f437 Blue Swirl
    env->exception_index = EXCP_DEBUG;
3912 f299f437 Blue Swirl
    cpu_loop_exit(env);
3913 eaa728ee bellard
}
3914 eaa728ee bellard
3915 f299f437 Blue Swirl
void helper_reset_rf(void)
3916 eaa728ee bellard
{
3917 f299f437 Blue Swirl
    env->eflags &= ~RF_MASK;
3918 eaa728ee bellard
}
3919 eaa728ee bellard
3920 f299f437 Blue Swirl
void helper_cli(void)
3921 eaa728ee bellard
{
3922 f299f437 Blue Swirl
    env->eflags &= ~IF_MASK;
3923 eaa728ee bellard
}
3924 eaa728ee bellard
3925 f299f437 Blue Swirl
void helper_sti(void)
3926 eaa728ee bellard
{
3927 f299f437 Blue Swirl
    env->eflags |= IF_MASK;
3928 eaa728ee bellard
}
3929 eaa728ee bellard
3930 f299f437 Blue Swirl
#if 0
3931 f299f437 Blue Swirl
/* vm86plus instructions */
3932 f299f437 Blue Swirl
void helper_cli_vm(void)
3933 eaa728ee bellard
{
3934 f299f437 Blue Swirl
    env->eflags &= ~VIF_MASK;
3935 eaa728ee bellard
}
3936 eaa728ee bellard

3937 f299f437 Blue Swirl
void helper_sti_vm(void)
3938 eaa728ee bellard
{
3939 f299f437 Blue Swirl
    env->eflags |= VIF_MASK;
3940 f299f437 Blue Swirl
    if (env->eflags & VIP_MASK) {
3941 f299f437 Blue Swirl
        raise_exception(env, EXCP0D_GPF);
3942 f299f437 Blue Swirl
    }
3943 eaa728ee bellard
}
3944 f299f437 Blue Swirl
#endif
3945 eaa728ee bellard
3946 f299f437 Blue Swirl
void helper_set_inhibit_irq(void)
3947 eaa728ee bellard
{
3948 f299f437 Blue Swirl
    env->hflags |= HF_INHIBIT_IRQ_MASK;
3949 eaa728ee bellard
}
3950 eaa728ee bellard
3951 f299f437 Blue Swirl
void helper_reset_inhibit_irq(void)
3952 eaa728ee bellard
{
3953 f299f437 Blue Swirl
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
3954 eaa728ee bellard
}
3955 eaa728ee bellard
3956 f299f437 Blue Swirl
void helper_boundw(target_ulong a0, int v)
3957 eaa728ee bellard
{
3958 f299f437 Blue Swirl
    int low, high;
3959 eaa728ee bellard
3960 f299f437 Blue Swirl
    low = ldsw(a0);
3961 f299f437 Blue Swirl
    high = ldsw(a0 + 2);
3962 f299f437 Blue Swirl
    v = (int16_t)v;
3963 f299f437 Blue Swirl
    if (v < low || v > high) {
3964 f299f437 Blue Swirl
        raise_exception(env, EXCP05_BOUND);
3965 f299f437 Blue Swirl
    }
3966 eaa728ee bellard
}
3967 eaa728ee bellard
3968 f299f437 Blue Swirl
void helper_boundl(target_ulong a0, int v)
3969 eaa728ee bellard
{
3970 f299f437 Blue Swirl
    int low, high;
3971 eaa728ee bellard
3972 f299f437 Blue Swirl
    low = ldl(a0);
3973 f299f437 Blue Swirl
    high = ldl(a0 + 4);
3974 f299f437 Blue Swirl
    if (v < low || v > high) {
3975 f299f437 Blue Swirl
        raise_exception(env, EXCP05_BOUND);
3976 f299f437 Blue Swirl
    }
3977 eaa728ee bellard
}
3978 eaa728ee bellard
3979 eaa728ee bellard
#if !defined(CONFIG_USER_ONLY)
3980 eaa728ee bellard
3981 eaa728ee bellard
#define MMUSUFFIX _mmu
3982 eaa728ee bellard
3983 eaa728ee bellard
#define SHIFT 0
3984 eaa728ee bellard
#include "softmmu_template.h"
3985 eaa728ee bellard
3986 eaa728ee bellard
#define SHIFT 1
3987 eaa728ee bellard
#include "softmmu_template.h"
3988 eaa728ee bellard
3989 eaa728ee bellard
#define SHIFT 2
3990 eaa728ee bellard
#include "softmmu_template.h"
3991 eaa728ee bellard
3992 eaa728ee bellard
#define SHIFT 3
3993 eaa728ee bellard
#include "softmmu_template.h"
3994 eaa728ee bellard
3995 eaa728ee bellard
#endif
3996 eaa728ee bellard
3997 d9957a8b blueswir1
#if !defined(CONFIG_USER_ONLY)
3998 eaa728ee bellard
/* try to fill the TLB and return an exception if error. If retaddr is
3999 eaa728ee bellard
   NULL, it means that the function was called in C code (i.e. not
4000 eaa728ee bellard
   from generated code or from helper.c) */
4001 eaa728ee bellard
/* XXX: fix it to restore all registers */
4002 317ac620 Andreas Färber
void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx,
4003 20503968 Blue Swirl
              uintptr_t retaddr)
4004 eaa728ee bellard
{
4005 eaa728ee bellard
    TranslationBlock *tb;
4006 eaa728ee bellard
    int ret;
4007 eaa728ee bellard
    CPUX86State *saved_env;
4008 eaa728ee bellard
4009 eaa728ee bellard
    saved_env = env;
4010 bccd9ec5 Blue Swirl
    env = env1;
4011 eaa728ee bellard
4012 97b348e7 Blue Swirl
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx);
4013 eaa728ee bellard
    if (ret) {
4014 eaa728ee bellard
        if (retaddr) {
4015 eaa728ee bellard
            /* now we have a real cpu fault */
4016 20503968 Blue Swirl
            tb = tb_find_pc(retaddr);
4017 eaa728ee bellard
            if (tb) {
4018 eaa728ee bellard
                /* the PC is inside the translated code. It means that we have
4019 eaa728ee bellard
                   a virtual CPU fault */
4020 20503968 Blue Swirl
                cpu_restore_state(tb, env, retaddr);
4021 eaa728ee bellard
            }
4022 eaa728ee bellard
        }
4023 77b2bc2c Blue Swirl
        raise_exception_err(env, env->exception_index, env->error_code);
4024 eaa728ee bellard
    }
4025 eaa728ee bellard
    env = saved_env;
4026 eaa728ee bellard
}
4027 d9957a8b blueswir1
#endif
4028 eaa728ee bellard
4029 eaa728ee bellard
/* Secure Virtual Machine helpers */
4030 eaa728ee bellard
4031 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
4032 eaa728ee bellard
4033 db620f46 bellard
void helper_vmrun(int aflag, int next_eip_addend)
4034 20054ef0 Blue Swirl
{
4035 eaa728ee bellard
}
4036 20054ef0 Blue Swirl
4037 20054ef0 Blue Swirl
void helper_vmmcall(void)
4038 20054ef0 Blue Swirl
{
4039 eaa728ee bellard
}
4040 20054ef0 Blue Swirl
4041 914178d3 bellard
void helper_vmload(int aflag)
4042 20054ef0 Blue Swirl
{
4043 eaa728ee bellard
}
4044 20054ef0 Blue Swirl
4045 914178d3 bellard
void helper_vmsave(int aflag)
4046 20054ef0 Blue Swirl
{
4047 eaa728ee bellard
}
4048 20054ef0 Blue Swirl
4049 872929aa bellard
void helper_stgi(void)
4050 872929aa bellard
{
4051 872929aa bellard
}
4052 20054ef0 Blue Swirl
4053 872929aa bellard
void helper_clgi(void)
4054 872929aa bellard
{
4055 872929aa bellard
}
4056 20054ef0 Blue Swirl
4057 20054ef0 Blue Swirl
void helper_skinit(void)
4058 20054ef0 Blue Swirl
{
4059 eaa728ee bellard
}
4060 20054ef0 Blue Swirl
4061 914178d3 bellard
void helper_invlpga(int aflag)
4062 20054ef0 Blue Swirl
{
4063 eaa728ee bellard
}
4064 20054ef0 Blue Swirl
4065 20054ef0 Blue Swirl
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
4066 20054ef0 Blue Swirl
{
4067 eaa728ee bellard
}
4068 20054ef0 Blue Swirl
4069 77b2bc2c Blue Swirl
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1)
4070 77b2bc2c Blue Swirl
{
4071 77b2bc2c Blue Swirl
}
4072 77b2bc2c Blue Swirl
4073 eaa728ee bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4074 eaa728ee bellard
{
4075 eaa728ee bellard
}
4076 eaa728ee bellard
4077 77b2bc2c Blue Swirl
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
4078 77b2bc2c Blue Swirl
                                   uint64_t param)
4079 e694d4e2 Blue Swirl
{
4080 e694d4e2 Blue Swirl
}
4081 e694d4e2 Blue Swirl
4082 20054ef0 Blue Swirl
void helper_svm_check_io(uint32_t port, uint32_t param,
4083 eaa728ee bellard
                         uint32_t next_eip_addend)
4084 eaa728ee bellard
{
4085 eaa728ee bellard
}
4086 eaa728ee bellard
#else
4087 eaa728ee bellard
4088 c227f099 Anthony Liguori
static inline void svm_save_seg(target_phys_addr_t addr,
4089 872929aa bellard
                                const SegmentCache *sc)
4090 eaa728ee bellard
{
4091 20054ef0 Blue Swirl
    stw_phys(addr + offsetof(struct vmcb_seg, selector),
4092 872929aa bellard
             sc->selector);
4093 20054ef0 Blue Swirl
    stq_phys(addr + offsetof(struct vmcb_seg, base),
4094 872929aa bellard
             sc->base);
4095 20054ef0 Blue Swirl
    stl_phys(addr + offsetof(struct vmcb_seg, limit),
4096 872929aa bellard
             sc->limit);
4097 20054ef0 Blue Swirl
    stw_phys(addr + offsetof(struct vmcb_seg, attrib),
4098 e72210e1 bellard
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4099 872929aa bellard
}
4100 20054ef0 Blue Swirl
4101 c227f099 Anthony Liguori
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4102 872929aa bellard
{
4103 872929aa bellard
    unsigned int flags;
4104 872929aa bellard
4105 872929aa bellard
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4106 872929aa bellard
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4107 872929aa bellard
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4108 872929aa bellard
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4109 872929aa bellard
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4110 eaa728ee bellard
}
4111 eaa728ee bellard
4112 20054ef0 Blue Swirl
static inline void svm_load_seg_cache(target_phys_addr_t addr,
4113 317ac620 Andreas Färber
                                      CPUX86State *env, int seg_reg)
4114 eaa728ee bellard
{
4115 872929aa bellard
    SegmentCache sc1, *sc = &sc1;
4116 20054ef0 Blue Swirl
4117 872929aa bellard
    svm_load_seg(addr, sc);
4118 872929aa bellard
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4119 872929aa bellard
                           sc->base, sc->limit, sc->flags);
4120 eaa728ee bellard
}
4121 eaa728ee bellard
4122 db620f46 bellard
void helper_vmrun(int aflag, int next_eip_addend)
4123 eaa728ee bellard
{
4124 eaa728ee bellard
    target_ulong addr;
4125 eaa728ee bellard
    uint32_t event_inj;
4126 eaa728ee bellard
    uint32_t int_ctl;
4127 eaa728ee bellard
4128 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4129 872929aa bellard
4130 20054ef0 Blue Swirl
    if (aflag == 2) {
4131 914178d3 bellard
        addr = EAX;
4132 20054ef0 Blue Swirl
    } else {
4133 914178d3 bellard
        addr = (uint32_t)EAX;
4134 20054ef0 Blue Swirl
    }
4135 914178d3 bellard
4136 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
4137 eaa728ee bellard
4138 eaa728ee bellard
    env->vm_vmcb = addr;
4139 eaa728ee bellard
4140 eaa728ee bellard
    /* save the current CPU state in the hsave page */
4141 20054ef0 Blue Swirl
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base),
4142 20054ef0 Blue Swirl
             env->gdt.base);
4143 20054ef0 Blue Swirl
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit),
4144 20054ef0 Blue Swirl
             env->gdt.limit);
4145 eaa728ee bellard
4146 20054ef0 Blue Swirl
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base),
4147 20054ef0 Blue Swirl
             env->idt.base);
4148 20054ef0 Blue Swirl
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit),
4149 20054ef0 Blue Swirl
             env->idt.limit);
4150 eaa728ee bellard
4151 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4152 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4153 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4154 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4155 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4156 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4157 eaa728ee bellard
4158 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4159 20054ef0 Blue Swirl
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags),
4160 997ff0d9 Blue Swirl
             cpu_compute_eflags(env));
4161 eaa728ee bellard
4162 20054ef0 Blue Swirl
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es),
4163 20054ef0 Blue Swirl
                 &env->segs[R_ES]);
4164 20054ef0 Blue Swirl
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs),
4165 872929aa bellard
                 &env->segs[R_CS]);
4166 20054ef0 Blue Swirl
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss),
4167 872929aa bellard
                 &env->segs[R_SS]);
4168 20054ef0 Blue Swirl
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds),
4169 872929aa bellard
                 &env->segs[R_DS]);
4170 eaa728ee bellard
4171 db620f46 bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
4172 db620f46 bellard
             EIP + next_eip_addend);
4173 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4174 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4175 eaa728ee bellard
4176 eaa728ee bellard
    /* load the interception bitmaps so we do not need to access the
4177 eaa728ee bellard
       vmcb in svm mode */
4178 20054ef0 Blue Swirl
    env->intercept = ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4179 20054ef0 Blue Swirl
                                                      control.intercept));
4180 20054ef0 Blue Swirl
    env->intercept_cr_read = lduw_phys(env->vm_vmcb +
4181 20054ef0 Blue Swirl
                                       offsetof(struct vmcb,
4182 20054ef0 Blue Swirl
                                                control.intercept_cr_read));
4183 20054ef0 Blue Swirl
    env->intercept_cr_write = lduw_phys(env->vm_vmcb +
4184 20054ef0 Blue Swirl
                                        offsetof(struct vmcb,
4185 20054ef0 Blue Swirl
                                                 control.intercept_cr_write));
4186 20054ef0 Blue Swirl
    env->intercept_dr_read = lduw_phys(env->vm_vmcb +
4187 20054ef0 Blue Swirl
                                       offsetof(struct vmcb,
4188 20054ef0 Blue Swirl
                                                control.intercept_dr_read));
4189 20054ef0 Blue Swirl
    env->intercept_dr_write = lduw_phys(env->vm_vmcb +
4190 20054ef0 Blue Swirl
                                        offsetof(struct vmcb,
4191 20054ef0 Blue Swirl
                                                 control.intercept_dr_write));
4192 20054ef0 Blue Swirl
    env->intercept_exceptions = ldl_phys(env->vm_vmcb +
4193 20054ef0 Blue Swirl
                                         offsetof(struct vmcb,
4194 20054ef0 Blue Swirl
                                                  control.intercept_exceptions
4195 20054ef0 Blue Swirl
                                                  ));
4196 eaa728ee bellard
4197 872929aa bellard
    /* enable intercepts */
4198 872929aa bellard
    env->hflags |= HF_SVMI_MASK;
4199 872929aa bellard
4200 20054ef0 Blue Swirl
    env->tsc_offset = ldq_phys(env->vm_vmcb +
4201 20054ef0 Blue Swirl
                               offsetof(struct vmcb, control.tsc_offset));
4202 33c263df bellard
4203 20054ef0 Blue Swirl
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4204 20054ef0 Blue Swirl
                                                      save.gdtr.base));
4205 20054ef0 Blue Swirl
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb,
4206 20054ef0 Blue Swirl
                                                      save.gdtr.limit));
4207 eaa728ee bellard
4208 20054ef0 Blue Swirl
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4209 20054ef0 Blue Swirl
                                                      save.idtr.base));
4210 20054ef0 Blue Swirl
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb,
4211 20054ef0 Blue Swirl
                                                      save.idtr.limit));
4212 eaa728ee bellard
4213 eaa728ee bellard
    /* clear exit_info_2 so we behave like the real hardware */
4214 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
4215 eaa728ee bellard
4216 20054ef0 Blue Swirl
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4217 20054ef0 Blue Swirl
                                                             save.cr0)));
4218 20054ef0 Blue Swirl
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4219 20054ef0 Blue Swirl
                                                             save.cr4)));
4220 20054ef0 Blue Swirl
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4221 20054ef0 Blue Swirl
                                                             save.cr3)));
4222 eaa728ee bellard
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4223 eaa728ee bellard
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4224 db620f46 bellard
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4225 eaa728ee bellard
    if (int_ctl & V_INTR_MASKING_MASK) {
4226 db620f46 bellard
        env->v_tpr = int_ctl & V_TPR_MASK;
4227 db620f46 bellard
        env->hflags2 |= HF2_VINTR_MASK;
4228 20054ef0 Blue Swirl
        if (env->eflags & IF_MASK) {
4229 db620f46 bellard
            env->hflags2 |= HF2_HIF_MASK;
4230 20054ef0 Blue Swirl
        }
4231 eaa728ee bellard
    }
4232 eaa728ee bellard
4233 20054ef0 Blue Swirl
    cpu_load_efer(env,
4234 5efc27bb bellard
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4235 eaa728ee bellard
    env->eflags = 0;
4236 997ff0d9 Blue Swirl
    cpu_load_eflags(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4237 997ff0d9 Blue Swirl
                                                          save.rflags)),
4238 997ff0d9 Blue Swirl
                    ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4239 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
4240 eaa728ee bellard
4241 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4242 872929aa bellard
                       env, R_ES);
4243 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4244 872929aa bellard
                       env, R_CS);
4245 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4246 872929aa bellard
                       env, R_SS);
4247 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4248 872929aa bellard
                       env, R_DS);
4249 eaa728ee bellard
4250 eaa728ee bellard
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4251 eaa728ee bellard
    env->eip = EIP;
4252 eaa728ee bellard
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4253 eaa728ee bellard
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4254 eaa728ee bellard
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4255 eaa728ee bellard
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4256 20054ef0 Blue Swirl
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb,
4257 20054ef0 Blue Swirl
                                                           save.cpl)));
4258 eaa728ee bellard
4259 eaa728ee bellard
    /* FIXME: guest state consistency checks */
4260 eaa728ee bellard
4261 20054ef0 Blue Swirl
    switch (ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4262 20054ef0 Blue Swirl
    case TLB_CONTROL_DO_NOTHING:
4263 20054ef0 Blue Swirl
        break;
4264 20054ef0 Blue Swirl
    case TLB_CONTROL_FLUSH_ALL_ASID:
4265 20054ef0 Blue Swirl
        /* FIXME: this is not 100% correct but should work for now */
4266 20054ef0 Blue Swirl
        tlb_flush(env, 1);
4267 eaa728ee bellard
        break;
4268 eaa728ee bellard
    }
4269 eaa728ee bellard
4270 960540b4 bellard
    env->hflags2 |= HF2_GIF_MASK;
4271 eaa728ee bellard
4272 db620f46 bellard
    if (int_ctl & V_IRQ_MASK) {
4273 db620f46 bellard
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4274 db620f46 bellard
    }
4275 db620f46 bellard
4276 eaa728ee bellard
    /* maybe we need to inject an event */
4277 20054ef0 Blue Swirl
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb,
4278 20054ef0 Blue Swirl
                                                 control.event_inj));
4279 eaa728ee bellard
    if (event_inj & SVM_EVTINJ_VALID) {
4280 eaa728ee bellard
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4281 eaa728ee bellard
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4282 20054ef0 Blue Swirl
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb +
4283 20054ef0 Blue Swirl
                                          offsetof(struct vmcb,
4284 20054ef0 Blue Swirl
                                                   control.event_inj_err));
4285 eaa728ee bellard
4286 93fcfe39 aliguori
        qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
4287 eaa728ee bellard
        /* FIXME: need to implement valid_err */
4288 eaa728ee bellard
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4289 eaa728ee bellard
        case SVM_EVTINJ_TYPE_INTR:
4290 20054ef0 Blue Swirl
            env->exception_index = vector;
4291 20054ef0 Blue Swirl
            env->error_code = event_inj_err;
4292 20054ef0 Blue Swirl
            env->exception_is_int = 0;
4293 20054ef0 Blue Swirl
            env->exception_next_eip = -1;
4294 20054ef0 Blue Swirl
            qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
4295 20054ef0 Blue Swirl
            /* XXX: is it always correct? */
4296 77b2bc2c Blue Swirl
            do_interrupt_x86_hardirq(env, vector, 1);
4297 20054ef0 Blue Swirl
            break;
4298 eaa728ee bellard
        case SVM_EVTINJ_TYPE_NMI:
4299 20054ef0 Blue Swirl
            env->exception_index = EXCP02_NMI;
4300 20054ef0 Blue Swirl
            env->error_code = event_inj_err;
4301 20054ef0 Blue Swirl
            env->exception_is_int = 0;
4302 20054ef0 Blue Swirl
            env->exception_next_eip = EIP;
4303 20054ef0 Blue Swirl
            qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
4304 20054ef0 Blue Swirl
            cpu_loop_exit(env);
4305 20054ef0 Blue Swirl
            break;
4306 eaa728ee bellard
        case SVM_EVTINJ_TYPE_EXEPT:
4307 20054ef0 Blue Swirl
            env->exception_index = vector;
4308 20054ef0 Blue Swirl
            env->error_code = event_inj_err;
4309 20054ef0 Blue Swirl
            env->exception_is_int = 0;
4310 20054ef0 Blue Swirl
            env->exception_next_eip = -1;
4311 20054ef0 Blue Swirl
            qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
4312 20054ef0 Blue Swirl
            cpu_loop_exit(env);
4313 20054ef0 Blue Swirl
            break;
4314 eaa728ee bellard
        case SVM_EVTINJ_TYPE_SOFT:
4315 20054ef0 Blue Swirl
            env->exception_index = vector;
4316 20054ef0 Blue Swirl
            env->error_code = event_inj_err;
4317 20054ef0 Blue Swirl
            env->exception_is_int = 1;
4318 20054ef0 Blue Swirl
            env->exception_next_eip = EIP;
4319 20054ef0 Blue Swirl
            qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
4320 20054ef0 Blue Swirl
            cpu_loop_exit(env);
4321 20054ef0 Blue Swirl
            break;
4322 eaa728ee bellard
        }
4323 20054ef0 Blue Swirl
        qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index,
4324 20054ef0 Blue Swirl
                      env->error_code);
4325 eaa728ee bellard
    }
4326 eaa728ee bellard
}
4327 eaa728ee bellard
4328 eaa728ee bellard
void helper_vmmcall(void)
4329 eaa728ee bellard
{
4330 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
4331 77b2bc2c Blue Swirl
    raise_exception(env, EXCP06_ILLOP);
4332 eaa728ee bellard
}
4333 eaa728ee bellard
4334 914178d3 bellard
void helper_vmload(int aflag)
4335 eaa728ee bellard
{
4336 eaa728ee bellard
    target_ulong addr;
4337 20054ef0 Blue Swirl
4338 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
4339 872929aa bellard
4340 20054ef0 Blue Swirl
    if (aflag == 2) {
4341 914178d3 bellard
        addr = EAX;
4342 20054ef0 Blue Swirl
    } else {
4343 914178d3 bellard
        addr = (uint32_t)EAX;
4344 20054ef0 Blue Swirl
    }
4345 914178d3 bellard
4346 20054ef0 Blue Swirl
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx
4347 20054ef0 Blue Swirl
                  "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4348 20054ef0 Blue Swirl
                  addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4349 20054ef0 Blue Swirl
                  env->segs[R_FS].base);
4350 eaa728ee bellard
4351 872929aa bellard
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
4352 872929aa bellard
                       env, R_FS);
4353 872929aa bellard
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
4354 872929aa bellard
                       env, R_GS);
4355 872929aa bellard
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
4356 872929aa bellard
                 &env->tr);
4357 872929aa bellard
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
4358 872929aa bellard
                 &env->ldt);
4359 eaa728ee bellard
4360 eaa728ee bellard
#ifdef TARGET_X86_64
4361 20054ef0 Blue Swirl
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb,
4362 20054ef0 Blue Swirl
                                                 save.kernel_gs_base));
4363 eaa728ee bellard
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
4364 eaa728ee bellard
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
4365 eaa728ee bellard
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
4366 eaa728ee bellard
#endif
4367 eaa728ee bellard
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
4368 eaa728ee bellard
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
4369 20054ef0 Blue Swirl
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb,
4370 20054ef0 Blue Swirl
                                                 save.sysenter_esp));
4371 20054ef0 Blue Swirl
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb,
4372 20054ef0 Blue Swirl
                                                 save.sysenter_eip));
4373 eaa728ee bellard
}
4374 eaa728ee bellard
4375 914178d3 bellard
void helper_vmsave(int aflag)
4376 eaa728ee bellard
{
4377 eaa728ee bellard
    target_ulong addr;
4378 20054ef0 Blue Swirl
4379 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
4380 914178d3 bellard
4381 20054ef0 Blue Swirl
    if (aflag == 2) {
4382 914178d3 bellard
        addr = EAX;
4383 20054ef0 Blue Swirl
    } else {
4384 914178d3 bellard
        addr = (uint32_t)EAX;
4385 20054ef0 Blue Swirl
    }
4386 914178d3 bellard
4387 20054ef0 Blue Swirl
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx
4388 20054ef0 Blue Swirl
                  "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4389 20054ef0 Blue Swirl
                  addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4390 20054ef0 Blue Swirl
                  env->segs[R_FS].base);
4391 eaa728ee bellard
4392 20054ef0 Blue Swirl
    svm_save_seg(addr + offsetof(struct vmcb, save.fs),
4393 872929aa bellard
                 &env->segs[R_FS]);
4394 20054ef0 Blue Swirl
    svm_save_seg(addr + offsetof(struct vmcb, save.gs),
4395 872929aa bellard
                 &env->segs[R_GS]);
4396 20054ef0 Blue Swirl
    svm_save_seg(addr + offsetof(struct vmcb, save.tr),
4397 872929aa bellard
                 &env->tr);
4398 20054ef0 Blue Swirl
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr),
4399 872929aa bellard
                 &env->ldt);
4400 eaa728ee bellard
4401 eaa728ee bellard
#ifdef TARGET_X86_64
4402 20054ef0 Blue Swirl
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base),
4403 20054ef0 Blue Swirl
             env->kernelgsbase);
4404 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
4405 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
4406 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
4407 eaa728ee bellard
#endif
4408 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
4409 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
4410 20054ef0 Blue Swirl
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp),
4411 20054ef0 Blue Swirl
             env->sysenter_esp);
4412 20054ef0 Blue Swirl
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip),
4413 20054ef0 Blue Swirl
             env->sysenter_eip);
4414 eaa728ee bellard
}
4415 eaa728ee bellard
4416 872929aa bellard
void helper_stgi(void)
4417 872929aa bellard
{
4418 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
4419 db620f46 bellard
    env->hflags2 |= HF2_GIF_MASK;
4420 872929aa bellard
}
4421 872929aa bellard
4422 872929aa bellard
void helper_clgi(void)
4423 872929aa bellard
{
4424 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
4425 db620f46 bellard
    env->hflags2 &= ~HF2_GIF_MASK;
4426 872929aa bellard
}
4427 872929aa bellard
4428 eaa728ee bellard
void helper_skinit(void)
4429 eaa728ee bellard
{
4430 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
4431 872929aa bellard
    /* XXX: not implemented */
4432 77b2bc2c Blue Swirl
    raise_exception(env, EXCP06_ILLOP);
4433 eaa728ee bellard
}
4434 eaa728ee bellard
4435 914178d3 bellard
void helper_invlpga(int aflag)
4436 eaa728ee bellard
{
4437 914178d3 bellard
    target_ulong addr;
4438 20054ef0 Blue Swirl
4439 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
4440 20054ef0 Blue Swirl
4441 20054ef0 Blue Swirl
    if (aflag == 2) {
4442 914178d3 bellard
        addr = EAX;
4443 20054ef0 Blue Swirl
    } else {
4444 914178d3 bellard
        addr = (uint32_t)EAX;
4445 20054ef0 Blue Swirl
    }
4446 914178d3 bellard
4447 914178d3 bellard
    /* XXX: could use the ASID to see if it is needed to do the
4448 914178d3 bellard
       flush */
4449 914178d3 bellard
    tlb_flush_page(env, addr);
4450 eaa728ee bellard
}
4451 eaa728ee bellard
4452 eaa728ee bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4453 eaa728ee bellard
{
4454 20054ef0 Blue Swirl
    if (likely(!(env->hflags & HF_SVMI_MASK))) {
4455 872929aa bellard
        return;
4456 20054ef0 Blue Swirl
    }
4457 20054ef0 Blue Swirl
    switch (type) {
4458 eaa728ee bellard
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
4459 872929aa bellard
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
4460 eaa728ee bellard
            helper_vmexit(type, param);
4461 eaa728ee bellard
        }
4462 eaa728ee bellard
        break;
4463 872929aa bellard
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
4464 872929aa bellard
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
4465 eaa728ee bellard
            helper_vmexit(type, param);
4466 eaa728ee bellard
        }
4467 eaa728ee bellard
        break;
4468 872929aa bellard
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
4469 872929aa bellard
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
4470 eaa728ee bellard
            helper_vmexit(type, param);
4471 eaa728ee bellard
        }
4472 eaa728ee bellard
        break;
4473 872929aa bellard
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
4474 872929aa bellard
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
4475 eaa728ee bellard
            helper_vmexit(type, param);
4476 eaa728ee bellard
        }
4477 eaa728ee bellard
        break;
4478 872929aa bellard
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
4479 872929aa bellard
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
4480 eaa728ee bellard
            helper_vmexit(type, param);
4481 eaa728ee bellard
        }
4482 eaa728ee bellard
        break;
4483 eaa728ee bellard
    case SVM_EXIT_MSR:
4484 872929aa bellard
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
4485 eaa728ee bellard
            /* FIXME: this should be read in at vmrun (faster this way?) */
4486 20054ef0 Blue Swirl
            uint64_t addr = ldq_phys(env->vm_vmcb +
4487 20054ef0 Blue Swirl
                                     offsetof(struct vmcb,
4488 20054ef0 Blue Swirl
                                              control.msrpm_base_pa));
4489 eaa728ee bellard
            uint32_t t0, t1;
4490 20054ef0 Blue Swirl
4491 20054ef0 Blue Swirl
            switch ((uint32_t)ECX) {
4492 eaa728ee bellard
            case 0 ... 0x1fff:
4493 eaa728ee bellard
                t0 = (ECX * 2) % 8;
4494 583cd3cb Adam Lackorzynski
                t1 = (ECX * 2) / 8;
4495 eaa728ee bellard
                break;
4496 eaa728ee bellard
            case 0xc0000000 ... 0xc0001fff:
4497 eaa728ee bellard
                t0 = (8192 + ECX - 0xc0000000) * 2;
4498 eaa728ee bellard
                t1 = (t0 / 8);
4499 eaa728ee bellard
                t0 %= 8;
4500 eaa728ee bellard
                break;
4501 eaa728ee bellard
            case 0xc0010000 ... 0xc0011fff:
4502 eaa728ee bellard
                t0 = (16384 + ECX - 0xc0010000) * 2;
4503 eaa728ee bellard
                t1 = (t0 / 8);
4504 eaa728ee bellard
                t0 %= 8;
4505 eaa728ee bellard
                break;
4506 eaa728ee bellard
            default:
4507 eaa728ee bellard
                helper_vmexit(type, param);
4508 eaa728ee bellard
                t0 = 0;
4509 eaa728ee bellard
                t1 = 0;
4510 eaa728ee bellard
                break;
4511 eaa728ee bellard
            }
4512 20054ef0 Blue Swirl
            if (ldub_phys(addr + t1) & ((1 << param) << t0)) {
4513 eaa728ee bellard
                helper_vmexit(type, param);
4514 20054ef0 Blue Swirl
            }
4515 eaa728ee bellard
        }
4516 eaa728ee bellard
        break;
4517 eaa728ee bellard
    default:
4518 872929aa bellard
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
4519 eaa728ee bellard
            helper_vmexit(type, param);
4520 eaa728ee bellard
        }
4521 eaa728ee bellard
        break;
4522 eaa728ee bellard
    }
4523 eaa728ee bellard
}
4524 eaa728ee bellard
4525 77b2bc2c Blue Swirl
void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
4526 77b2bc2c Blue Swirl
                                   uint64_t param)
4527 e694d4e2 Blue Swirl
{
4528 317ac620 Andreas Färber
    CPUX86State *saved_env;
4529 e694d4e2 Blue Swirl
4530 e694d4e2 Blue Swirl
    saved_env = env;
4531 e694d4e2 Blue Swirl
    env = env1;
4532 77b2bc2c Blue Swirl
    helper_svm_check_intercept_param(type, param);
4533 e694d4e2 Blue Swirl
    env = saved_env;
4534 e694d4e2 Blue Swirl
}
4535 e694d4e2 Blue Swirl
4536 20054ef0 Blue Swirl
void helper_svm_check_io(uint32_t port, uint32_t param,
4537 eaa728ee bellard
                         uint32_t next_eip_addend)
4538 eaa728ee bellard
{
4539 872929aa bellard
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
4540 eaa728ee bellard
        /* FIXME: this should be read in at vmrun (faster this way?) */
4541 20054ef0 Blue Swirl
        uint64_t addr = ldq_phys(env->vm_vmcb +
4542 20054ef0 Blue Swirl
                                 offsetof(struct vmcb, control.iopm_base_pa));
4543 eaa728ee bellard
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
4544 20054ef0 Blue Swirl
4545 20054ef0 Blue Swirl
        if (lduw_phys(addr + port / 8) & (mask << (port & 7))) {
4546 eaa728ee bellard
            /* next EIP */
4547 20054ef0 Blue Swirl
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
4548 eaa728ee bellard
                     env->eip + next_eip_addend);
4549 eaa728ee bellard
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
4550 eaa728ee bellard
        }
4551 eaa728ee bellard
    }
4552 eaa728ee bellard
}
4553 eaa728ee bellard
4554 eaa728ee bellard
/* Note: currently only 32 bits of exit_code are used */
4555 eaa728ee bellard
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
4556 eaa728ee bellard
{
4557 eaa728ee bellard
    uint32_t int_ctl;
4558 eaa728ee bellard
4559 20054ef0 Blue Swirl
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
4560 20054ef0 Blue Swirl
                  PRIx64 ", " TARGET_FMT_lx ")!\n",
4561 20054ef0 Blue Swirl
                  exit_code, exit_info_1,
4562 20054ef0 Blue Swirl
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb,
4563 20054ef0 Blue Swirl
                                                   control.exit_info_2)),
4564 20054ef0 Blue Swirl
                  EIP);
4565 eaa728ee bellard
4566 20054ef0 Blue Swirl
    if (env->hflags & HF_INHIBIT_IRQ_MASK) {
4567 20054ef0 Blue Swirl
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state),
4568 20054ef0 Blue Swirl
                 SVM_INTERRUPT_SHADOW_MASK);
4569 eaa728ee bellard
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4570 eaa728ee bellard
    } else {
4571 eaa728ee bellard
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
4572 eaa728ee bellard
    }
4573 eaa728ee bellard
4574 eaa728ee bellard
    /* Save the VM state in the vmcb */
4575 20054ef0 Blue Swirl
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es),
4576 872929aa bellard
                 &env->segs[R_ES]);
4577 20054ef0 Blue Swirl
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4578 872929aa bellard
                 &env->segs[R_CS]);
4579 20054ef0 Blue Swirl
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4580 872929aa bellard
                 &env->segs[R_SS]);
4581 20054ef0 Blue Swirl
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4582 872929aa bellard
                 &env->segs[R_DS]);
4583 eaa728ee bellard
4584 20054ef0 Blue Swirl
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base),
4585 20054ef0 Blue Swirl
             env->gdt.base);
4586 20054ef0 Blue Swirl
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit),
4587 20054ef0 Blue Swirl
             env->gdt.limit);
4588 eaa728ee bellard
4589 20054ef0 Blue Swirl
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base),
4590 20054ef0 Blue Swirl
             env->idt.base);
4591 20054ef0 Blue Swirl
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit),
4592 20054ef0 Blue Swirl
             env->idt.limit);
4593 eaa728ee bellard
4594 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
4595 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
4596 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
4597 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
4598 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
4599 eaa728ee bellard
4600 db620f46 bellard
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4601 db620f46 bellard
    int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
4602 db620f46 bellard
    int_ctl |= env->v_tpr & V_TPR_MASK;
4603 20054ef0 Blue Swirl
    if (env->interrupt_request & CPU_INTERRUPT_VIRQ) {
4604 db620f46 bellard
        int_ctl |= V_IRQ_MASK;
4605 20054ef0 Blue Swirl
    }
4606 db620f46 bellard
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
4607 eaa728ee bellard
4608 20054ef0 Blue Swirl
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags),
4609 997ff0d9 Blue Swirl
             cpu_compute_eflags(env));
4610 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
4611 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
4612 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
4613 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
4614 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
4615 20054ef0 Blue Swirl
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl),
4616 20054ef0 Blue Swirl
             env->hflags & HF_CPL_MASK);
4617 eaa728ee bellard
4618 eaa728ee bellard
    /* Reload the host state from vm_hsave */
4619 db620f46 bellard
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4620 872929aa bellard
    env->hflags &= ~HF_SVMI_MASK;
4621 eaa728ee bellard
    env->intercept = 0;
4622 eaa728ee bellard
    env->intercept_exceptions = 0;
4623 eaa728ee bellard
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
4624 33c263df bellard
    env->tsc_offset = 0;
4625 eaa728ee bellard
4626 20054ef0 Blue Swirl
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb,
4627 20054ef0 Blue Swirl
                                                       save.gdtr.base));
4628 20054ef0 Blue Swirl
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb,
4629 20054ef0 Blue Swirl
                                                       save.gdtr.limit));
4630 20054ef0 Blue Swirl
4631 20054ef0 Blue Swirl
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb,
4632 20054ef0 Blue Swirl
                                                       save.idtr.base));
4633 20054ef0 Blue Swirl
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb,
4634 20054ef0 Blue Swirl
                                                       save.idtr.limit));
4635 20054ef0 Blue Swirl
4636 20054ef0 Blue Swirl
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb,
4637 20054ef0 Blue Swirl
                                                              save.cr0)) |
4638 20054ef0 Blue Swirl
                       CR0_PE_MASK);
4639 20054ef0 Blue Swirl
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb,
4640 20054ef0 Blue Swirl
                                                              save.cr4)));
4641 20054ef0 Blue Swirl
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb,
4642 20054ef0 Blue Swirl
                                                              save.cr3)));
4643 5efc27bb bellard
    /* we need to set the efer after the crs so the hidden flags get
4644 5efc27bb bellard
       set properly */
4645 20054ef0 Blue Swirl
    cpu_load_efer(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb,
4646 20054ef0 Blue Swirl
                                                         save.efer)));
4647 eaa728ee bellard
    env->eflags = 0;
4648 997ff0d9 Blue Swirl
    cpu_load_eflags(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb,
4649 997ff0d9 Blue Swirl
                                                           save.rflags)),
4650 997ff0d9 Blue Swirl
                    ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4651 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
4652 eaa728ee bellard
4653 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
4654 872929aa bellard
                       env, R_ES);
4655 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
4656 872929aa bellard
                       env, R_CS);
4657 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
4658 872929aa bellard
                       env, R_SS);
4659 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
4660 872929aa bellard
                       env, R_DS);
4661 eaa728ee bellard
4662 eaa728ee bellard
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
4663 eaa728ee bellard
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
4664 eaa728ee bellard
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
4665 eaa728ee bellard
4666 eaa728ee bellard
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
4667 eaa728ee bellard
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
4668 eaa728ee bellard
4669 eaa728ee bellard
    /* other setups */
4670 eaa728ee bellard
    cpu_x86_set_cpl(env, 0);
4671 20054ef0 Blue Swirl
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code),
4672 20054ef0 Blue Swirl
             exit_code);
4673 20054ef0 Blue Swirl
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1),
4674 20054ef0 Blue Swirl
             exit_info_1);
4675 eaa728ee bellard
4676 2ed51f5b aliguori
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info),
4677 20054ef0 Blue Swirl
             ldl_phys(env->vm_vmcb + offsetof(struct vmcb,
4678 20054ef0 Blue Swirl
                                              control.event_inj)));
4679 2ed51f5b aliguori
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err),
4680 20054ef0 Blue Swirl
             ldl_phys(env->vm_vmcb + offsetof(struct vmcb,
4681 20054ef0 Blue Swirl
                                              control.event_inj_err)));
4682 ab5ea558 Jan Kiszka
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 0);
4683 2ed51f5b aliguori
4684 960540b4 bellard
    env->hflags2 &= ~HF2_GIF_MASK;
4685 eaa728ee bellard
    /* FIXME: Resets the current ASID register to zero (host ASID). */
4686 eaa728ee bellard
4687 eaa728ee bellard
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
4688 eaa728ee bellard
4689 eaa728ee bellard
    /* Clears the TSC_OFFSET inside the processor. */
4690 eaa728ee bellard
4691 eaa728ee bellard
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
4692 eaa728ee bellard
       from the page table indicated the host's CR3. If the PDPEs contain
4693 eaa728ee bellard
       illegal state, the processor causes a shutdown. */
4694 eaa728ee bellard
4695 eaa728ee bellard
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
4696 eaa728ee bellard
    env->cr[0] |= CR0_PE_MASK;
4697 eaa728ee bellard
    env->eflags &= ~VM_MASK;
4698 eaa728ee bellard
4699 eaa728ee bellard
    /* Disables all breakpoints in the host DR7 register. */
4700 eaa728ee bellard
4701 eaa728ee bellard
    /* Checks the reloaded host state for consistency. */
4702 eaa728ee bellard
4703 eaa728ee bellard
    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
4704 eaa728ee bellard
       host's code segment or non-canonical (in the case of long mode), a
4705 20054ef0 Blue Swirl
       #GP fault is delivered inside the host. */
4706 eaa728ee bellard
4707 eaa728ee bellard
    /* remove any pending exception */
4708 eaa728ee bellard
    env->exception_index = -1;
4709 eaa728ee bellard
    env->error_code = 0;
4710 eaa728ee bellard
    env->old_exception = -1;
4711 eaa728ee bellard
4712 1162c041 Blue Swirl
    cpu_loop_exit(env);
4713 eaa728ee bellard
}
4714 eaa728ee bellard
4715 77b2bc2c Blue Swirl
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1)
4716 77b2bc2c Blue Swirl
{
4717 77b2bc2c Blue Swirl
    env = nenv;
4718 77b2bc2c Blue Swirl
    helper_vmexit(exit_code, exit_info_1);
4719 77b2bc2c Blue Swirl
}
4720 77b2bc2c Blue Swirl
4721 eaa728ee bellard
#endif
4722 eaa728ee bellard
4723 eaa728ee bellard
#define SHIFT 0
4724 38de4c46 Blue Swirl
#include "cc_helper_template.h"
4725 eaa728ee bellard
#undef SHIFT
4726 eaa728ee bellard
4727 eaa728ee bellard
#define SHIFT 1
4728 38de4c46 Blue Swirl
#include "cc_helper_template.h"
4729 eaa728ee bellard
#undef SHIFT
4730 eaa728ee bellard
4731 eaa728ee bellard
#define SHIFT 2
4732 38de4c46 Blue Swirl
#include "cc_helper_template.h"
4733 eaa728ee bellard
#undef SHIFT
4734 eaa728ee bellard
4735 eaa728ee bellard
#ifdef TARGET_X86_64
4736 eaa728ee bellard
4737 eaa728ee bellard
#define SHIFT 3
4738 38de4c46 Blue Swirl
#include "cc_helper_template.h"
4739 eaa728ee bellard
#undef SHIFT
4740 eaa728ee bellard
4741 eaa728ee bellard
#endif
4742 eaa728ee bellard
4743 38de4c46 Blue Swirl
#define SHIFT 0
4744 38de4c46 Blue Swirl
#include "shift_helper_template.h"
4745 38de4c46 Blue Swirl
#undef SHIFT
4746 38de4c46 Blue Swirl
4747 38de4c46 Blue Swirl
#define SHIFT 1
4748 38de4c46 Blue Swirl
#include "shift_helper_template.h"
4749 38de4c46 Blue Swirl
#undef SHIFT
4750 38de4c46 Blue Swirl
4751 38de4c46 Blue Swirl
#define SHIFT 2
4752 38de4c46 Blue Swirl
#include "shift_helper_template.h"
4753 38de4c46 Blue Swirl
#undef SHIFT
4754 38de4c46 Blue Swirl
4755 38de4c46 Blue Swirl
#ifdef TARGET_X86_64
4756 38de4c46 Blue Swirl
#define SHIFT 3
4757 38de4c46 Blue Swirl
#include "shift_helper_template.h"
4758 38de4c46 Blue Swirl
#undef SHIFT
4759 38de4c46 Blue Swirl
#endif
4760 38de4c46 Blue Swirl
4761 eaa728ee bellard
/* bit operations */
4762 eaa728ee bellard
target_ulong helper_bsf(target_ulong t0)
4763 eaa728ee bellard
{
4764 eaa728ee bellard
    int count;
4765 eaa728ee bellard
    target_ulong res;
4766 eaa728ee bellard
4767 eaa728ee bellard
    res = t0;
4768 eaa728ee bellard
    count = 0;
4769 eaa728ee bellard
    while ((res & 1) == 0) {
4770 eaa728ee bellard
        count++;
4771 eaa728ee bellard
        res >>= 1;
4772 eaa728ee bellard
    }
4773 eaa728ee bellard
    return count;
4774 eaa728ee bellard
}
4775 eaa728ee bellard
4776 31501a71 Andre Przywara
target_ulong helper_lzcnt(target_ulong t0, int wordsize)
4777 eaa728ee bellard
{
4778 eaa728ee bellard
    int count;
4779 eaa728ee bellard
    target_ulong res, mask;
4780 31501a71 Andre Przywara
4781 31501a71 Andre Przywara
    if (wordsize > 0 && t0 == 0) {
4782 31501a71 Andre Przywara
        return wordsize;
4783 31501a71 Andre Przywara
    }
4784 eaa728ee bellard
    res = t0;
4785 eaa728ee bellard
    count = TARGET_LONG_BITS - 1;
4786 eaa728ee bellard
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
4787 eaa728ee bellard
    while ((res & mask) == 0) {
4788 eaa728ee bellard
        count--;
4789 eaa728ee bellard
        res <<= 1;
4790 eaa728ee bellard
    }
4791 31501a71 Andre Przywara
    if (wordsize > 0) {
4792 31501a71 Andre Przywara
        return wordsize - 1 - count;
4793 31501a71 Andre Przywara
    }
4794 eaa728ee bellard
    return count;
4795 eaa728ee bellard
}
4796 eaa728ee bellard
4797 31501a71 Andre Przywara
target_ulong helper_bsr(target_ulong t0)
4798 31501a71 Andre Przywara
{
4799 20054ef0 Blue Swirl
    return helper_lzcnt(t0, 0);
4800 31501a71 Andre Przywara
}
4801 eaa728ee bellard
4802 eaa728ee bellard
static int compute_all_eflags(void)
4803 eaa728ee bellard
{
4804 eaa728ee bellard
    return CC_SRC;
4805 eaa728ee bellard
}
4806 eaa728ee bellard
4807 eaa728ee bellard
static int compute_c_eflags(void)
4808 eaa728ee bellard
{
4809 eaa728ee bellard
    return CC_SRC & CC_C;
4810 eaa728ee bellard
}
4811 eaa728ee bellard
4812 a7812ae4 pbrook
uint32_t helper_cc_compute_all(int op)
4813 a7812ae4 pbrook
{
4814 a7812ae4 pbrook
    switch (op) {
4815 20054ef0 Blue Swirl
    default: /* should never happen */
4816 20054ef0 Blue Swirl
        return 0;
4817 20054ef0 Blue Swirl
4818 20054ef0 Blue Swirl
    case CC_OP_EFLAGS:
4819 20054ef0 Blue Swirl
        return compute_all_eflags();
4820 20054ef0 Blue Swirl
4821 20054ef0 Blue Swirl
    case CC_OP_MULB:
4822 20054ef0 Blue Swirl
        return compute_all_mulb();
4823 20054ef0 Blue Swirl
    case CC_OP_MULW:
4824 20054ef0 Blue Swirl
        return compute_all_mulw();
4825 20054ef0 Blue Swirl
    case CC_OP_MULL:
4826 20054ef0 Blue Swirl
        return compute_all_mull();
4827 20054ef0 Blue Swirl
4828 20054ef0 Blue Swirl
    case CC_OP_ADDB:
4829 20054ef0 Blue Swirl
        return compute_all_addb();
4830 20054ef0 Blue Swirl
    case CC_OP_ADDW:
4831 20054ef0 Blue Swirl
        return compute_all_addw();
4832 20054ef0 Blue Swirl
    case CC_OP_ADDL:
4833 20054ef0 Blue Swirl
        return compute_all_addl();
4834 20054ef0 Blue Swirl
4835 20054ef0 Blue Swirl
    case CC_OP_ADCB:
4836 20054ef0 Blue Swirl
        return compute_all_adcb();
4837 20054ef0 Blue Swirl
    case CC_OP_ADCW:
4838 20054ef0 Blue Swirl
        return compute_all_adcw();
4839 20054ef0 Blue Swirl
    case CC_OP_ADCL:
4840 20054ef0 Blue Swirl
        return compute_all_adcl();
4841 20054ef0 Blue Swirl
4842 20054ef0 Blue Swirl
    case CC_OP_SUBB:
4843 20054ef0 Blue Swirl
        return compute_all_subb();
4844 20054ef0 Blue Swirl
    case CC_OP_SUBW:
4845 20054ef0 Blue Swirl
        return compute_all_subw();
4846 20054ef0 Blue Swirl
    case CC_OP_SUBL:
4847 20054ef0 Blue Swirl
        return compute_all_subl();
4848 20054ef0 Blue Swirl
4849 20054ef0 Blue Swirl
    case CC_OP_SBBB:
4850 20054ef0 Blue Swirl
        return compute_all_sbbb();
4851 20054ef0 Blue Swirl
    case CC_OP_SBBW:
4852 20054ef0 Blue Swirl
        return compute_all_sbbw();
4853 20054ef0 Blue Swirl
    case CC_OP_SBBL:
4854 20054ef0 Blue Swirl
        return compute_all_sbbl();
4855 20054ef0 Blue Swirl
4856 20054ef0 Blue Swirl
    case CC_OP_LOGICB:
4857 20054ef0 Blue Swirl
        return compute_all_logicb();
4858 20054ef0 Blue Swirl
    case CC_OP_LOGICW:
4859 20054ef0 Blue Swirl
        return compute_all_logicw();
4860 20054ef0 Blue Swirl
    case CC_OP_LOGICL:
4861 20054ef0 Blue Swirl
        return compute_all_logicl();
4862 20054ef0 Blue Swirl
4863 20054ef0 Blue Swirl
    case CC_OP_INCB:
4864 20054ef0 Blue Swirl
        return compute_all_incb();
4865 20054ef0 Blue Swirl
    case CC_OP_INCW:
4866 20054ef0 Blue Swirl
        return compute_all_incw();
4867 20054ef0 Blue Swirl
    case CC_OP_INCL:
4868 20054ef0 Blue Swirl
        return compute_all_incl();
4869 20054ef0 Blue Swirl
4870 20054ef0 Blue Swirl
    case CC_OP_DECB:
4871 20054ef0 Blue Swirl
        return compute_all_decb();
4872 20054ef0 Blue Swirl
    case CC_OP_DECW:
4873 20054ef0 Blue Swirl
        return compute_all_decw();
4874 20054ef0 Blue Swirl
    case CC_OP_DECL:
4875 20054ef0 Blue Swirl
        return compute_all_decl();
4876 20054ef0 Blue Swirl
4877 20054ef0 Blue Swirl
    case CC_OP_SHLB:
4878 20054ef0 Blue Swirl
        return compute_all_shlb();
4879 20054ef0 Blue Swirl
    case CC_OP_SHLW:
4880 20054ef0 Blue Swirl
        return compute_all_shlw();
4881 20054ef0 Blue Swirl
    case CC_OP_SHLL:
4882 20054ef0 Blue Swirl
        return compute_all_shll();
4883 20054ef0 Blue Swirl
4884 20054ef0 Blue Swirl
    case CC_OP_SARB:
4885 20054ef0 Blue Swirl
        return compute_all_sarb();
4886 20054ef0 Blue Swirl
    case CC_OP_SARW:
4887 20054ef0 Blue Swirl
        return compute_all_sarw();
4888 20054ef0 Blue Swirl
    case CC_OP_SARL:
4889 20054ef0 Blue Swirl
        return compute_all_sarl();
4890 eaa728ee bellard
4891 eaa728ee bellard
#ifdef TARGET_X86_64
4892 20054ef0 Blue Swirl
    case CC_OP_MULQ:
4893 20054ef0 Blue Swirl
        return compute_all_mulq();
4894 eaa728ee bellard
4895 20054ef0 Blue Swirl
    case CC_OP_ADDQ:
4896 20054ef0 Blue Swirl
        return compute_all_addq();
4897 eaa728ee bellard
4898 20054ef0 Blue Swirl
    case CC_OP_ADCQ:
4899 20054ef0 Blue Swirl
        return compute_all_adcq();
4900 eaa728ee bellard
4901 20054ef0 Blue Swirl
    case CC_OP_SUBQ:
4902 20054ef0 Blue Swirl
        return compute_all_subq();
4903 eaa728ee bellard
4904 20054ef0 Blue Swirl
    case CC_OP_SBBQ:
4905 20054ef0 Blue Swirl
        return compute_all_sbbq();
4906 eaa728ee bellard
4907 20054ef0 Blue Swirl
    case CC_OP_LOGICQ:
4908 20054ef0 Blue Swirl
        return compute_all_logicq();
4909 eaa728ee bellard
4910 20054ef0 Blue Swirl
    case CC_OP_INCQ:
4911 20054ef0 Blue Swirl
        return compute_all_incq();
4912 eaa728ee bellard
4913 20054ef0 Blue Swirl
    case CC_OP_DECQ:
4914 20054ef0 Blue Swirl
        return compute_all_decq();
4915 eaa728ee bellard
4916 20054ef0 Blue Swirl
    case CC_OP_SHLQ:
4917 20054ef0 Blue Swirl
        return compute_all_shlq();
4918 eaa728ee bellard
4919 20054ef0 Blue Swirl
    case CC_OP_SARQ:
4920 20054ef0 Blue Swirl
        return compute_all_sarq();
4921 eaa728ee bellard
#endif
4922 a7812ae4 pbrook
    }
4923 a7812ae4 pbrook
}
4924 a7812ae4 pbrook
4925 317ac620 Andreas Färber
uint32_t cpu_cc_compute_all(CPUX86State *env1, int op)
4926 e694d4e2 Blue Swirl
{
4927 317ac620 Andreas Färber
    CPUX86State *saved_env;
4928 e694d4e2 Blue Swirl
    uint32_t ret;
4929 e694d4e2 Blue Swirl
4930 e694d4e2 Blue Swirl
    saved_env = env;
4931 e694d4e2 Blue Swirl
    env = env1;
4932 e694d4e2 Blue Swirl
    ret = helper_cc_compute_all(op);
4933 e694d4e2 Blue Swirl
    env = saved_env;
4934 e694d4e2 Blue Swirl
    return ret;
4935 e694d4e2 Blue Swirl
}
4936 e694d4e2 Blue Swirl
4937 a7812ae4 pbrook
uint32_t helper_cc_compute_c(int op)
4938 a7812ae4 pbrook
{
4939 a7812ae4 pbrook
    switch (op) {
4940 20054ef0 Blue Swirl
    default: /* should never happen */
4941 20054ef0 Blue Swirl
        return 0;
4942 20054ef0 Blue Swirl
4943 20054ef0 Blue Swirl
    case CC_OP_EFLAGS:
4944 20054ef0 Blue Swirl
        return compute_c_eflags();
4945 20054ef0 Blue Swirl
4946 20054ef0 Blue Swirl
    case CC_OP_MULB:
4947 20054ef0 Blue Swirl
        return compute_c_mull();
4948 20054ef0 Blue Swirl
    case CC_OP_MULW:
4949 20054ef0 Blue Swirl
        return compute_c_mull();
4950 20054ef0 Blue Swirl
    case CC_OP_MULL:
4951 20054ef0 Blue Swirl
        return compute_c_mull();
4952 20054ef0 Blue Swirl
4953 20054ef0 Blue Swirl
    case CC_OP_ADDB:
4954 20054ef0 Blue Swirl
        return compute_c_addb();
4955 20054ef0 Blue Swirl
    case CC_OP_ADDW:
4956 20054ef0 Blue Swirl
        return compute_c_addw();
4957 20054ef0 Blue Swirl
    case CC_OP_ADDL:
4958 20054ef0 Blue Swirl
        return compute_c_addl();
4959 20054ef0 Blue Swirl
4960 20054ef0 Blue Swirl
    case CC_OP_ADCB:
4961 20054ef0 Blue Swirl
        return compute_c_adcb();
4962 20054ef0 Blue Swirl
    case CC_OP_ADCW:
4963 20054ef0 Blue Swirl
        return compute_c_adcw();
4964 20054ef0 Blue Swirl
    case CC_OP_ADCL:
4965 20054ef0 Blue Swirl
        return compute_c_adcl();
4966 20054ef0 Blue Swirl
4967 20054ef0 Blue Swirl
    case CC_OP_SUBB:
4968 20054ef0 Blue Swirl
        return compute_c_subb();
4969 20054ef0 Blue Swirl
    case CC_OP_SUBW:
4970 20054ef0 Blue Swirl
        return compute_c_subw();
4971 20054ef0 Blue Swirl
    case CC_OP_SUBL:
4972 20054ef0 Blue Swirl
        return compute_c_subl();
4973 20054ef0 Blue Swirl
4974 20054ef0 Blue Swirl
    case CC_OP_SBBB:
4975 20054ef0 Blue Swirl
        return compute_c_sbbb();
4976 20054ef0 Blue Swirl
    case CC_OP_SBBW:
4977 20054ef0 Blue Swirl
        return compute_c_sbbw();
4978 20054ef0 Blue Swirl
    case CC_OP_SBBL:
4979 20054ef0 Blue Swirl
        return compute_c_sbbl();
4980 20054ef0 Blue Swirl
4981 20054ef0 Blue Swirl
    case CC_OP_LOGICB:
4982 20054ef0 Blue Swirl
        return compute_c_logicb();
4983 20054ef0 Blue Swirl
    case CC_OP_LOGICW:
4984 20054ef0 Blue Swirl
        return compute_c_logicw();
4985 20054ef0 Blue Swirl
    case CC_OP_LOGICL:
4986 20054ef0 Blue Swirl
        return compute_c_logicl();
4987 20054ef0 Blue Swirl
4988 20054ef0 Blue Swirl
    case CC_OP_INCB:
4989 20054ef0 Blue Swirl
        return compute_c_incl();
4990 20054ef0 Blue Swirl
    case CC_OP_INCW:
4991 20054ef0 Blue Swirl
        return compute_c_incl();
4992 20054ef0 Blue Swirl
    case CC_OP_INCL:
4993 20054ef0 Blue Swirl
        return compute_c_incl();
4994 20054ef0 Blue Swirl
4995 20054ef0 Blue Swirl
    case CC_OP_DECB:
4996 20054ef0 Blue Swirl
        return compute_c_incl();
4997 20054ef0 Blue Swirl
    case CC_OP_DECW:
4998 20054ef0 Blue Swirl
        return compute_c_incl();
4999 20054ef0 Blue Swirl
    case CC_OP_DECL:
5000 20054ef0 Blue Swirl
        return compute_c_incl();
5001 20054ef0 Blue Swirl
5002 20054ef0 Blue Swirl
    case CC_OP_SHLB:
5003 20054ef0 Blue Swirl
        return compute_c_shlb();
5004 20054ef0 Blue Swirl
    case CC_OP_SHLW:
5005 20054ef0 Blue Swirl
        return compute_c_shlw();
5006 20054ef0 Blue Swirl
    case CC_OP_SHLL:
5007 20054ef0 Blue Swirl
        return compute_c_shll();
5008 20054ef0 Blue Swirl
5009 20054ef0 Blue Swirl
    case CC_OP_SARB:
5010 20054ef0 Blue Swirl
        return compute_c_sarl();
5011 20054ef0 Blue Swirl
    case CC_OP_SARW:
5012 20054ef0 Blue Swirl
        return compute_c_sarl();
5013 20054ef0 Blue Swirl
    case CC_OP_SARL:
5014 20054ef0 Blue Swirl
        return compute_c_sarl();
5015 a7812ae4 pbrook
5016 a7812ae4 pbrook
#ifdef TARGET_X86_64
5017 20054ef0 Blue Swirl
    case CC_OP_MULQ:
5018 20054ef0 Blue Swirl
        return compute_c_mull();
5019 a7812ae4 pbrook
5020 20054ef0 Blue Swirl
    case CC_OP_ADDQ:
5021 20054ef0 Blue Swirl
        return compute_c_addq();
5022 a7812ae4 pbrook
5023 20054ef0 Blue Swirl
    case CC_OP_ADCQ:
5024 20054ef0 Blue Swirl
        return compute_c_adcq();
5025 a7812ae4 pbrook
5026 20054ef0 Blue Swirl
    case CC_OP_SUBQ:
5027 20054ef0 Blue Swirl
        return compute_c_subq();
5028 a7812ae4 pbrook
5029 20054ef0 Blue Swirl
    case CC_OP_SBBQ:
5030 20054ef0 Blue Swirl
        return compute_c_sbbq();
5031 a7812ae4 pbrook
5032 20054ef0 Blue Swirl
    case CC_OP_LOGICQ:
5033 20054ef0 Blue Swirl
        return compute_c_logicq();
5034 a7812ae4 pbrook
5035 20054ef0 Blue Swirl
    case CC_OP_INCQ:
5036 20054ef0 Blue Swirl
        return compute_c_incl();
5037 a7812ae4 pbrook
5038 20054ef0 Blue Swirl
    case CC_OP_DECQ:
5039 20054ef0 Blue Swirl
        return compute_c_incl();
5040 a7812ae4 pbrook
5041 20054ef0 Blue Swirl
    case CC_OP_SHLQ:
5042 20054ef0 Blue Swirl
        return compute_c_shlq();
5043 a7812ae4 pbrook
5044 20054ef0 Blue Swirl
    case CC_OP_SARQ:
5045 20054ef0 Blue Swirl
        return compute_c_sarl();
5046 a7812ae4 pbrook
#endif
5047 a7812ae4 pbrook
    }
5048 a7812ae4 pbrook
}