Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 38de4c46

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

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

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