Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 8c0d577e

History | View | Annotate | Download (159 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 eaa728ee bellard
#define CPU_NO_GLOBAL_REGS
20 eaa728ee bellard
#include "exec.h"
21 d9957a8b blueswir1
#include "exec-all.h"
22 eaa728ee bellard
#include "host-utils.h"
23 35bed8ee Paul Brook
#include "ioport.h"
24 eaa728ee bellard
25 eaa728ee bellard
//#define DEBUG_PCALL
26 eaa728ee bellard
27 d12d51d5 aliguori
28 d12d51d5 aliguori
#ifdef DEBUG_PCALL
29 93fcfe39 aliguori
#  define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
30 93fcfe39 aliguori
#  define LOG_PCALL_STATE(env) \
31 93fcfe39 aliguori
          log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
32 d12d51d5 aliguori
#else
33 d12d51d5 aliguori
#  define LOG_PCALL(...) do { } while (0)
34 d12d51d5 aliguori
#  define LOG_PCALL_STATE(env) do { } while (0)
35 d12d51d5 aliguori
#endif
36 d12d51d5 aliguori
37 d12d51d5 aliguori
38 eaa728ee bellard
#if 0
39 eaa728ee bellard
#define raise_exception_err(a, b)\
40 eaa728ee bellard
do {\
41 93fcfe39 aliguori
    qemu_log("raise_exception line=%d\n", __LINE__);\
42 eaa728ee bellard
    (raise_exception_err)(a, b);\
43 eaa728ee bellard
} while (0)
44 eaa728ee bellard
#endif
45 eaa728ee bellard
46 d9957a8b blueswir1
static const uint8_t parity_table[256] = {
47 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
48 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
49 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
51 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
52 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
53 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
55 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
56 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
57 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
58 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
59 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
60 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
61 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
62 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
63 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
64 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
65 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
66 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
67 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
68 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
69 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
70 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
71 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
72 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
73 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
74 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
75 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
76 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
77 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
78 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
79 eaa728ee bellard
};
80 eaa728ee bellard
81 eaa728ee bellard
/* modulo 17 table */
82 d9957a8b blueswir1
static const uint8_t rclw_table[32] = {
83 eaa728ee bellard
    0, 1, 2, 3, 4, 5, 6, 7,
84 eaa728ee bellard
    8, 9,10,11,12,13,14,15,
85 eaa728ee bellard
   16, 0, 1, 2, 3, 4, 5, 6,
86 eaa728ee bellard
    7, 8, 9,10,11,12,13,14,
87 eaa728ee bellard
};
88 eaa728ee bellard
89 eaa728ee bellard
/* modulo 9 table */
90 d9957a8b blueswir1
static const uint8_t rclb_table[32] = {
91 eaa728ee bellard
    0, 1, 2, 3, 4, 5, 6, 7,
92 eaa728ee bellard
    8, 0, 1, 2, 3, 4, 5, 6,
93 eaa728ee bellard
    7, 8, 0, 1, 2, 3, 4, 5,
94 eaa728ee bellard
    6, 7, 8, 0, 1, 2, 3, 4,
95 eaa728ee bellard
};
96 eaa728ee bellard
97 d9957a8b blueswir1
static const CPU86_LDouble f15rk[7] =
98 eaa728ee bellard
{
99 eaa728ee bellard
    0.00000000000000000000L,
100 eaa728ee bellard
    1.00000000000000000000L,
101 eaa728ee bellard
    3.14159265358979323851L,  /*pi*/
102 eaa728ee bellard
    0.30102999566398119523L,  /*lg2*/
103 eaa728ee bellard
    0.69314718055994530943L,  /*ln2*/
104 eaa728ee bellard
    1.44269504088896340739L,  /*l2e*/
105 eaa728ee bellard
    3.32192809488736234781L,  /*l2t*/
106 eaa728ee bellard
};
107 eaa728ee bellard
108 eaa728ee bellard
/* broken thread support */
109 eaa728ee bellard
110 c227f099 Anthony Liguori
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
111 eaa728ee bellard
112 eaa728ee bellard
void helper_lock(void)
113 eaa728ee bellard
{
114 eaa728ee bellard
    spin_lock(&global_cpu_lock);
115 eaa728ee bellard
}
116 eaa728ee bellard
117 eaa728ee bellard
void helper_unlock(void)
118 eaa728ee bellard
{
119 eaa728ee bellard
    spin_unlock(&global_cpu_lock);
120 eaa728ee bellard
}
121 eaa728ee bellard
122 eaa728ee bellard
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
123 eaa728ee bellard
{
124 eaa728ee bellard
    load_eflags(t0, update_mask);
125 eaa728ee bellard
}
126 eaa728ee bellard
127 eaa728ee bellard
target_ulong helper_read_eflags(void)
128 eaa728ee bellard
{
129 eaa728ee bellard
    uint32_t eflags;
130 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
131 eaa728ee bellard
    eflags |= (DF & DF_MASK);
132 eaa728ee bellard
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
133 eaa728ee bellard
    return eflags;
134 eaa728ee bellard
}
135 eaa728ee bellard
136 eaa728ee bellard
/* return non zero if error */
137 eaa728ee bellard
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
138 eaa728ee bellard
                               int selector)
139 eaa728ee bellard
{
140 eaa728ee bellard
    SegmentCache *dt;
141 eaa728ee bellard
    int index;
142 eaa728ee bellard
    target_ulong ptr;
143 eaa728ee bellard
144 eaa728ee bellard
    if (selector & 0x4)
145 eaa728ee bellard
        dt = &env->ldt;
146 eaa728ee bellard
    else
147 eaa728ee bellard
        dt = &env->gdt;
148 eaa728ee bellard
    index = selector & ~7;
149 eaa728ee bellard
    if ((index + 7) > dt->limit)
150 eaa728ee bellard
        return -1;
151 eaa728ee bellard
    ptr = dt->base + index;
152 eaa728ee bellard
    *e1_ptr = ldl_kernel(ptr);
153 eaa728ee bellard
    *e2_ptr = ldl_kernel(ptr + 4);
154 eaa728ee bellard
    return 0;
155 eaa728ee bellard
}
156 eaa728ee bellard
157 eaa728ee bellard
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
158 eaa728ee bellard
{
159 eaa728ee bellard
    unsigned int limit;
160 eaa728ee bellard
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
161 eaa728ee bellard
    if (e2 & DESC_G_MASK)
162 eaa728ee bellard
        limit = (limit << 12) | 0xfff;
163 eaa728ee bellard
    return limit;
164 eaa728ee bellard
}
165 eaa728ee bellard
166 eaa728ee bellard
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
167 eaa728ee bellard
{
168 eaa728ee bellard
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
169 eaa728ee bellard
}
170 eaa728ee bellard
171 eaa728ee bellard
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
172 eaa728ee bellard
{
173 eaa728ee bellard
    sc->base = get_seg_base(e1, e2);
174 eaa728ee bellard
    sc->limit = get_seg_limit(e1, e2);
175 eaa728ee bellard
    sc->flags = e2;
176 eaa728ee bellard
}
177 eaa728ee bellard
178 eaa728ee bellard
/* init the segment cache in vm86 mode. */
179 eaa728ee bellard
static inline void load_seg_vm(int seg, int selector)
180 eaa728ee bellard
{
181 eaa728ee bellard
    selector &= 0xffff;
182 eaa728ee bellard
    cpu_x86_load_seg_cache(env, seg, selector,
183 eaa728ee bellard
                           (selector << 4), 0xffff, 0);
184 eaa728ee bellard
}
185 eaa728ee bellard
186 eaa728ee bellard
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
187 eaa728ee bellard
                                       uint32_t *esp_ptr, int dpl)
188 eaa728ee bellard
{
189 eaa728ee bellard
    int type, index, shift;
190 eaa728ee bellard
191 eaa728ee bellard
#if 0
192 eaa728ee bellard
    {
193 eaa728ee bellard
        int i;
194 eaa728ee bellard
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
195 eaa728ee bellard
        for(i=0;i<env->tr.limit;i++) {
196 eaa728ee bellard
            printf("%02x ", env->tr.base[i]);
197 eaa728ee bellard
            if ((i & 7) == 7) printf("\n");
198 eaa728ee bellard
        }
199 eaa728ee bellard
        printf("\n");
200 eaa728ee bellard
    }
201 eaa728ee bellard
#endif
202 eaa728ee bellard
203 eaa728ee bellard
    if (!(env->tr.flags & DESC_P_MASK))
204 eaa728ee bellard
        cpu_abort(env, "invalid tss");
205 eaa728ee bellard
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
206 eaa728ee bellard
    if ((type & 7) != 1)
207 eaa728ee bellard
        cpu_abort(env, "invalid tss type");
208 eaa728ee bellard
    shift = type >> 3;
209 eaa728ee bellard
    index = (dpl * 4 + 2) << shift;
210 eaa728ee bellard
    if (index + (4 << shift) - 1 > env->tr.limit)
211 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
212 eaa728ee bellard
    if (shift == 0) {
213 eaa728ee bellard
        *esp_ptr = lduw_kernel(env->tr.base + index);
214 eaa728ee bellard
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
215 eaa728ee bellard
    } else {
216 eaa728ee bellard
        *esp_ptr = ldl_kernel(env->tr.base + index);
217 eaa728ee bellard
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
218 eaa728ee bellard
    }
219 eaa728ee bellard
}
220 eaa728ee bellard
221 eaa728ee bellard
/* XXX: merge with load_seg() */
222 eaa728ee bellard
static void tss_load_seg(int seg_reg, int selector)
223 eaa728ee bellard
{
224 eaa728ee bellard
    uint32_t e1, e2;
225 eaa728ee bellard
    int rpl, dpl, cpl;
226 eaa728ee bellard
227 eaa728ee bellard
    if ((selector & 0xfffc) != 0) {
228 eaa728ee bellard
        if (load_segment(&e1, &e2, selector) != 0)
229 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
230 eaa728ee bellard
        if (!(e2 & DESC_S_MASK))
231 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
232 eaa728ee bellard
        rpl = selector & 3;
233 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
234 eaa728ee bellard
        cpl = env->hflags & HF_CPL_MASK;
235 eaa728ee bellard
        if (seg_reg == R_CS) {
236 eaa728ee bellard
            if (!(e2 & DESC_CS_MASK))
237 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
238 eaa728ee bellard
            /* XXX: is it correct ? */
239 eaa728ee bellard
            if (dpl != rpl)
240 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
241 eaa728ee bellard
            if ((e2 & DESC_C_MASK) && dpl > rpl)
242 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
243 eaa728ee bellard
        } else if (seg_reg == R_SS) {
244 eaa728ee bellard
            /* SS must be writable data */
245 eaa728ee bellard
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
246 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
247 eaa728ee bellard
            if (dpl != cpl || dpl != rpl)
248 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
249 eaa728ee bellard
        } else {
250 eaa728ee bellard
            /* not readable code */
251 eaa728ee bellard
            if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
252 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
253 eaa728ee bellard
            /* if data or non conforming code, checks the rights */
254 eaa728ee bellard
            if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
255 eaa728ee bellard
                if (dpl < cpl || dpl < rpl)
256 eaa728ee bellard
                    raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
257 eaa728ee bellard
            }
258 eaa728ee bellard
        }
259 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
260 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
261 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector,
262 eaa728ee bellard
                       get_seg_base(e1, e2),
263 eaa728ee bellard
                       get_seg_limit(e1, e2),
264 eaa728ee bellard
                       e2);
265 eaa728ee bellard
    } else {
266 eaa728ee bellard
        if (seg_reg == R_SS || seg_reg == R_CS)
267 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
268 eaa728ee bellard
    }
269 eaa728ee bellard
}
270 eaa728ee bellard
271 eaa728ee bellard
#define SWITCH_TSS_JMP  0
272 eaa728ee bellard
#define SWITCH_TSS_IRET 1
273 eaa728ee bellard
#define SWITCH_TSS_CALL 2
274 eaa728ee bellard
275 eaa728ee bellard
/* XXX: restore CPU state in registers (PowerPC case) */
276 eaa728ee bellard
static void switch_tss(int tss_selector,
277 eaa728ee bellard
                       uint32_t e1, uint32_t e2, int source,
278 eaa728ee bellard
                       uint32_t next_eip)
279 eaa728ee bellard
{
280 eaa728ee bellard
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
281 eaa728ee bellard
    target_ulong tss_base;
282 eaa728ee bellard
    uint32_t new_regs[8], new_segs[6];
283 eaa728ee bellard
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
284 eaa728ee bellard
    uint32_t old_eflags, eflags_mask;
285 eaa728ee bellard
    SegmentCache *dt;
286 eaa728ee bellard
    int index;
287 eaa728ee bellard
    target_ulong ptr;
288 eaa728ee bellard
289 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
290 d12d51d5 aliguori
    LOG_PCALL("switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
291 eaa728ee bellard
292 eaa728ee bellard
    /* if task gate, we read the TSS segment and we load it */
293 eaa728ee bellard
    if (type == 5) {
294 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
295 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
296 eaa728ee bellard
        tss_selector = e1 >> 16;
297 eaa728ee bellard
        if (tss_selector & 4)
298 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
299 eaa728ee bellard
        if (load_segment(&e1, &e2, tss_selector) != 0)
300 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
301 eaa728ee bellard
        if (e2 & DESC_S_MASK)
302 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
303 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
304 eaa728ee bellard
        if ((type & 7) != 1)
305 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
306 eaa728ee bellard
    }
307 eaa728ee bellard
308 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
309 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
310 eaa728ee bellard
311 eaa728ee bellard
    if (type & 8)
312 eaa728ee bellard
        tss_limit_max = 103;
313 eaa728ee bellard
    else
314 eaa728ee bellard
        tss_limit_max = 43;
315 eaa728ee bellard
    tss_limit = get_seg_limit(e1, e2);
316 eaa728ee bellard
    tss_base = get_seg_base(e1, e2);
317 eaa728ee bellard
    if ((tss_selector & 4) != 0 ||
318 eaa728ee bellard
        tss_limit < tss_limit_max)
319 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
320 eaa728ee bellard
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
321 eaa728ee bellard
    if (old_type & 8)
322 eaa728ee bellard
        old_tss_limit_max = 103;
323 eaa728ee bellard
    else
324 eaa728ee bellard
        old_tss_limit_max = 43;
325 eaa728ee bellard
326 eaa728ee bellard
    /* read all the registers from the new TSS */
327 eaa728ee bellard
    if (type & 8) {
328 eaa728ee bellard
        /* 32 bit */
329 eaa728ee bellard
        new_cr3 = ldl_kernel(tss_base + 0x1c);
330 eaa728ee bellard
        new_eip = ldl_kernel(tss_base + 0x20);
331 eaa728ee bellard
        new_eflags = ldl_kernel(tss_base + 0x24);
332 eaa728ee bellard
        for(i = 0; i < 8; i++)
333 eaa728ee bellard
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
334 eaa728ee bellard
        for(i = 0; i < 6; i++)
335 eaa728ee bellard
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
336 eaa728ee bellard
        new_ldt = lduw_kernel(tss_base + 0x60);
337 eaa728ee bellard
        new_trap = ldl_kernel(tss_base + 0x64);
338 eaa728ee bellard
    } else {
339 eaa728ee bellard
        /* 16 bit */
340 eaa728ee bellard
        new_cr3 = 0;
341 eaa728ee bellard
        new_eip = lduw_kernel(tss_base + 0x0e);
342 eaa728ee bellard
        new_eflags = lduw_kernel(tss_base + 0x10);
343 eaa728ee bellard
        for(i = 0; i < 8; i++)
344 eaa728ee bellard
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
345 eaa728ee bellard
        for(i = 0; i < 4; i++)
346 eaa728ee bellard
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
347 eaa728ee bellard
        new_ldt = lduw_kernel(tss_base + 0x2a);
348 eaa728ee bellard
        new_segs[R_FS] = 0;
349 eaa728ee bellard
        new_segs[R_GS] = 0;
350 eaa728ee bellard
        new_trap = 0;
351 eaa728ee bellard
    }
352 eaa728ee bellard
353 eaa728ee bellard
    /* NOTE: we must avoid memory exceptions during the task switch,
354 eaa728ee bellard
       so we make dummy accesses before */
355 eaa728ee bellard
    /* XXX: it can still fail in some cases, so a bigger hack is
356 eaa728ee bellard
       necessary to valid the TLB after having done the accesses */
357 eaa728ee bellard
358 eaa728ee bellard
    v1 = ldub_kernel(env->tr.base);
359 eaa728ee bellard
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
360 eaa728ee bellard
    stb_kernel(env->tr.base, v1);
361 eaa728ee bellard
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
362 eaa728ee bellard
363 eaa728ee bellard
    /* clear busy bit (it is restartable) */
364 eaa728ee bellard
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
365 eaa728ee bellard
        target_ulong ptr;
366 eaa728ee bellard
        uint32_t e2;
367 eaa728ee bellard
        ptr = env->gdt.base + (env->tr.selector & ~7);
368 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
369 eaa728ee bellard
        e2 &= ~DESC_TSS_BUSY_MASK;
370 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
371 eaa728ee bellard
    }
372 eaa728ee bellard
    old_eflags = compute_eflags();
373 eaa728ee bellard
    if (source == SWITCH_TSS_IRET)
374 eaa728ee bellard
        old_eflags &= ~NT_MASK;
375 eaa728ee bellard
376 eaa728ee bellard
    /* save the current state in the old TSS */
377 eaa728ee bellard
    if (type & 8) {
378 eaa728ee bellard
        /* 32 bit */
379 eaa728ee bellard
        stl_kernel(env->tr.base + 0x20, next_eip);
380 eaa728ee bellard
        stl_kernel(env->tr.base + 0x24, old_eflags);
381 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
382 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
383 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
384 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
385 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
386 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
387 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
388 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
389 eaa728ee bellard
        for(i = 0; i < 6; i++)
390 eaa728ee bellard
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
391 eaa728ee bellard
    } else {
392 eaa728ee bellard
        /* 16 bit */
393 eaa728ee bellard
        stw_kernel(env->tr.base + 0x0e, next_eip);
394 eaa728ee bellard
        stw_kernel(env->tr.base + 0x10, old_eflags);
395 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
396 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
397 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
398 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
399 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
400 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
401 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
402 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
403 eaa728ee bellard
        for(i = 0; i < 4; i++)
404 eaa728ee bellard
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
405 eaa728ee bellard
    }
406 eaa728ee bellard
407 eaa728ee bellard
    /* now if an exception occurs, it will occurs in the next task
408 eaa728ee bellard
       context */
409 eaa728ee bellard
410 eaa728ee bellard
    if (source == SWITCH_TSS_CALL) {
411 eaa728ee bellard
        stw_kernel(tss_base, env->tr.selector);
412 eaa728ee bellard
        new_eflags |= NT_MASK;
413 eaa728ee bellard
    }
414 eaa728ee bellard
415 eaa728ee bellard
    /* set busy bit */
416 eaa728ee bellard
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
417 eaa728ee bellard
        target_ulong ptr;
418 eaa728ee bellard
        uint32_t e2;
419 eaa728ee bellard
        ptr = env->gdt.base + (tss_selector & ~7);
420 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
421 eaa728ee bellard
        e2 |= DESC_TSS_BUSY_MASK;
422 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
423 eaa728ee bellard
    }
424 eaa728ee bellard
425 eaa728ee bellard
    /* set the new CPU state */
426 eaa728ee bellard
    /* from this point, any exception which occurs can give problems */
427 eaa728ee bellard
    env->cr[0] |= CR0_TS_MASK;
428 eaa728ee bellard
    env->hflags |= HF_TS_MASK;
429 eaa728ee bellard
    env->tr.selector = tss_selector;
430 eaa728ee bellard
    env->tr.base = tss_base;
431 eaa728ee bellard
    env->tr.limit = tss_limit;
432 eaa728ee bellard
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
433 eaa728ee bellard
434 eaa728ee bellard
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
435 eaa728ee bellard
        cpu_x86_update_cr3(env, new_cr3);
436 eaa728ee bellard
    }
437 eaa728ee bellard
438 eaa728ee bellard
    /* load all registers without an exception, then reload them with
439 eaa728ee bellard
       possible exception */
440 eaa728ee bellard
    env->eip = new_eip;
441 eaa728ee bellard
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
442 eaa728ee bellard
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
443 eaa728ee bellard
    if (!(type & 8))
444 eaa728ee bellard
        eflags_mask &= 0xffff;
445 eaa728ee bellard
    load_eflags(new_eflags, eflags_mask);
446 eaa728ee bellard
    /* XXX: what to do in 16 bit case ? */
447 eaa728ee bellard
    EAX = new_regs[0];
448 eaa728ee bellard
    ECX = new_regs[1];
449 eaa728ee bellard
    EDX = new_regs[2];
450 eaa728ee bellard
    EBX = new_regs[3];
451 eaa728ee bellard
    ESP = new_regs[4];
452 eaa728ee bellard
    EBP = new_regs[5];
453 eaa728ee bellard
    ESI = new_regs[6];
454 eaa728ee bellard
    EDI = new_regs[7];
455 eaa728ee bellard
    if (new_eflags & VM_MASK) {
456 eaa728ee bellard
        for(i = 0; i < 6; i++)
457 eaa728ee bellard
            load_seg_vm(i, new_segs[i]);
458 eaa728ee bellard
        /* in vm86, CPL is always 3 */
459 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
460 eaa728ee bellard
    } else {
461 eaa728ee bellard
        /* CPL is set the RPL of CS */
462 eaa728ee bellard
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
463 eaa728ee bellard
        /* first just selectors as the rest may trigger exceptions */
464 eaa728ee bellard
        for(i = 0; i < 6; i++)
465 eaa728ee bellard
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
466 eaa728ee bellard
    }
467 eaa728ee bellard
468 eaa728ee bellard
    env->ldt.selector = new_ldt & ~4;
469 eaa728ee bellard
    env->ldt.base = 0;
470 eaa728ee bellard
    env->ldt.limit = 0;
471 eaa728ee bellard
    env->ldt.flags = 0;
472 eaa728ee bellard
473 eaa728ee bellard
    /* load the LDT */
474 eaa728ee bellard
    if (new_ldt & 4)
475 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
476 eaa728ee bellard
477 eaa728ee bellard
    if ((new_ldt & 0xfffc) != 0) {
478 eaa728ee bellard
        dt = &env->gdt;
479 eaa728ee bellard
        index = new_ldt & ~7;
480 eaa728ee bellard
        if ((index + 7) > dt->limit)
481 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
482 eaa728ee bellard
        ptr = dt->base + index;
483 eaa728ee bellard
        e1 = ldl_kernel(ptr);
484 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
485 eaa728ee bellard
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
486 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
487 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
488 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
489 eaa728ee bellard
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
490 eaa728ee bellard
    }
491 eaa728ee bellard
492 eaa728ee bellard
    /* load the segments */
493 eaa728ee bellard
    if (!(new_eflags & VM_MASK)) {
494 eaa728ee bellard
        tss_load_seg(R_CS, new_segs[R_CS]);
495 eaa728ee bellard
        tss_load_seg(R_SS, new_segs[R_SS]);
496 eaa728ee bellard
        tss_load_seg(R_ES, new_segs[R_ES]);
497 eaa728ee bellard
        tss_load_seg(R_DS, new_segs[R_DS]);
498 eaa728ee bellard
        tss_load_seg(R_FS, new_segs[R_FS]);
499 eaa728ee bellard
        tss_load_seg(R_GS, new_segs[R_GS]);
500 eaa728ee bellard
    }
501 eaa728ee bellard
502 eaa728ee bellard
    /* check that EIP is in the CS segment limits */
503 eaa728ee bellard
    if (new_eip > env->segs[R_CS].limit) {
504 eaa728ee bellard
        /* XXX: different exception if CALL ? */
505 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
506 eaa728ee bellard
    }
507 01df040b aliguori
508 01df040b aliguori
#ifndef CONFIG_USER_ONLY
509 01df040b aliguori
    /* reset local breakpoints */
510 01df040b aliguori
    if (env->dr[7] & 0x55) {
511 01df040b aliguori
        for (i = 0; i < 4; i++) {
512 01df040b aliguori
            if (hw_breakpoint_enabled(env->dr[7], i) == 0x1)
513 01df040b aliguori
                hw_breakpoint_remove(env, i);
514 01df040b aliguori
        }
515 01df040b aliguori
        env->dr[7] &= ~0x55;
516 01df040b aliguori
    }
517 01df040b aliguori
#endif
518 eaa728ee bellard
}
519 eaa728ee bellard
520 eaa728ee bellard
/* check if Port I/O is allowed in TSS */
521 eaa728ee bellard
static inline void check_io(int addr, int size)
522 eaa728ee bellard
{
523 eaa728ee bellard
    int io_offset, val, mask;
524 eaa728ee bellard
525 eaa728ee bellard
    /* TSS must be a valid 32 bit one */
526 eaa728ee bellard
    if (!(env->tr.flags & DESC_P_MASK) ||
527 eaa728ee bellard
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
528 eaa728ee bellard
        env->tr.limit < 103)
529 eaa728ee bellard
        goto fail;
530 eaa728ee bellard
    io_offset = lduw_kernel(env->tr.base + 0x66);
531 eaa728ee bellard
    io_offset += (addr >> 3);
532 eaa728ee bellard
    /* Note: the check needs two bytes */
533 eaa728ee bellard
    if ((io_offset + 1) > env->tr.limit)
534 eaa728ee bellard
        goto fail;
535 eaa728ee bellard
    val = lduw_kernel(env->tr.base + io_offset);
536 eaa728ee bellard
    val >>= (addr & 7);
537 eaa728ee bellard
    mask = (1 << size) - 1;
538 eaa728ee bellard
    /* all bits must be zero to allow the I/O */
539 eaa728ee bellard
    if ((val & mask) != 0) {
540 eaa728ee bellard
    fail:
541 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
542 eaa728ee bellard
    }
543 eaa728ee bellard
}
544 eaa728ee bellard
545 eaa728ee bellard
void helper_check_iob(uint32_t t0)
546 eaa728ee bellard
{
547 eaa728ee bellard
    check_io(t0, 1);
548 eaa728ee bellard
}
549 eaa728ee bellard
550 eaa728ee bellard
void helper_check_iow(uint32_t t0)
551 eaa728ee bellard
{
552 eaa728ee bellard
    check_io(t0, 2);
553 eaa728ee bellard
}
554 eaa728ee bellard
555 eaa728ee bellard
void helper_check_iol(uint32_t t0)
556 eaa728ee bellard
{
557 eaa728ee bellard
    check_io(t0, 4);
558 eaa728ee bellard
}
559 eaa728ee bellard
560 eaa728ee bellard
void helper_outb(uint32_t port, uint32_t data)
561 eaa728ee bellard
{
562 afcea8cb Blue Swirl
    cpu_outb(port, data & 0xff);
563 eaa728ee bellard
}
564 eaa728ee bellard
565 eaa728ee bellard
target_ulong helper_inb(uint32_t port)
566 eaa728ee bellard
{
567 afcea8cb Blue Swirl
    return cpu_inb(port);
568 eaa728ee bellard
}
569 eaa728ee bellard
570 eaa728ee bellard
void helper_outw(uint32_t port, uint32_t data)
571 eaa728ee bellard
{
572 afcea8cb Blue Swirl
    cpu_outw(port, data & 0xffff);
573 eaa728ee bellard
}
574 eaa728ee bellard
575 eaa728ee bellard
target_ulong helper_inw(uint32_t port)
576 eaa728ee bellard
{
577 afcea8cb Blue Swirl
    return cpu_inw(port);
578 eaa728ee bellard
}
579 eaa728ee bellard
580 eaa728ee bellard
void helper_outl(uint32_t port, uint32_t data)
581 eaa728ee bellard
{
582 afcea8cb Blue Swirl
    cpu_outl(port, data);
583 eaa728ee bellard
}
584 eaa728ee bellard
585 eaa728ee bellard
target_ulong helper_inl(uint32_t port)
586 eaa728ee bellard
{
587 afcea8cb Blue Swirl
    return cpu_inl(port);
588 eaa728ee bellard
}
589 eaa728ee bellard
590 eaa728ee bellard
static inline unsigned int get_sp_mask(unsigned int e2)
591 eaa728ee bellard
{
592 eaa728ee bellard
    if (e2 & DESC_B_MASK)
593 eaa728ee bellard
        return 0xffffffff;
594 eaa728ee bellard
    else
595 eaa728ee bellard
        return 0xffff;
596 eaa728ee bellard
}
597 eaa728ee bellard
598 2ed51f5b aliguori
static int exeption_has_error_code(int intno)
599 2ed51f5b aliguori
{
600 2ed51f5b aliguori
        switch(intno) {
601 2ed51f5b aliguori
        case 8:
602 2ed51f5b aliguori
        case 10:
603 2ed51f5b aliguori
        case 11:
604 2ed51f5b aliguori
        case 12:
605 2ed51f5b aliguori
        case 13:
606 2ed51f5b aliguori
        case 14:
607 2ed51f5b aliguori
        case 17:
608 2ed51f5b aliguori
            return 1;
609 2ed51f5b aliguori
        }
610 2ed51f5b aliguori
        return 0;
611 2ed51f5b aliguori
}
612 2ed51f5b aliguori
613 eaa728ee bellard
#ifdef TARGET_X86_64
614 eaa728ee bellard
#define SET_ESP(val, sp_mask)\
615 eaa728ee bellard
do {\
616 eaa728ee bellard
    if ((sp_mask) == 0xffff)\
617 eaa728ee bellard
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
618 eaa728ee bellard
    else if ((sp_mask) == 0xffffffffLL)\
619 eaa728ee bellard
        ESP = (uint32_t)(val);\
620 eaa728ee bellard
    else\
621 eaa728ee bellard
        ESP = (val);\
622 eaa728ee bellard
} while (0)
623 eaa728ee bellard
#else
624 eaa728ee bellard
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
625 eaa728ee bellard
#endif
626 eaa728ee bellard
627 c0a04f0e aliguori
/* in 64-bit machines, this can overflow. So this segment addition macro
628 c0a04f0e aliguori
 * can be used to trim the value to 32-bit whenever needed */
629 c0a04f0e aliguori
#define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
630 c0a04f0e aliguori
631 eaa728ee bellard
/* XXX: add a is_user flag to have proper security support */
632 eaa728ee bellard
#define PUSHW(ssp, sp, sp_mask, val)\
633 eaa728ee bellard
{\
634 eaa728ee bellard
    sp -= 2;\
635 eaa728ee bellard
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
636 eaa728ee bellard
}
637 eaa728ee bellard
638 eaa728ee bellard
#define PUSHL(ssp, sp, sp_mask, val)\
639 eaa728ee bellard
{\
640 eaa728ee bellard
    sp -= 4;\
641 c0a04f0e aliguori
    stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
642 eaa728ee bellard
}
643 eaa728ee bellard
644 eaa728ee bellard
#define POPW(ssp, sp, sp_mask, val)\
645 eaa728ee bellard
{\
646 eaa728ee bellard
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
647 eaa728ee bellard
    sp += 2;\
648 eaa728ee bellard
}
649 eaa728ee bellard
650 eaa728ee bellard
#define POPL(ssp, sp, sp_mask, val)\
651 eaa728ee bellard
{\
652 c0a04f0e aliguori
    val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
653 eaa728ee bellard
    sp += 4;\
654 eaa728ee bellard
}
655 eaa728ee bellard
656 eaa728ee bellard
/* protected mode interrupt */
657 eaa728ee bellard
static void do_interrupt_protected(int intno, int is_int, int error_code,
658 eaa728ee bellard
                                   unsigned int next_eip, int is_hw)
659 eaa728ee bellard
{
660 eaa728ee bellard
    SegmentCache *dt;
661 eaa728ee bellard
    target_ulong ptr, ssp;
662 eaa728ee bellard
    int type, dpl, selector, ss_dpl, cpl;
663 eaa728ee bellard
    int has_error_code, new_stack, shift;
664 1c918eba blueswir1
    uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
665 eaa728ee bellard
    uint32_t old_eip, sp_mask;
666 eaa728ee bellard
667 eaa728ee bellard
    has_error_code = 0;
668 2ed51f5b aliguori
    if (!is_int && !is_hw)
669 2ed51f5b aliguori
        has_error_code = exeption_has_error_code(intno);
670 eaa728ee bellard
    if (is_int)
671 eaa728ee bellard
        old_eip = next_eip;
672 eaa728ee bellard
    else
673 eaa728ee bellard
        old_eip = env->eip;
674 eaa728ee bellard
675 eaa728ee bellard
    dt = &env->idt;
676 eaa728ee bellard
    if (intno * 8 + 7 > dt->limit)
677 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
678 eaa728ee bellard
    ptr = dt->base + intno * 8;
679 eaa728ee bellard
    e1 = ldl_kernel(ptr);
680 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
681 eaa728ee bellard
    /* check gate type */
682 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
683 eaa728ee bellard
    switch(type) {
684 eaa728ee bellard
    case 5: /* task gate */
685 eaa728ee bellard
        /* must do that check here to return the correct error code */
686 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
687 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
688 eaa728ee bellard
        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
689 eaa728ee bellard
        if (has_error_code) {
690 eaa728ee bellard
            int type;
691 eaa728ee bellard
            uint32_t mask;
692 eaa728ee bellard
            /* push the error code */
693 eaa728ee bellard
            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
694 eaa728ee bellard
            shift = type >> 3;
695 eaa728ee bellard
            if (env->segs[R_SS].flags & DESC_B_MASK)
696 eaa728ee bellard
                mask = 0xffffffff;
697 eaa728ee bellard
            else
698 eaa728ee bellard
                mask = 0xffff;
699 eaa728ee bellard
            esp = (ESP - (2 << shift)) & mask;
700 eaa728ee bellard
            ssp = env->segs[R_SS].base + esp;
701 eaa728ee bellard
            if (shift)
702 eaa728ee bellard
                stl_kernel(ssp, error_code);
703 eaa728ee bellard
            else
704 eaa728ee bellard
                stw_kernel(ssp, error_code);
705 eaa728ee bellard
            SET_ESP(esp, mask);
706 eaa728ee bellard
        }
707 eaa728ee bellard
        return;
708 eaa728ee bellard
    case 6: /* 286 interrupt gate */
709 eaa728ee bellard
    case 7: /* 286 trap gate */
710 eaa728ee bellard
    case 14: /* 386 interrupt gate */
711 eaa728ee bellard
    case 15: /* 386 trap gate */
712 eaa728ee bellard
        break;
713 eaa728ee bellard
    default:
714 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
715 eaa728ee bellard
        break;
716 eaa728ee bellard
    }
717 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
718 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
719 1235fc06 ths
    /* check privilege if software int */
720 eaa728ee bellard
    if (is_int && dpl < cpl)
721 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
722 eaa728ee bellard
    /* check valid bit */
723 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
724 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
725 eaa728ee bellard
    selector = e1 >> 16;
726 eaa728ee bellard
    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
727 eaa728ee bellard
    if ((selector & 0xfffc) == 0)
728 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
729 eaa728ee bellard
730 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
731 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
732 eaa728ee bellard
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
733 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
734 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
735 eaa728ee bellard
    if (dpl > cpl)
736 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
737 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
738 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
739 eaa728ee bellard
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
740 eaa728ee bellard
        /* to inner privilege */
741 eaa728ee bellard
        get_ss_esp_from_tss(&ss, &esp, dpl);
742 eaa728ee bellard
        if ((ss & 0xfffc) == 0)
743 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
744 eaa728ee bellard
        if ((ss & 3) != dpl)
745 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
746 eaa728ee bellard
        if (load_segment(&ss_e1, &ss_e2, ss) != 0)
747 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
748 eaa728ee bellard
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
749 eaa728ee bellard
        if (ss_dpl != dpl)
750 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
751 eaa728ee bellard
        if (!(ss_e2 & DESC_S_MASK) ||
752 eaa728ee bellard
            (ss_e2 & DESC_CS_MASK) ||
753 eaa728ee bellard
            !(ss_e2 & DESC_W_MASK))
754 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
755 eaa728ee bellard
        if (!(ss_e2 & DESC_P_MASK))
756 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
757 eaa728ee bellard
        new_stack = 1;
758 eaa728ee bellard
        sp_mask = get_sp_mask(ss_e2);
759 eaa728ee bellard
        ssp = get_seg_base(ss_e1, ss_e2);
760 eaa728ee bellard
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
761 eaa728ee bellard
        /* to same privilege */
762 eaa728ee bellard
        if (env->eflags & VM_MASK)
763 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
764 eaa728ee bellard
        new_stack = 0;
765 eaa728ee bellard
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
766 eaa728ee bellard
        ssp = env->segs[R_SS].base;
767 eaa728ee bellard
        esp = ESP;
768 eaa728ee bellard
        dpl = cpl;
769 eaa728ee bellard
    } else {
770 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
771 eaa728ee bellard
        new_stack = 0; /* avoid warning */
772 eaa728ee bellard
        sp_mask = 0; /* avoid warning */
773 eaa728ee bellard
        ssp = 0; /* avoid warning */
774 eaa728ee bellard
        esp = 0; /* avoid warning */
775 eaa728ee bellard
    }
776 eaa728ee bellard
777 eaa728ee bellard
    shift = type >> 3;
778 eaa728ee bellard
779 eaa728ee bellard
#if 0
780 eaa728ee bellard
    /* XXX: check that enough room is available */
781 eaa728ee bellard
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
782 eaa728ee bellard
    if (env->eflags & VM_MASK)
783 eaa728ee bellard
        push_size += 8;
784 eaa728ee bellard
    push_size <<= shift;
785 eaa728ee bellard
#endif
786 eaa728ee bellard
    if (shift == 1) {
787 eaa728ee bellard
        if (new_stack) {
788 eaa728ee bellard
            if (env->eflags & VM_MASK) {
789 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
790 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
791 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
792 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
793 eaa728ee bellard
            }
794 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
795 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, ESP);
796 eaa728ee bellard
        }
797 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, compute_eflags());
798 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
799 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, old_eip);
800 eaa728ee bellard
        if (has_error_code) {
801 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, error_code);
802 eaa728ee bellard
        }
803 eaa728ee bellard
    } else {
804 eaa728ee bellard
        if (new_stack) {
805 eaa728ee bellard
            if (env->eflags & VM_MASK) {
806 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
807 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
808 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
809 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
810 eaa728ee bellard
            }
811 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
812 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, ESP);
813 eaa728ee bellard
        }
814 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, compute_eflags());
815 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
816 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, old_eip);
817 eaa728ee bellard
        if (has_error_code) {
818 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, error_code);
819 eaa728ee bellard
        }
820 eaa728ee bellard
    }
821 eaa728ee bellard
822 eaa728ee bellard
    if (new_stack) {
823 eaa728ee bellard
        if (env->eflags & VM_MASK) {
824 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
825 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
826 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
827 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
828 eaa728ee bellard
        }
829 eaa728ee bellard
        ss = (ss & ~3) | dpl;
830 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, ss,
831 eaa728ee bellard
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
832 eaa728ee bellard
    }
833 eaa728ee bellard
    SET_ESP(esp, sp_mask);
834 eaa728ee bellard
835 eaa728ee bellard
    selector = (selector & ~3) | dpl;
836 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, selector,
837 eaa728ee bellard
                   get_seg_base(e1, e2),
838 eaa728ee bellard
                   get_seg_limit(e1, e2),
839 eaa728ee bellard
                   e2);
840 eaa728ee bellard
    cpu_x86_set_cpl(env, dpl);
841 eaa728ee bellard
    env->eip = offset;
842 eaa728ee bellard
843 eaa728ee bellard
    /* interrupt gate clear IF mask */
844 eaa728ee bellard
    if ((type & 1) == 0) {
845 eaa728ee bellard
        env->eflags &= ~IF_MASK;
846 eaa728ee bellard
    }
847 eaa728ee bellard
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
848 eaa728ee bellard
}
849 eaa728ee bellard
850 eaa728ee bellard
#ifdef TARGET_X86_64
851 eaa728ee bellard
852 eaa728ee bellard
#define PUSHQ(sp, val)\
853 eaa728ee bellard
{\
854 eaa728ee bellard
    sp -= 8;\
855 eaa728ee bellard
    stq_kernel(sp, (val));\
856 eaa728ee bellard
}
857 eaa728ee bellard
858 eaa728ee bellard
#define POPQ(sp, val)\
859 eaa728ee bellard
{\
860 eaa728ee bellard
    val = ldq_kernel(sp);\
861 eaa728ee bellard
    sp += 8;\
862 eaa728ee bellard
}
863 eaa728ee bellard
864 eaa728ee bellard
static inline target_ulong get_rsp_from_tss(int level)
865 eaa728ee bellard
{
866 eaa728ee bellard
    int index;
867 eaa728ee bellard
868 eaa728ee bellard
#if 0
869 eaa728ee bellard
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
870 eaa728ee bellard
           env->tr.base, env->tr.limit);
871 eaa728ee bellard
#endif
872 eaa728ee bellard
873 eaa728ee bellard
    if (!(env->tr.flags & DESC_P_MASK))
874 eaa728ee bellard
        cpu_abort(env, "invalid tss");
875 eaa728ee bellard
    index = 8 * level + 4;
876 eaa728ee bellard
    if ((index + 7) > env->tr.limit)
877 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
878 eaa728ee bellard
    return ldq_kernel(env->tr.base + index);
879 eaa728ee bellard
}
880 eaa728ee bellard
881 eaa728ee bellard
/* 64 bit interrupt */
882 eaa728ee bellard
static void do_interrupt64(int intno, int is_int, int error_code,
883 eaa728ee bellard
                           target_ulong next_eip, int is_hw)
884 eaa728ee bellard
{
885 eaa728ee bellard
    SegmentCache *dt;
886 eaa728ee bellard
    target_ulong ptr;
887 eaa728ee bellard
    int type, dpl, selector, cpl, ist;
888 eaa728ee bellard
    int has_error_code, new_stack;
889 eaa728ee bellard
    uint32_t e1, e2, e3, ss;
890 eaa728ee bellard
    target_ulong old_eip, esp, offset;
891 eaa728ee bellard
892 eaa728ee bellard
    has_error_code = 0;
893 2ed51f5b aliguori
    if (!is_int && !is_hw)
894 2ed51f5b aliguori
        has_error_code = exeption_has_error_code(intno);
895 eaa728ee bellard
    if (is_int)
896 eaa728ee bellard
        old_eip = next_eip;
897 eaa728ee bellard
    else
898 eaa728ee bellard
        old_eip = env->eip;
899 eaa728ee bellard
900 eaa728ee bellard
    dt = &env->idt;
901 eaa728ee bellard
    if (intno * 16 + 15 > dt->limit)
902 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
903 eaa728ee bellard
    ptr = dt->base + intno * 16;
904 eaa728ee bellard
    e1 = ldl_kernel(ptr);
905 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
906 eaa728ee bellard
    e3 = ldl_kernel(ptr + 8);
907 eaa728ee bellard
    /* check gate type */
908 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
909 eaa728ee bellard
    switch(type) {
910 eaa728ee bellard
    case 14: /* 386 interrupt gate */
911 eaa728ee bellard
    case 15: /* 386 trap gate */
912 eaa728ee bellard
        break;
913 eaa728ee bellard
    default:
914 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
915 eaa728ee bellard
        break;
916 eaa728ee bellard
    }
917 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
918 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
919 1235fc06 ths
    /* check privilege if software int */
920 eaa728ee bellard
    if (is_int && dpl < cpl)
921 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
922 eaa728ee bellard
    /* check valid bit */
923 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
924 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
925 eaa728ee bellard
    selector = e1 >> 16;
926 eaa728ee bellard
    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
927 eaa728ee bellard
    ist = e2 & 7;
928 eaa728ee bellard
    if ((selector & 0xfffc) == 0)
929 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
930 eaa728ee bellard
931 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
932 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
933 eaa728ee bellard
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
934 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
935 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
936 eaa728ee bellard
    if (dpl > cpl)
937 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
938 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
939 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
940 eaa728ee bellard
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
941 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
942 eaa728ee bellard
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
943 eaa728ee bellard
        /* to inner privilege */
944 eaa728ee bellard
        if (ist != 0)
945 eaa728ee bellard
            esp = get_rsp_from_tss(ist + 3);
946 eaa728ee bellard
        else
947 eaa728ee bellard
            esp = get_rsp_from_tss(dpl);
948 eaa728ee bellard
        esp &= ~0xfLL; /* align stack */
949 eaa728ee bellard
        ss = 0;
950 eaa728ee bellard
        new_stack = 1;
951 eaa728ee bellard
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
952 eaa728ee bellard
        /* to same privilege */
953 eaa728ee bellard
        if (env->eflags & VM_MASK)
954 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
955 eaa728ee bellard
        new_stack = 0;
956 eaa728ee bellard
        if (ist != 0)
957 eaa728ee bellard
            esp = get_rsp_from_tss(ist + 3);
958 eaa728ee bellard
        else
959 eaa728ee bellard
            esp = ESP;
960 eaa728ee bellard
        esp &= ~0xfLL; /* align stack */
961 eaa728ee bellard
        dpl = cpl;
962 eaa728ee bellard
    } else {
963 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
964 eaa728ee bellard
        new_stack = 0; /* avoid warning */
965 eaa728ee bellard
        esp = 0; /* avoid warning */
966 eaa728ee bellard
    }
967 eaa728ee bellard
968 eaa728ee bellard
    PUSHQ(esp, env->segs[R_SS].selector);
969 eaa728ee bellard
    PUSHQ(esp, ESP);
970 eaa728ee bellard
    PUSHQ(esp, compute_eflags());
971 eaa728ee bellard
    PUSHQ(esp, env->segs[R_CS].selector);
972 eaa728ee bellard
    PUSHQ(esp, old_eip);
973 eaa728ee bellard
    if (has_error_code) {
974 eaa728ee bellard
        PUSHQ(esp, error_code);
975 eaa728ee bellard
    }
976 eaa728ee bellard
977 eaa728ee bellard
    if (new_stack) {
978 eaa728ee bellard
        ss = 0 | dpl;
979 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
980 eaa728ee bellard
    }
981 eaa728ee bellard
    ESP = esp;
982 eaa728ee bellard
983 eaa728ee bellard
    selector = (selector & ~3) | dpl;
984 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, selector,
985 eaa728ee bellard
                   get_seg_base(e1, e2),
986 eaa728ee bellard
                   get_seg_limit(e1, e2),
987 eaa728ee bellard
                   e2);
988 eaa728ee bellard
    cpu_x86_set_cpl(env, dpl);
989 eaa728ee bellard
    env->eip = offset;
990 eaa728ee bellard
991 eaa728ee bellard
    /* interrupt gate clear IF mask */
992 eaa728ee bellard
    if ((type & 1) == 0) {
993 eaa728ee bellard
        env->eflags &= ~IF_MASK;
994 eaa728ee bellard
    }
995 eaa728ee bellard
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
996 eaa728ee bellard
}
997 eaa728ee bellard
#endif
998 eaa728ee bellard
999 d9957a8b blueswir1
#ifdef TARGET_X86_64
1000 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
1001 eaa728ee bellard
void helper_syscall(int next_eip_addend)
1002 eaa728ee bellard
{
1003 eaa728ee bellard
    env->exception_index = EXCP_SYSCALL;
1004 eaa728ee bellard
    env->exception_next_eip = env->eip + next_eip_addend;
1005 eaa728ee bellard
    cpu_loop_exit();
1006 eaa728ee bellard
}
1007 eaa728ee bellard
#else
1008 eaa728ee bellard
void helper_syscall(int next_eip_addend)
1009 eaa728ee bellard
{
1010 eaa728ee bellard
    int selector;
1011 eaa728ee bellard
1012 eaa728ee bellard
    if (!(env->efer & MSR_EFER_SCE)) {
1013 eaa728ee bellard
        raise_exception_err(EXCP06_ILLOP, 0);
1014 eaa728ee bellard
    }
1015 eaa728ee bellard
    selector = (env->star >> 32) & 0xffff;
1016 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1017 eaa728ee bellard
        int code64;
1018 eaa728ee bellard
1019 eaa728ee bellard
        ECX = env->eip + next_eip_addend;
1020 eaa728ee bellard
        env->regs[11] = compute_eflags();
1021 eaa728ee bellard
1022 eaa728ee bellard
        code64 = env->hflags & HF_CS64_MASK;
1023 eaa728ee bellard
1024 eaa728ee bellard
        cpu_x86_set_cpl(env, 0);
1025 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1026 eaa728ee bellard
                           0, 0xffffffff,
1027 eaa728ee bellard
                               DESC_G_MASK | DESC_P_MASK |
1028 eaa728ee bellard
                               DESC_S_MASK |
1029 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1030 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1031 eaa728ee bellard
                               0, 0xffffffff,
1032 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1033 eaa728ee bellard
                               DESC_S_MASK |
1034 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1035 eaa728ee bellard
        env->eflags &= ~env->fmask;
1036 eaa728ee bellard
        load_eflags(env->eflags, 0);
1037 eaa728ee bellard
        if (code64)
1038 eaa728ee bellard
            env->eip = env->lstar;
1039 eaa728ee bellard
        else
1040 eaa728ee bellard
            env->eip = env->cstar;
1041 d9957a8b blueswir1
    } else {
1042 eaa728ee bellard
        ECX = (uint32_t)(env->eip + next_eip_addend);
1043 eaa728ee bellard
1044 eaa728ee bellard
        cpu_x86_set_cpl(env, 0);
1045 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1046 eaa728ee bellard
                           0, 0xffffffff,
1047 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1048 eaa728ee bellard
                               DESC_S_MASK |
1049 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1050 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1051 eaa728ee bellard
                               0, 0xffffffff,
1052 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1053 eaa728ee bellard
                               DESC_S_MASK |
1054 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1055 eaa728ee bellard
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1056 eaa728ee bellard
        env->eip = (uint32_t)env->star;
1057 eaa728ee bellard
    }
1058 eaa728ee bellard
}
1059 eaa728ee bellard
#endif
1060 d9957a8b blueswir1
#endif
1061 eaa728ee bellard
1062 d9957a8b blueswir1
#ifdef TARGET_X86_64
1063 eaa728ee bellard
void helper_sysret(int dflag)
1064 eaa728ee bellard
{
1065 eaa728ee bellard
    int cpl, selector;
1066 eaa728ee bellard
1067 eaa728ee bellard
    if (!(env->efer & MSR_EFER_SCE)) {
1068 eaa728ee bellard
        raise_exception_err(EXCP06_ILLOP, 0);
1069 eaa728ee bellard
    }
1070 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
1071 eaa728ee bellard
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1072 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
1073 eaa728ee bellard
    }
1074 eaa728ee bellard
    selector = (env->star >> 48) & 0xffff;
1075 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1076 eaa728ee bellard
        if (dflag == 2) {
1077 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1078 eaa728ee bellard
                                   0, 0xffffffff,
1079 eaa728ee bellard
                                   DESC_G_MASK | DESC_P_MASK |
1080 eaa728ee bellard
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1081 eaa728ee bellard
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1082 eaa728ee bellard
                                   DESC_L_MASK);
1083 eaa728ee bellard
            env->eip = ECX;
1084 eaa728ee bellard
        } else {
1085 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1086 eaa728ee bellard
                                   0, 0xffffffff,
1087 eaa728ee bellard
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1088 eaa728ee bellard
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1089 eaa728ee bellard
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1090 eaa728ee bellard
            env->eip = (uint32_t)ECX;
1091 eaa728ee bellard
        }
1092 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1093 eaa728ee bellard
                               0, 0xffffffff,
1094 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1095 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1096 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1097 eaa728ee bellard
        load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1098 eaa728ee bellard
                    IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1099 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
1100 d9957a8b blueswir1
    } else {
1101 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1102 eaa728ee bellard
                               0, 0xffffffff,
1103 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1104 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1105 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1106 eaa728ee bellard
        env->eip = (uint32_t)ECX;
1107 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1108 eaa728ee bellard
                               0, 0xffffffff,
1109 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1110 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1111 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1112 eaa728ee bellard
        env->eflags |= IF_MASK;
1113 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
1114 eaa728ee bellard
    }
1115 eaa728ee bellard
}
1116 d9957a8b blueswir1
#endif
1117 eaa728ee bellard
1118 eaa728ee bellard
/* real mode interrupt */
1119 eaa728ee bellard
static void do_interrupt_real(int intno, int is_int, int error_code,
1120 eaa728ee bellard
                              unsigned int next_eip)
1121 eaa728ee bellard
{
1122 eaa728ee bellard
    SegmentCache *dt;
1123 eaa728ee bellard
    target_ulong ptr, ssp;
1124 eaa728ee bellard
    int selector;
1125 eaa728ee bellard
    uint32_t offset, esp;
1126 eaa728ee bellard
    uint32_t old_cs, old_eip;
1127 eaa728ee bellard
1128 eaa728ee bellard
    /* real mode (simpler !) */
1129 eaa728ee bellard
    dt = &env->idt;
1130 eaa728ee bellard
    if (intno * 4 + 3 > dt->limit)
1131 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1132 eaa728ee bellard
    ptr = dt->base + intno * 4;
1133 eaa728ee bellard
    offset = lduw_kernel(ptr);
1134 eaa728ee bellard
    selector = lduw_kernel(ptr + 2);
1135 eaa728ee bellard
    esp = ESP;
1136 eaa728ee bellard
    ssp = env->segs[R_SS].base;
1137 eaa728ee bellard
    if (is_int)
1138 eaa728ee bellard
        old_eip = next_eip;
1139 eaa728ee bellard
    else
1140 eaa728ee bellard
        old_eip = env->eip;
1141 eaa728ee bellard
    old_cs = env->segs[R_CS].selector;
1142 eaa728ee bellard
    /* XXX: use SS segment size ? */
1143 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, compute_eflags());
1144 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, old_cs);
1145 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, old_eip);
1146 eaa728ee bellard
1147 eaa728ee bellard
    /* update processor state */
1148 eaa728ee bellard
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1149 eaa728ee bellard
    env->eip = offset;
1150 eaa728ee bellard
    env->segs[R_CS].selector = selector;
1151 eaa728ee bellard
    env->segs[R_CS].base = (selector << 4);
1152 eaa728ee bellard
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1153 eaa728ee bellard
}
1154 eaa728ee bellard
1155 eaa728ee bellard
/* fake user mode interrupt */
1156 eaa728ee bellard
void do_interrupt_user(int intno, int is_int, int error_code,
1157 eaa728ee bellard
                       target_ulong next_eip)
1158 eaa728ee bellard
{
1159 eaa728ee bellard
    SegmentCache *dt;
1160 eaa728ee bellard
    target_ulong ptr;
1161 eaa728ee bellard
    int dpl, cpl, shift;
1162 eaa728ee bellard
    uint32_t e2;
1163 eaa728ee bellard
1164 eaa728ee bellard
    dt = &env->idt;
1165 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1166 eaa728ee bellard
        shift = 4;
1167 eaa728ee bellard
    } else {
1168 eaa728ee bellard
        shift = 3;
1169 eaa728ee bellard
    }
1170 eaa728ee bellard
    ptr = dt->base + (intno << shift);
1171 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
1172 eaa728ee bellard
1173 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1174 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
1175 1235fc06 ths
    /* check privilege if software int */
1176 eaa728ee bellard
    if (is_int && dpl < cpl)
1177 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1178 eaa728ee bellard
1179 eaa728ee bellard
    /* Since we emulate only user space, we cannot do more than
1180 eaa728ee bellard
       exiting the emulation with the suitable exception and error
1181 eaa728ee bellard
       code */
1182 eaa728ee bellard
    if (is_int)
1183 eaa728ee bellard
        EIP = next_eip;
1184 eaa728ee bellard
}
1185 eaa728ee bellard
1186 00ea18d1 aliguori
#if !defined(CONFIG_USER_ONLY)
1187 2ed51f5b aliguori
static void handle_even_inj(int intno, int is_int, int error_code,
1188 2ed51f5b aliguori
                int is_hw, int rm)
1189 2ed51f5b aliguori
{
1190 2ed51f5b aliguori
    uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1191 2ed51f5b aliguori
    if (!(event_inj & SVM_EVTINJ_VALID)) {
1192 2ed51f5b aliguori
            int type;
1193 2ed51f5b aliguori
            if (is_int)
1194 2ed51f5b aliguori
                    type = SVM_EVTINJ_TYPE_SOFT;
1195 2ed51f5b aliguori
            else
1196 2ed51f5b aliguori
                    type = SVM_EVTINJ_TYPE_EXEPT;
1197 2ed51f5b aliguori
            event_inj = intno | type | SVM_EVTINJ_VALID;
1198 2ed51f5b aliguori
            if (!rm && exeption_has_error_code(intno)) {
1199 2ed51f5b aliguori
                    event_inj |= SVM_EVTINJ_VALID_ERR;
1200 2ed51f5b aliguori
                    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err), error_code);
1201 2ed51f5b aliguori
            }
1202 2ed51f5b aliguori
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj);
1203 2ed51f5b aliguori
    }
1204 2ed51f5b aliguori
}
1205 00ea18d1 aliguori
#endif
1206 2ed51f5b aliguori
1207 eaa728ee bellard
/*
1208 eaa728ee bellard
 * Begin execution of an interruption. is_int is TRUE if coming from
1209 eaa728ee bellard
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1210 eaa728ee bellard
 * instruction. It is only relevant if is_int is TRUE.
1211 eaa728ee bellard
 */
1212 eaa728ee bellard
void do_interrupt(int intno, int is_int, int error_code,
1213 eaa728ee bellard
                  target_ulong next_eip, int is_hw)
1214 eaa728ee bellard
{
1215 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
1216 eaa728ee bellard
        if ((env->cr[0] & CR0_PE_MASK)) {
1217 eaa728ee bellard
            static int count;
1218 93fcfe39 aliguori
            qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1219 eaa728ee bellard
                    count, intno, error_code, is_int,
1220 eaa728ee bellard
                    env->hflags & HF_CPL_MASK,
1221 eaa728ee bellard
                    env->segs[R_CS].selector, EIP,
1222 eaa728ee bellard
                    (int)env->segs[R_CS].base + EIP,
1223 eaa728ee bellard
                    env->segs[R_SS].selector, ESP);
1224 eaa728ee bellard
            if (intno == 0x0e) {
1225 93fcfe39 aliguori
                qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
1226 eaa728ee bellard
            } else {
1227 93fcfe39 aliguori
                qemu_log(" EAX=" TARGET_FMT_lx, EAX);
1228 eaa728ee bellard
            }
1229 93fcfe39 aliguori
            qemu_log("\n");
1230 93fcfe39 aliguori
            log_cpu_state(env, X86_DUMP_CCOP);
1231 eaa728ee bellard
#if 0
1232 eaa728ee bellard
            {
1233 eaa728ee bellard
                int i;
1234 9bd5494e Adam Lackorzynski
                target_ulong ptr;
1235 93fcfe39 aliguori
                qemu_log("       code=");
1236 eaa728ee bellard
                ptr = env->segs[R_CS].base + env->eip;
1237 eaa728ee bellard
                for(i = 0; i < 16; i++) {
1238 93fcfe39 aliguori
                    qemu_log(" %02x", ldub(ptr + i));
1239 eaa728ee bellard
                }
1240 93fcfe39 aliguori
                qemu_log("\n");
1241 eaa728ee bellard
            }
1242 eaa728ee bellard
#endif
1243 eaa728ee bellard
            count++;
1244 eaa728ee bellard
        }
1245 eaa728ee bellard
    }
1246 eaa728ee bellard
    if (env->cr[0] & CR0_PE_MASK) {
1247 00ea18d1 aliguori
#if !defined(CONFIG_USER_ONLY)
1248 2ed51f5b aliguori
        if (env->hflags & HF_SVMI_MASK)
1249 2ed51f5b aliguori
            handle_even_inj(intno, is_int, error_code, is_hw, 0);
1250 00ea18d1 aliguori
#endif
1251 eb38c52c blueswir1
#ifdef TARGET_X86_64
1252 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
1253 eaa728ee bellard
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1254 eaa728ee bellard
        } else
1255 eaa728ee bellard
#endif
1256 eaa728ee bellard
        {
1257 eaa728ee bellard
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1258 eaa728ee bellard
        }
1259 eaa728ee bellard
    } else {
1260 00ea18d1 aliguori
#if !defined(CONFIG_USER_ONLY)
1261 2ed51f5b aliguori
        if (env->hflags & HF_SVMI_MASK)
1262 2ed51f5b aliguori
            handle_even_inj(intno, is_int, error_code, is_hw, 1);
1263 00ea18d1 aliguori
#endif
1264 eaa728ee bellard
        do_interrupt_real(intno, is_int, error_code, next_eip);
1265 eaa728ee bellard
    }
1266 2ed51f5b aliguori
1267 00ea18d1 aliguori
#if !defined(CONFIG_USER_ONLY)
1268 2ed51f5b aliguori
    if (env->hflags & HF_SVMI_MASK) {
1269 2ed51f5b aliguori
            uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
1270 2ed51f5b aliguori
            stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
1271 2ed51f5b aliguori
    }
1272 00ea18d1 aliguori
#endif
1273 eaa728ee bellard
}
1274 eaa728ee bellard
1275 f55761a0 aliguori
/* This should come from sysemu.h - if we could include it here... */
1276 f55761a0 aliguori
void qemu_system_reset_request(void);
1277 f55761a0 aliguori
1278 eaa728ee bellard
/*
1279 eaa728ee bellard
 * Check nested exceptions and change to double or triple fault if
1280 eaa728ee bellard
 * needed. It should only be called, if this is not an interrupt.
1281 eaa728ee bellard
 * Returns the new exception number.
1282 eaa728ee bellard
 */
1283 eaa728ee bellard
static int check_exception(int intno, int *error_code)
1284 eaa728ee bellard
{
1285 eaa728ee bellard
    int first_contributory = env->old_exception == 0 ||
1286 eaa728ee bellard
                              (env->old_exception >= 10 &&
1287 eaa728ee bellard
                               env->old_exception <= 13);
1288 eaa728ee bellard
    int second_contributory = intno == 0 ||
1289 eaa728ee bellard
                               (intno >= 10 && intno <= 13);
1290 eaa728ee bellard
1291 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
1292 eaa728ee bellard
                env->old_exception, intno);
1293 eaa728ee bellard
1294 f55761a0 aliguori
#if !defined(CONFIG_USER_ONLY)
1295 f55761a0 aliguori
    if (env->old_exception == EXCP08_DBLE) {
1296 f55761a0 aliguori
        if (env->hflags & HF_SVMI_MASK)
1297 f55761a0 aliguori
            helper_vmexit(SVM_EXIT_SHUTDOWN, 0); /* does not return */
1298 f55761a0 aliguori
1299 680c3069 aliguori
        qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1300 f55761a0 aliguori
1301 f55761a0 aliguori
        qemu_system_reset_request();
1302 f55761a0 aliguori
        return EXCP_HLT;
1303 f55761a0 aliguori
    }
1304 f55761a0 aliguori
#endif
1305 eaa728ee bellard
1306 eaa728ee bellard
    if ((first_contributory && second_contributory)
1307 eaa728ee bellard
        || (env->old_exception == EXCP0E_PAGE &&
1308 eaa728ee bellard
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1309 eaa728ee bellard
        intno = EXCP08_DBLE;
1310 eaa728ee bellard
        *error_code = 0;
1311 eaa728ee bellard
    }
1312 eaa728ee bellard
1313 eaa728ee bellard
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1314 eaa728ee bellard
        (intno == EXCP08_DBLE))
1315 eaa728ee bellard
        env->old_exception = intno;
1316 eaa728ee bellard
1317 eaa728ee bellard
    return intno;
1318 eaa728ee bellard
}
1319 eaa728ee bellard
1320 eaa728ee bellard
/*
1321 eaa728ee bellard
 * Signal an interruption. It is executed in the main CPU loop.
1322 eaa728ee bellard
 * is_int is TRUE if coming from the int instruction. next_eip is the
1323 eaa728ee bellard
 * EIP value AFTER the interrupt instruction. It is only relevant if
1324 eaa728ee bellard
 * is_int is TRUE.
1325 eaa728ee bellard
 */
1326 a5e50b26 malc
static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
1327 a5e50b26 malc
                                          int next_eip_addend)
1328 eaa728ee bellard
{
1329 eaa728ee bellard
    if (!is_int) {
1330 eaa728ee bellard
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1331 eaa728ee bellard
        intno = check_exception(intno, &error_code);
1332 872929aa bellard
    } else {
1333 872929aa bellard
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1334 eaa728ee bellard
    }
1335 eaa728ee bellard
1336 eaa728ee bellard
    env->exception_index = intno;
1337 eaa728ee bellard
    env->error_code = error_code;
1338 eaa728ee bellard
    env->exception_is_int = is_int;
1339 eaa728ee bellard
    env->exception_next_eip = env->eip + next_eip_addend;
1340 eaa728ee bellard
    cpu_loop_exit();
1341 eaa728ee bellard
}
1342 eaa728ee bellard
1343 eaa728ee bellard
/* shortcuts to generate exceptions */
1344 eaa728ee bellard
1345 d9957a8b blueswir1
void raise_exception_err(int exception_index, int error_code)
1346 eaa728ee bellard
{
1347 eaa728ee bellard
    raise_interrupt(exception_index, 0, error_code, 0);
1348 eaa728ee bellard
}
1349 eaa728ee bellard
1350 eaa728ee bellard
void raise_exception(int exception_index)
1351 eaa728ee bellard
{
1352 eaa728ee bellard
    raise_interrupt(exception_index, 0, 0, 0);
1353 eaa728ee bellard
}
1354 eaa728ee bellard
1355 63a54736 Jason Wessel
void raise_exception_env(int exception_index, CPUState *nenv)
1356 63a54736 Jason Wessel
{
1357 63a54736 Jason Wessel
    env = nenv;
1358 63a54736 Jason Wessel
    raise_exception(exception_index);
1359 63a54736 Jason Wessel
}
1360 eaa728ee bellard
/* SMM support */
1361 eaa728ee bellard
1362 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
1363 eaa728ee bellard
1364 eaa728ee bellard
void do_smm_enter(void)
1365 eaa728ee bellard
{
1366 eaa728ee bellard
}
1367 eaa728ee bellard
1368 eaa728ee bellard
void helper_rsm(void)
1369 eaa728ee bellard
{
1370 eaa728ee bellard
}
1371 eaa728ee bellard
1372 eaa728ee bellard
#else
1373 eaa728ee bellard
1374 eaa728ee bellard
#ifdef TARGET_X86_64
1375 eaa728ee bellard
#define SMM_REVISION_ID 0x00020064
1376 eaa728ee bellard
#else
1377 eaa728ee bellard
#define SMM_REVISION_ID 0x00020000
1378 eaa728ee bellard
#endif
1379 eaa728ee bellard
1380 eaa728ee bellard
void do_smm_enter(void)
1381 eaa728ee bellard
{
1382 eaa728ee bellard
    target_ulong sm_state;
1383 eaa728ee bellard
    SegmentCache *dt;
1384 eaa728ee bellard
    int i, offset;
1385 eaa728ee bellard
1386 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
1387 93fcfe39 aliguori
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1388 eaa728ee bellard
1389 eaa728ee bellard
    env->hflags |= HF_SMM_MASK;
1390 eaa728ee bellard
    cpu_smm_update(env);
1391 eaa728ee bellard
1392 eaa728ee bellard
    sm_state = env->smbase + 0x8000;
1393 eaa728ee bellard
1394 eaa728ee bellard
#ifdef TARGET_X86_64
1395 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1396 eaa728ee bellard
        dt = &env->segs[i];
1397 eaa728ee bellard
        offset = 0x7e00 + i * 16;
1398 eaa728ee bellard
        stw_phys(sm_state + offset, dt->selector);
1399 eaa728ee bellard
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1400 eaa728ee bellard
        stl_phys(sm_state + offset + 4, dt->limit);
1401 eaa728ee bellard
        stq_phys(sm_state + offset + 8, dt->base);
1402 eaa728ee bellard
    }
1403 eaa728ee bellard
1404 eaa728ee bellard
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1405 eaa728ee bellard
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1406 eaa728ee bellard
1407 eaa728ee bellard
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1408 eaa728ee bellard
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1409 eaa728ee bellard
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1410 eaa728ee bellard
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1411 eaa728ee bellard
1412 eaa728ee bellard
    stq_phys(sm_state + 0x7e88, env->idt.base);
1413 eaa728ee bellard
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1414 eaa728ee bellard
1415 eaa728ee bellard
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1416 eaa728ee bellard
    stq_phys(sm_state + 0x7e98, env->tr.base);
1417 eaa728ee bellard
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1418 eaa728ee bellard
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1419 eaa728ee bellard
1420 eaa728ee bellard
    stq_phys(sm_state + 0x7ed0, env->efer);
1421 eaa728ee bellard
1422 eaa728ee bellard
    stq_phys(sm_state + 0x7ff8, EAX);
1423 eaa728ee bellard
    stq_phys(sm_state + 0x7ff0, ECX);
1424 eaa728ee bellard
    stq_phys(sm_state + 0x7fe8, EDX);
1425 eaa728ee bellard
    stq_phys(sm_state + 0x7fe0, EBX);
1426 eaa728ee bellard
    stq_phys(sm_state + 0x7fd8, ESP);
1427 eaa728ee bellard
    stq_phys(sm_state + 0x7fd0, EBP);
1428 eaa728ee bellard
    stq_phys(sm_state + 0x7fc8, ESI);
1429 eaa728ee bellard
    stq_phys(sm_state + 0x7fc0, EDI);
1430 eaa728ee bellard
    for(i = 8; i < 16; i++)
1431 eaa728ee bellard
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1432 eaa728ee bellard
    stq_phys(sm_state + 0x7f78, env->eip);
1433 eaa728ee bellard
    stl_phys(sm_state + 0x7f70, compute_eflags());
1434 eaa728ee bellard
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1435 eaa728ee bellard
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1436 eaa728ee bellard
1437 eaa728ee bellard
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1438 eaa728ee bellard
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1439 eaa728ee bellard
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1440 eaa728ee bellard
1441 eaa728ee bellard
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1442 eaa728ee bellard
    stl_phys(sm_state + 0x7f00, env->smbase);
1443 eaa728ee bellard
#else
1444 eaa728ee bellard
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1445 eaa728ee bellard
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1446 eaa728ee bellard
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1447 eaa728ee bellard
    stl_phys(sm_state + 0x7ff0, env->eip);
1448 eaa728ee bellard
    stl_phys(sm_state + 0x7fec, EDI);
1449 eaa728ee bellard
    stl_phys(sm_state + 0x7fe8, ESI);
1450 eaa728ee bellard
    stl_phys(sm_state + 0x7fe4, EBP);
1451 eaa728ee bellard
    stl_phys(sm_state + 0x7fe0, ESP);
1452 eaa728ee bellard
    stl_phys(sm_state + 0x7fdc, EBX);
1453 eaa728ee bellard
    stl_phys(sm_state + 0x7fd8, EDX);
1454 eaa728ee bellard
    stl_phys(sm_state + 0x7fd4, ECX);
1455 eaa728ee bellard
    stl_phys(sm_state + 0x7fd0, EAX);
1456 eaa728ee bellard
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1457 eaa728ee bellard
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1458 eaa728ee bellard
1459 eaa728ee bellard
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1460 eaa728ee bellard
    stl_phys(sm_state + 0x7f64, env->tr.base);
1461 eaa728ee bellard
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1462 eaa728ee bellard
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1463 eaa728ee bellard
1464 eaa728ee bellard
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1465 eaa728ee bellard
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1466 eaa728ee bellard
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1467 eaa728ee bellard
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1468 eaa728ee bellard
1469 eaa728ee bellard
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1470 eaa728ee bellard
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1471 eaa728ee bellard
1472 eaa728ee bellard
    stl_phys(sm_state + 0x7f58, env->idt.base);
1473 eaa728ee bellard
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1474 eaa728ee bellard
1475 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1476 eaa728ee bellard
        dt = &env->segs[i];
1477 eaa728ee bellard
        if (i < 3)
1478 eaa728ee bellard
            offset = 0x7f84 + i * 12;
1479 eaa728ee bellard
        else
1480 eaa728ee bellard
            offset = 0x7f2c + (i - 3) * 12;
1481 eaa728ee bellard
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1482 eaa728ee bellard
        stl_phys(sm_state + offset + 8, dt->base);
1483 eaa728ee bellard
        stl_phys(sm_state + offset + 4, dt->limit);
1484 eaa728ee bellard
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1485 eaa728ee bellard
    }
1486 eaa728ee bellard
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1487 eaa728ee bellard
1488 eaa728ee bellard
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1489 eaa728ee bellard
    stl_phys(sm_state + 0x7ef8, env->smbase);
1490 eaa728ee bellard
#endif
1491 eaa728ee bellard
    /* init SMM cpu state */
1492 eaa728ee bellard
1493 eaa728ee bellard
#ifdef TARGET_X86_64
1494 5efc27bb bellard
    cpu_load_efer(env, 0);
1495 eaa728ee bellard
#endif
1496 eaa728ee bellard
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1497 eaa728ee bellard
    env->eip = 0x00008000;
1498 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1499 eaa728ee bellard
                           0xffffffff, 0);
1500 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1501 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1502 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1503 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1504 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1505 eaa728ee bellard
1506 eaa728ee bellard
    cpu_x86_update_cr0(env,
1507 eaa728ee bellard
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1508 eaa728ee bellard
    cpu_x86_update_cr4(env, 0);
1509 eaa728ee bellard
    env->dr[7] = 0x00000400;
1510 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
1511 eaa728ee bellard
}
1512 eaa728ee bellard
1513 eaa728ee bellard
void helper_rsm(void)
1514 eaa728ee bellard
{
1515 eaa728ee bellard
    target_ulong sm_state;
1516 eaa728ee bellard
    int i, offset;
1517 eaa728ee bellard
    uint32_t val;
1518 eaa728ee bellard
1519 eaa728ee bellard
    sm_state = env->smbase + 0x8000;
1520 eaa728ee bellard
#ifdef TARGET_X86_64
1521 5efc27bb bellard
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1522 eaa728ee bellard
1523 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1524 eaa728ee bellard
        offset = 0x7e00 + i * 16;
1525 eaa728ee bellard
        cpu_x86_load_seg_cache(env, i,
1526 eaa728ee bellard
                               lduw_phys(sm_state + offset),
1527 eaa728ee bellard
                               ldq_phys(sm_state + offset + 8),
1528 eaa728ee bellard
                               ldl_phys(sm_state + offset + 4),
1529 eaa728ee bellard
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1530 eaa728ee bellard
    }
1531 eaa728ee bellard
1532 eaa728ee bellard
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1533 eaa728ee bellard
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1534 eaa728ee bellard
1535 eaa728ee bellard
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1536 eaa728ee bellard
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1537 eaa728ee bellard
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1538 eaa728ee bellard
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1539 eaa728ee bellard
1540 eaa728ee bellard
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1541 eaa728ee bellard
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1542 eaa728ee bellard
1543 eaa728ee bellard
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1544 eaa728ee bellard
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1545 eaa728ee bellard
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1546 eaa728ee bellard
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1547 eaa728ee bellard
1548 eaa728ee bellard
    EAX = ldq_phys(sm_state + 0x7ff8);
1549 eaa728ee bellard
    ECX = ldq_phys(sm_state + 0x7ff0);
1550 eaa728ee bellard
    EDX = ldq_phys(sm_state + 0x7fe8);
1551 eaa728ee bellard
    EBX = ldq_phys(sm_state + 0x7fe0);
1552 eaa728ee bellard
    ESP = ldq_phys(sm_state + 0x7fd8);
1553 eaa728ee bellard
    EBP = ldq_phys(sm_state + 0x7fd0);
1554 eaa728ee bellard
    ESI = ldq_phys(sm_state + 0x7fc8);
1555 eaa728ee bellard
    EDI = ldq_phys(sm_state + 0x7fc0);
1556 eaa728ee bellard
    for(i = 8; i < 16; i++)
1557 eaa728ee bellard
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1558 eaa728ee bellard
    env->eip = ldq_phys(sm_state + 0x7f78);
1559 eaa728ee bellard
    load_eflags(ldl_phys(sm_state + 0x7f70),
1560 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1561 eaa728ee bellard
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1562 eaa728ee bellard
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1563 eaa728ee bellard
1564 eaa728ee bellard
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1565 eaa728ee bellard
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1566 eaa728ee bellard
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1567 eaa728ee bellard
1568 eaa728ee bellard
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1569 eaa728ee bellard
    if (val & 0x20000) {
1570 eaa728ee bellard
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1571 eaa728ee bellard
    }
1572 eaa728ee bellard
#else
1573 eaa728ee bellard
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1574 eaa728ee bellard
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1575 eaa728ee bellard
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1576 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1577 eaa728ee bellard
    env->eip = ldl_phys(sm_state + 0x7ff0);
1578 eaa728ee bellard
    EDI = ldl_phys(sm_state + 0x7fec);
1579 eaa728ee bellard
    ESI = ldl_phys(sm_state + 0x7fe8);
1580 eaa728ee bellard
    EBP = ldl_phys(sm_state + 0x7fe4);
1581 eaa728ee bellard
    ESP = ldl_phys(sm_state + 0x7fe0);
1582 eaa728ee bellard
    EBX = ldl_phys(sm_state + 0x7fdc);
1583 eaa728ee bellard
    EDX = ldl_phys(sm_state + 0x7fd8);
1584 eaa728ee bellard
    ECX = ldl_phys(sm_state + 0x7fd4);
1585 eaa728ee bellard
    EAX = ldl_phys(sm_state + 0x7fd0);
1586 eaa728ee bellard
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1587 eaa728ee bellard
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1588 eaa728ee bellard
1589 eaa728ee bellard
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1590 eaa728ee bellard
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1591 eaa728ee bellard
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1592 eaa728ee bellard
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1593 eaa728ee bellard
1594 eaa728ee bellard
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1595 eaa728ee bellard
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1596 eaa728ee bellard
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1597 eaa728ee bellard
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1598 eaa728ee bellard
1599 eaa728ee bellard
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1600 eaa728ee bellard
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1601 eaa728ee bellard
1602 eaa728ee bellard
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1603 eaa728ee bellard
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1604 eaa728ee bellard
1605 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1606 eaa728ee bellard
        if (i < 3)
1607 eaa728ee bellard
            offset = 0x7f84 + i * 12;
1608 eaa728ee bellard
        else
1609 eaa728ee bellard
            offset = 0x7f2c + (i - 3) * 12;
1610 eaa728ee bellard
        cpu_x86_load_seg_cache(env, i,
1611 eaa728ee bellard
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1612 eaa728ee bellard
                               ldl_phys(sm_state + offset + 8),
1613 eaa728ee bellard
                               ldl_phys(sm_state + offset + 4),
1614 eaa728ee bellard
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1615 eaa728ee bellard
    }
1616 eaa728ee bellard
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1617 eaa728ee bellard
1618 eaa728ee bellard
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1619 eaa728ee bellard
    if (val & 0x20000) {
1620 eaa728ee bellard
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1621 eaa728ee bellard
    }
1622 eaa728ee bellard
#endif
1623 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
1624 eaa728ee bellard
    env->hflags &= ~HF_SMM_MASK;
1625 eaa728ee bellard
    cpu_smm_update(env);
1626 eaa728ee bellard
1627 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
1628 93fcfe39 aliguori
    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
1629 eaa728ee bellard
}
1630 eaa728ee bellard
1631 eaa728ee bellard
#endif /* !CONFIG_USER_ONLY */
1632 eaa728ee bellard
1633 eaa728ee bellard
1634 eaa728ee bellard
/* division, flags are undefined */
1635 eaa728ee bellard
1636 eaa728ee bellard
void helper_divb_AL(target_ulong t0)
1637 eaa728ee bellard
{
1638 eaa728ee bellard
    unsigned int num, den, q, r;
1639 eaa728ee bellard
1640 eaa728ee bellard
    num = (EAX & 0xffff);
1641 eaa728ee bellard
    den = (t0 & 0xff);
1642 eaa728ee bellard
    if (den == 0) {
1643 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1644 eaa728ee bellard
    }
1645 eaa728ee bellard
    q = (num / den);
1646 eaa728ee bellard
    if (q > 0xff)
1647 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1648 eaa728ee bellard
    q &= 0xff;
1649 eaa728ee bellard
    r = (num % den) & 0xff;
1650 eaa728ee bellard
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1651 eaa728ee bellard
}
1652 eaa728ee bellard
1653 eaa728ee bellard
void helper_idivb_AL(target_ulong t0)
1654 eaa728ee bellard
{
1655 eaa728ee bellard
    int num, den, q, r;
1656 eaa728ee bellard
1657 eaa728ee bellard
    num = (int16_t)EAX;
1658 eaa728ee bellard
    den = (int8_t)t0;
1659 eaa728ee bellard
    if (den == 0) {
1660 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1661 eaa728ee bellard
    }
1662 eaa728ee bellard
    q = (num / den);
1663 eaa728ee bellard
    if (q != (int8_t)q)
1664 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1665 eaa728ee bellard
    q &= 0xff;
1666 eaa728ee bellard
    r = (num % den) & 0xff;
1667 eaa728ee bellard
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1668 eaa728ee bellard
}
1669 eaa728ee bellard
1670 eaa728ee bellard
void helper_divw_AX(target_ulong t0)
1671 eaa728ee bellard
{
1672 eaa728ee bellard
    unsigned int num, den, q, r;
1673 eaa728ee bellard
1674 eaa728ee bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1675 eaa728ee bellard
    den = (t0 & 0xffff);
1676 eaa728ee bellard
    if (den == 0) {
1677 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1678 eaa728ee bellard
    }
1679 eaa728ee bellard
    q = (num / den);
1680 eaa728ee bellard
    if (q > 0xffff)
1681 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1682 eaa728ee bellard
    q &= 0xffff;
1683 eaa728ee bellard
    r = (num % den) & 0xffff;
1684 eaa728ee bellard
    EAX = (EAX & ~0xffff) | q;
1685 eaa728ee bellard
    EDX = (EDX & ~0xffff) | r;
1686 eaa728ee bellard
}
1687 eaa728ee bellard
1688 eaa728ee bellard
void helper_idivw_AX(target_ulong t0)
1689 eaa728ee bellard
{
1690 eaa728ee bellard
    int num, den, q, r;
1691 eaa728ee bellard
1692 eaa728ee bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1693 eaa728ee bellard
    den = (int16_t)t0;
1694 eaa728ee bellard
    if (den == 0) {
1695 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1696 eaa728ee bellard
    }
1697 eaa728ee bellard
    q = (num / den);
1698 eaa728ee bellard
    if (q != (int16_t)q)
1699 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1700 eaa728ee bellard
    q &= 0xffff;
1701 eaa728ee bellard
    r = (num % den) & 0xffff;
1702 eaa728ee bellard
    EAX = (EAX & ~0xffff) | q;
1703 eaa728ee bellard
    EDX = (EDX & ~0xffff) | r;
1704 eaa728ee bellard
}
1705 eaa728ee bellard
1706 eaa728ee bellard
void helper_divl_EAX(target_ulong t0)
1707 eaa728ee bellard
{
1708 eaa728ee bellard
    unsigned int den, r;
1709 eaa728ee bellard
    uint64_t num, q;
1710 eaa728ee bellard
1711 eaa728ee bellard
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1712 eaa728ee bellard
    den = t0;
1713 eaa728ee bellard
    if (den == 0) {
1714 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1715 eaa728ee bellard
    }
1716 eaa728ee bellard
    q = (num / den);
1717 eaa728ee bellard
    r = (num % den);
1718 eaa728ee bellard
    if (q > 0xffffffff)
1719 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1720 eaa728ee bellard
    EAX = (uint32_t)q;
1721 eaa728ee bellard
    EDX = (uint32_t)r;
1722 eaa728ee bellard
}
1723 eaa728ee bellard
1724 eaa728ee bellard
void helper_idivl_EAX(target_ulong t0)
1725 eaa728ee bellard
{
1726 eaa728ee bellard
    int den, r;
1727 eaa728ee bellard
    int64_t num, q;
1728 eaa728ee bellard
1729 eaa728ee bellard
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1730 eaa728ee bellard
    den = t0;
1731 eaa728ee bellard
    if (den == 0) {
1732 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1733 eaa728ee bellard
    }
1734 eaa728ee bellard
    q = (num / den);
1735 eaa728ee bellard
    r = (num % den);
1736 eaa728ee bellard
    if (q != (int32_t)q)
1737 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1738 eaa728ee bellard
    EAX = (uint32_t)q;
1739 eaa728ee bellard
    EDX = (uint32_t)r;
1740 eaa728ee bellard
}
1741 eaa728ee bellard
1742 eaa728ee bellard
/* bcd */
1743 eaa728ee bellard
1744 eaa728ee bellard
/* XXX: exception */
1745 eaa728ee bellard
void helper_aam(int base)
1746 eaa728ee bellard
{
1747 eaa728ee bellard
    int al, ah;
1748 eaa728ee bellard
    al = EAX & 0xff;
1749 eaa728ee bellard
    ah = al / base;
1750 eaa728ee bellard
    al = al % base;
1751 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1752 eaa728ee bellard
    CC_DST = al;
1753 eaa728ee bellard
}
1754 eaa728ee bellard
1755 eaa728ee bellard
void helper_aad(int base)
1756 eaa728ee bellard
{
1757 eaa728ee bellard
    int al, ah;
1758 eaa728ee bellard
    al = EAX & 0xff;
1759 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1760 eaa728ee bellard
    al = ((ah * base) + al) & 0xff;
1761 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al;
1762 eaa728ee bellard
    CC_DST = al;
1763 eaa728ee bellard
}
1764 eaa728ee bellard
1765 eaa728ee bellard
void helper_aaa(void)
1766 eaa728ee bellard
{
1767 eaa728ee bellard
    int icarry;
1768 eaa728ee bellard
    int al, ah, af;
1769 eaa728ee bellard
    int eflags;
1770 eaa728ee bellard
1771 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1772 eaa728ee bellard
    af = eflags & CC_A;
1773 eaa728ee bellard
    al = EAX & 0xff;
1774 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1775 eaa728ee bellard
1776 eaa728ee bellard
    icarry = (al > 0xf9);
1777 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1778 eaa728ee bellard
        al = (al + 6) & 0x0f;
1779 eaa728ee bellard
        ah = (ah + 1 + icarry) & 0xff;
1780 eaa728ee bellard
        eflags |= CC_C | CC_A;
1781 eaa728ee bellard
    } else {
1782 eaa728ee bellard
        eflags &= ~(CC_C | CC_A);
1783 eaa728ee bellard
        al &= 0x0f;
1784 eaa728ee bellard
    }
1785 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1786 eaa728ee bellard
    CC_SRC = eflags;
1787 eaa728ee bellard
}
1788 eaa728ee bellard
1789 eaa728ee bellard
void helper_aas(void)
1790 eaa728ee bellard
{
1791 eaa728ee bellard
    int icarry;
1792 eaa728ee bellard
    int al, ah, af;
1793 eaa728ee bellard
    int eflags;
1794 eaa728ee bellard
1795 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1796 eaa728ee bellard
    af = eflags & CC_A;
1797 eaa728ee bellard
    al = EAX & 0xff;
1798 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1799 eaa728ee bellard
1800 eaa728ee bellard
    icarry = (al < 6);
1801 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1802 eaa728ee bellard
        al = (al - 6) & 0x0f;
1803 eaa728ee bellard
        ah = (ah - 1 - icarry) & 0xff;
1804 eaa728ee bellard
        eflags |= CC_C | CC_A;
1805 eaa728ee bellard
    } else {
1806 eaa728ee bellard
        eflags &= ~(CC_C | CC_A);
1807 eaa728ee bellard
        al &= 0x0f;
1808 eaa728ee bellard
    }
1809 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1810 eaa728ee bellard
    CC_SRC = eflags;
1811 eaa728ee bellard
}
1812 eaa728ee bellard
1813 eaa728ee bellard
void helper_daa(void)
1814 eaa728ee bellard
{
1815 eaa728ee bellard
    int al, af, cf;
1816 eaa728ee bellard
    int eflags;
1817 eaa728ee bellard
1818 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1819 eaa728ee bellard
    cf = eflags & CC_C;
1820 eaa728ee bellard
    af = eflags & CC_A;
1821 eaa728ee bellard
    al = EAX & 0xff;
1822 eaa728ee bellard
1823 eaa728ee bellard
    eflags = 0;
1824 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1825 eaa728ee bellard
        al = (al + 6) & 0xff;
1826 eaa728ee bellard
        eflags |= CC_A;
1827 eaa728ee bellard
    }
1828 eaa728ee bellard
    if ((al > 0x9f) || cf) {
1829 eaa728ee bellard
        al = (al + 0x60) & 0xff;
1830 eaa728ee bellard
        eflags |= CC_C;
1831 eaa728ee bellard
    }
1832 eaa728ee bellard
    EAX = (EAX & ~0xff) | al;
1833 eaa728ee bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1834 eaa728ee bellard
    eflags |= (al == 0) << 6; /* zf */
1835 eaa728ee bellard
    eflags |= parity_table[al]; /* pf */
1836 eaa728ee bellard
    eflags |= (al & 0x80); /* sf */
1837 eaa728ee bellard
    CC_SRC = eflags;
1838 eaa728ee bellard
}
1839 eaa728ee bellard
1840 eaa728ee bellard
void helper_das(void)
1841 eaa728ee bellard
{
1842 eaa728ee bellard
    int al, al1, af, cf;
1843 eaa728ee bellard
    int eflags;
1844 eaa728ee bellard
1845 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1846 eaa728ee bellard
    cf = eflags & CC_C;
1847 eaa728ee bellard
    af = eflags & CC_A;
1848 eaa728ee bellard
    al = EAX & 0xff;
1849 eaa728ee bellard
1850 eaa728ee bellard
    eflags = 0;
1851 eaa728ee bellard
    al1 = al;
1852 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1853 eaa728ee bellard
        eflags |= CC_A;
1854 eaa728ee bellard
        if (al < 6 || cf)
1855 eaa728ee bellard
            eflags |= CC_C;
1856 eaa728ee bellard
        al = (al - 6) & 0xff;
1857 eaa728ee bellard
    }
1858 eaa728ee bellard
    if ((al1 > 0x99) || cf) {
1859 eaa728ee bellard
        al = (al - 0x60) & 0xff;
1860 eaa728ee bellard
        eflags |= CC_C;
1861 eaa728ee bellard
    }
1862 eaa728ee bellard
    EAX = (EAX & ~0xff) | al;
1863 eaa728ee bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1864 eaa728ee bellard
    eflags |= (al == 0) << 6; /* zf */
1865 eaa728ee bellard
    eflags |= parity_table[al]; /* pf */
1866 eaa728ee bellard
    eflags |= (al & 0x80); /* sf */
1867 eaa728ee bellard
    CC_SRC = eflags;
1868 eaa728ee bellard
}
1869 eaa728ee bellard
1870 eaa728ee bellard
void helper_into(int next_eip_addend)
1871 eaa728ee bellard
{
1872 eaa728ee bellard
    int eflags;
1873 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1874 eaa728ee bellard
    if (eflags & CC_O) {
1875 eaa728ee bellard
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1876 eaa728ee bellard
    }
1877 eaa728ee bellard
}
1878 eaa728ee bellard
1879 eaa728ee bellard
void helper_cmpxchg8b(target_ulong a0)
1880 eaa728ee bellard
{
1881 eaa728ee bellard
    uint64_t d;
1882 eaa728ee bellard
    int eflags;
1883 eaa728ee bellard
1884 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1885 eaa728ee bellard
    d = ldq(a0);
1886 eaa728ee bellard
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1887 eaa728ee bellard
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1888 eaa728ee bellard
        eflags |= CC_Z;
1889 eaa728ee bellard
    } else {
1890 278ed7c3 bellard
        /* always do the store */
1891 278ed7c3 bellard
        stq(a0, d); 
1892 eaa728ee bellard
        EDX = (uint32_t)(d >> 32);
1893 eaa728ee bellard
        EAX = (uint32_t)d;
1894 eaa728ee bellard
        eflags &= ~CC_Z;
1895 eaa728ee bellard
    }
1896 eaa728ee bellard
    CC_SRC = eflags;
1897 eaa728ee bellard
}
1898 eaa728ee bellard
1899 eaa728ee bellard
#ifdef TARGET_X86_64
1900 eaa728ee bellard
void helper_cmpxchg16b(target_ulong a0)
1901 eaa728ee bellard
{
1902 eaa728ee bellard
    uint64_t d0, d1;
1903 eaa728ee bellard
    int eflags;
1904 eaa728ee bellard
1905 278ed7c3 bellard
    if ((a0 & 0xf) != 0)
1906 278ed7c3 bellard
        raise_exception(EXCP0D_GPF);
1907 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1908 eaa728ee bellard
    d0 = ldq(a0);
1909 eaa728ee bellard
    d1 = ldq(a0 + 8);
1910 eaa728ee bellard
    if (d0 == EAX && d1 == EDX) {
1911 eaa728ee bellard
        stq(a0, EBX);
1912 eaa728ee bellard
        stq(a0 + 8, ECX);
1913 eaa728ee bellard
        eflags |= CC_Z;
1914 eaa728ee bellard
    } else {
1915 278ed7c3 bellard
        /* always do the store */
1916 278ed7c3 bellard
        stq(a0, d0); 
1917 278ed7c3 bellard
        stq(a0 + 8, d1); 
1918 eaa728ee bellard
        EDX = d1;
1919 eaa728ee bellard
        EAX = d0;
1920 eaa728ee bellard
        eflags &= ~CC_Z;
1921 eaa728ee bellard
    }
1922 eaa728ee bellard
    CC_SRC = eflags;
1923 eaa728ee bellard
}
1924 eaa728ee bellard
#endif
1925 eaa728ee bellard
1926 eaa728ee bellard
void helper_single_step(void)
1927 eaa728ee bellard
{
1928 01df040b aliguori
#ifndef CONFIG_USER_ONLY
1929 01df040b aliguori
    check_hw_breakpoints(env, 1);
1930 01df040b aliguori
    env->dr[6] |= DR6_BS;
1931 01df040b aliguori
#endif
1932 01df040b aliguori
    raise_exception(EXCP01_DB);
1933 eaa728ee bellard
}
1934 eaa728ee bellard
1935 eaa728ee bellard
void helper_cpuid(void)
1936 eaa728ee bellard
{
1937 6fd805e1 aliguori
    uint32_t eax, ebx, ecx, edx;
1938 eaa728ee bellard
1939 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1940 e737b32a balrog
1941 e00b6f80 aliguori
    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
1942 6fd805e1 aliguori
    EAX = eax;
1943 6fd805e1 aliguori
    EBX = ebx;
1944 6fd805e1 aliguori
    ECX = ecx;
1945 6fd805e1 aliguori
    EDX = edx;
1946 eaa728ee bellard
}
1947 eaa728ee bellard
1948 eaa728ee bellard
void helper_enter_level(int level, int data32, target_ulong t1)
1949 eaa728ee bellard
{
1950 eaa728ee bellard
    target_ulong ssp;
1951 eaa728ee bellard
    uint32_t esp_mask, esp, ebp;
1952 eaa728ee bellard
1953 eaa728ee bellard
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1954 eaa728ee bellard
    ssp = env->segs[R_SS].base;
1955 eaa728ee bellard
    ebp = EBP;
1956 eaa728ee bellard
    esp = ESP;
1957 eaa728ee bellard
    if (data32) {
1958 eaa728ee bellard
        /* 32 bit */
1959 eaa728ee bellard
        esp -= 4;
1960 eaa728ee bellard
        while (--level) {
1961 eaa728ee bellard
            esp -= 4;
1962 eaa728ee bellard
            ebp -= 4;
1963 eaa728ee bellard
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1964 eaa728ee bellard
        }
1965 eaa728ee bellard
        esp -= 4;
1966 eaa728ee bellard
        stl(ssp + (esp & esp_mask), t1);
1967 eaa728ee bellard
    } else {
1968 eaa728ee bellard
        /* 16 bit */
1969 eaa728ee bellard
        esp -= 2;
1970 eaa728ee bellard
        while (--level) {
1971 eaa728ee bellard
            esp -= 2;
1972 eaa728ee bellard
            ebp -= 2;
1973 eaa728ee bellard
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1974 eaa728ee bellard
        }
1975 eaa728ee bellard
        esp -= 2;
1976 eaa728ee bellard
        stw(ssp + (esp & esp_mask), t1);
1977 eaa728ee bellard
    }
1978 eaa728ee bellard
}
1979 eaa728ee bellard
1980 eaa728ee bellard
#ifdef TARGET_X86_64
1981 eaa728ee bellard
void helper_enter64_level(int level, int data64, target_ulong t1)
1982 eaa728ee bellard
{
1983 eaa728ee bellard
    target_ulong esp, ebp;
1984 eaa728ee bellard
    ebp = EBP;
1985 eaa728ee bellard
    esp = ESP;
1986 eaa728ee bellard
1987 eaa728ee bellard
    if (data64) {
1988 eaa728ee bellard
        /* 64 bit */
1989 eaa728ee bellard
        esp -= 8;
1990 eaa728ee bellard
        while (--level) {
1991 eaa728ee bellard
            esp -= 8;
1992 eaa728ee bellard
            ebp -= 8;
1993 eaa728ee bellard
            stq(esp, ldq(ebp));
1994 eaa728ee bellard
        }
1995 eaa728ee bellard
        esp -= 8;
1996 eaa728ee bellard
        stq(esp, t1);
1997 eaa728ee bellard
    } else {
1998 eaa728ee bellard
        /* 16 bit */
1999 eaa728ee bellard
        esp -= 2;
2000 eaa728ee bellard
        while (--level) {
2001 eaa728ee bellard
            esp -= 2;
2002 eaa728ee bellard
            ebp -= 2;
2003 eaa728ee bellard
            stw(esp, lduw(ebp));
2004 eaa728ee bellard
        }
2005 eaa728ee bellard
        esp -= 2;
2006 eaa728ee bellard
        stw(esp, t1);
2007 eaa728ee bellard
    }
2008 eaa728ee bellard
}
2009 eaa728ee bellard
#endif
2010 eaa728ee bellard
2011 eaa728ee bellard
void helper_lldt(int selector)
2012 eaa728ee bellard
{
2013 eaa728ee bellard
    SegmentCache *dt;
2014 eaa728ee bellard
    uint32_t e1, e2;
2015 eaa728ee bellard
    int index, entry_limit;
2016 eaa728ee bellard
    target_ulong ptr;
2017 eaa728ee bellard
2018 eaa728ee bellard
    selector &= 0xffff;
2019 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2020 eaa728ee bellard
        /* XXX: NULL selector case: invalid LDT */
2021 eaa728ee bellard
        env->ldt.base = 0;
2022 eaa728ee bellard
        env->ldt.limit = 0;
2023 eaa728ee bellard
    } else {
2024 eaa728ee bellard
        if (selector & 0x4)
2025 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2026 eaa728ee bellard
        dt = &env->gdt;
2027 eaa728ee bellard
        index = selector & ~7;
2028 eaa728ee bellard
#ifdef TARGET_X86_64
2029 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK)
2030 eaa728ee bellard
            entry_limit = 15;
2031 eaa728ee bellard
        else
2032 eaa728ee bellard
#endif
2033 eaa728ee bellard
            entry_limit = 7;
2034 eaa728ee bellard
        if ((index + entry_limit) > dt->limit)
2035 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2036 eaa728ee bellard
        ptr = dt->base + index;
2037 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2038 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2039 eaa728ee bellard
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2040 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2041 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2042 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2043 eaa728ee bellard
#ifdef TARGET_X86_64
2044 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
2045 eaa728ee bellard
            uint32_t e3;
2046 eaa728ee bellard
            e3 = ldl_kernel(ptr + 8);
2047 eaa728ee bellard
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2048 eaa728ee bellard
            env->ldt.base |= (target_ulong)e3 << 32;
2049 eaa728ee bellard
        } else
2050 eaa728ee bellard
#endif
2051 eaa728ee bellard
        {
2052 eaa728ee bellard
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2053 eaa728ee bellard
        }
2054 eaa728ee bellard
    }
2055 eaa728ee bellard
    env->ldt.selector = selector;
2056 eaa728ee bellard
}
2057 eaa728ee bellard
2058 eaa728ee bellard
void helper_ltr(int selector)
2059 eaa728ee bellard
{
2060 eaa728ee bellard
    SegmentCache *dt;
2061 eaa728ee bellard
    uint32_t e1, e2;
2062 eaa728ee bellard
    int index, type, entry_limit;
2063 eaa728ee bellard
    target_ulong ptr;
2064 eaa728ee bellard
2065 eaa728ee bellard
    selector &= 0xffff;
2066 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2067 eaa728ee bellard
        /* NULL selector case: invalid TR */
2068 eaa728ee bellard
        env->tr.base = 0;
2069 eaa728ee bellard
        env->tr.limit = 0;
2070 eaa728ee bellard
        env->tr.flags = 0;
2071 eaa728ee bellard
    } else {
2072 eaa728ee bellard
        if (selector & 0x4)
2073 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2074 eaa728ee bellard
        dt = &env->gdt;
2075 eaa728ee bellard
        index = selector & ~7;
2076 eaa728ee bellard
#ifdef TARGET_X86_64
2077 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK)
2078 eaa728ee bellard
            entry_limit = 15;
2079 eaa728ee bellard
        else
2080 eaa728ee bellard
#endif
2081 eaa728ee bellard
            entry_limit = 7;
2082 eaa728ee bellard
        if ((index + entry_limit) > dt->limit)
2083 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2084 eaa728ee bellard
        ptr = dt->base + index;
2085 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2086 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2087 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2088 eaa728ee bellard
        if ((e2 & DESC_S_MASK) ||
2089 eaa728ee bellard
            (type != 1 && type != 9))
2090 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2091 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2092 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2093 eaa728ee bellard
#ifdef TARGET_X86_64
2094 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
2095 eaa728ee bellard
            uint32_t e3, e4;
2096 eaa728ee bellard
            e3 = ldl_kernel(ptr + 8);
2097 eaa728ee bellard
            e4 = ldl_kernel(ptr + 12);
2098 eaa728ee bellard
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2099 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2100 eaa728ee bellard
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2101 eaa728ee bellard
            env->tr.base |= (target_ulong)e3 << 32;
2102 eaa728ee bellard
        } else
2103 eaa728ee bellard
#endif
2104 eaa728ee bellard
        {
2105 eaa728ee bellard
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2106 eaa728ee bellard
        }
2107 eaa728ee bellard
        e2 |= DESC_TSS_BUSY_MASK;
2108 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
2109 eaa728ee bellard
    }
2110 eaa728ee bellard
    env->tr.selector = selector;
2111 eaa728ee bellard
}
2112 eaa728ee bellard
2113 eaa728ee bellard
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2114 eaa728ee bellard
void helper_load_seg(int seg_reg, int selector)
2115 eaa728ee bellard
{
2116 eaa728ee bellard
    uint32_t e1, e2;
2117 eaa728ee bellard
    int cpl, dpl, rpl;
2118 eaa728ee bellard
    SegmentCache *dt;
2119 eaa728ee bellard
    int index;
2120 eaa728ee bellard
    target_ulong ptr;
2121 eaa728ee bellard
2122 eaa728ee bellard
    selector &= 0xffff;
2123 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2124 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2125 eaa728ee bellard
        /* null selector case */
2126 eaa728ee bellard
        if (seg_reg == R_SS
2127 eaa728ee bellard
#ifdef TARGET_X86_64
2128 eaa728ee bellard
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2129 eaa728ee bellard
#endif
2130 eaa728ee bellard
            )
2131 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, 0);
2132 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2133 eaa728ee bellard
    } else {
2134 eaa728ee bellard
2135 eaa728ee bellard
        if (selector & 0x4)
2136 eaa728ee bellard
            dt = &env->ldt;
2137 eaa728ee bellard
        else
2138 eaa728ee bellard
            dt = &env->gdt;
2139 eaa728ee bellard
        index = selector & ~7;
2140 eaa728ee bellard
        if ((index + 7) > dt->limit)
2141 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2142 eaa728ee bellard
        ptr = dt->base + index;
2143 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2144 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2145 eaa728ee bellard
2146 eaa728ee bellard
        if (!(e2 & DESC_S_MASK))
2147 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2148 eaa728ee bellard
        rpl = selector & 3;
2149 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2150 eaa728ee bellard
        if (seg_reg == R_SS) {
2151 eaa728ee bellard
            /* must be writable segment */
2152 eaa728ee bellard
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2153 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2154 eaa728ee bellard
            if (rpl != cpl || dpl != cpl)
2155 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2156 eaa728ee bellard
        } else {
2157 eaa728ee bellard
            /* must be readable segment */
2158 eaa728ee bellard
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2159 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2160 eaa728ee bellard
2161 eaa728ee bellard
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2162 eaa728ee bellard
                /* if not conforming code, test rights */
2163 eaa728ee bellard
                if (dpl < cpl || dpl < rpl)
2164 eaa728ee bellard
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2165 eaa728ee bellard
            }
2166 eaa728ee bellard
        }
2167 eaa728ee bellard
2168 eaa728ee bellard
        if (!(e2 & DESC_P_MASK)) {
2169 eaa728ee bellard
            if (seg_reg == R_SS)
2170 eaa728ee bellard
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2171 eaa728ee bellard
            else
2172 eaa728ee bellard
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2173 eaa728ee bellard
        }
2174 eaa728ee bellard
2175 eaa728ee bellard
        /* set the access bit if not already set */
2176 eaa728ee bellard
        if (!(e2 & DESC_A_MASK)) {
2177 eaa728ee bellard
            e2 |= DESC_A_MASK;
2178 eaa728ee bellard
            stl_kernel(ptr + 4, e2);
2179 eaa728ee bellard
        }
2180 eaa728ee bellard
2181 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2182 eaa728ee bellard
                       get_seg_base(e1, e2),
2183 eaa728ee bellard
                       get_seg_limit(e1, e2),
2184 eaa728ee bellard
                       e2);
2185 eaa728ee bellard
#if 0
2186 93fcfe39 aliguori
        qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2187 eaa728ee bellard
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2188 eaa728ee bellard
#endif
2189 eaa728ee bellard
    }
2190 eaa728ee bellard
}
2191 eaa728ee bellard
2192 eaa728ee bellard
/* protected mode jump */
2193 eaa728ee bellard
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2194 eaa728ee bellard
                           int next_eip_addend)
2195 eaa728ee bellard
{
2196 eaa728ee bellard
    int gate_cs, type;
2197 eaa728ee bellard
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2198 eaa728ee bellard
    target_ulong next_eip;
2199 eaa728ee bellard
2200 eaa728ee bellard
    if ((new_cs & 0xfffc) == 0)
2201 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
2202 eaa728ee bellard
    if (load_segment(&e1, &e2, new_cs) != 0)
2203 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2204 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2205 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
2206 eaa728ee bellard
        if (!(e2 & DESC_CS_MASK))
2207 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2208 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2209 eaa728ee bellard
        if (e2 & DESC_C_MASK) {
2210 eaa728ee bellard
            /* conforming code segment */
2211 eaa728ee bellard
            if (dpl > cpl)
2212 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2213 eaa728ee bellard
        } else {
2214 eaa728ee bellard
            /* non conforming code segment */
2215 eaa728ee bellard
            rpl = new_cs & 3;
2216 eaa728ee bellard
            if (rpl > cpl)
2217 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2218 eaa728ee bellard
            if (dpl != cpl)
2219 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2220 eaa728ee bellard
        }
2221 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2222 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2223 eaa728ee bellard
        limit = get_seg_limit(e1, e2);
2224 eaa728ee bellard
        if (new_eip > limit &&
2225 eaa728ee bellard
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2226 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2227 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2228 eaa728ee bellard
                       get_seg_base(e1, e2), limit, e2);
2229 eaa728ee bellard
        EIP = new_eip;
2230 eaa728ee bellard
    } else {
2231 eaa728ee bellard
        /* jump to call or task gate */
2232 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2233 eaa728ee bellard
        rpl = new_cs & 3;
2234 eaa728ee bellard
        cpl = env->hflags & HF_CPL_MASK;
2235 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2236 eaa728ee bellard
        switch(type) {
2237 eaa728ee bellard
        case 1: /* 286 TSS */
2238 eaa728ee bellard
        case 9: /* 386 TSS */
2239 eaa728ee bellard
        case 5: /* task gate */
2240 eaa728ee bellard
            if (dpl < cpl || dpl < rpl)
2241 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2242 eaa728ee bellard
            next_eip = env->eip + next_eip_addend;
2243 eaa728ee bellard
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2244 eaa728ee bellard
            CC_OP = CC_OP_EFLAGS;
2245 eaa728ee bellard
            break;
2246 eaa728ee bellard
        case 4: /* 286 call gate */
2247 eaa728ee bellard
        case 12: /* 386 call gate */
2248 eaa728ee bellard
            if ((dpl < cpl) || (dpl < rpl))
2249 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2250 eaa728ee bellard
            if (!(e2 & DESC_P_MASK))
2251 eaa728ee bellard
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2252 eaa728ee bellard
            gate_cs = e1 >> 16;
2253 eaa728ee bellard
            new_eip = (e1 & 0xffff);
2254 eaa728ee bellard
            if (type == 12)
2255 eaa728ee bellard
                new_eip |= (e2 & 0xffff0000);
2256 eaa728ee bellard
            if (load_segment(&e1, &e2, gate_cs) != 0)
2257 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2258 eaa728ee bellard
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2259 eaa728ee bellard
            /* must be code segment */
2260 eaa728ee bellard
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2261 eaa728ee bellard
                 (DESC_S_MASK | DESC_CS_MASK)))
2262 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2263 eaa728ee bellard
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2264 eaa728ee bellard
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2265 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2266 eaa728ee bellard
            if (!(e2 & DESC_P_MASK))
2267 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2268 eaa728ee bellard
            limit = get_seg_limit(e1, e2);
2269 eaa728ee bellard
            if (new_eip > limit)
2270 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, 0);
2271 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2272 eaa728ee bellard
                                   get_seg_base(e1, e2), limit, e2);
2273 eaa728ee bellard
            EIP = new_eip;
2274 eaa728ee bellard
            break;
2275 eaa728ee bellard
        default:
2276 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2277 eaa728ee bellard
            break;
2278 eaa728ee bellard
        }
2279 eaa728ee bellard
    }
2280 eaa728ee bellard
}
2281 eaa728ee bellard
2282 eaa728ee bellard
/* real mode call */
2283 eaa728ee bellard
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2284 eaa728ee bellard
                       int shift, int next_eip)
2285 eaa728ee bellard
{
2286 eaa728ee bellard
    int new_eip;
2287 eaa728ee bellard
    uint32_t esp, esp_mask;
2288 eaa728ee bellard
    target_ulong ssp;
2289 eaa728ee bellard
2290 eaa728ee bellard
    new_eip = new_eip1;
2291 eaa728ee bellard
    esp = ESP;
2292 eaa728ee bellard
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2293 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2294 eaa728ee bellard
    if (shift) {
2295 eaa728ee bellard
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2296 eaa728ee bellard
        PUSHL(ssp, esp, esp_mask, next_eip);
2297 eaa728ee bellard
    } else {
2298 eaa728ee bellard
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2299 eaa728ee bellard
        PUSHW(ssp, esp, esp_mask, next_eip);
2300 eaa728ee bellard
    }
2301 eaa728ee bellard
2302 eaa728ee bellard
    SET_ESP(esp, esp_mask);
2303 eaa728ee bellard
    env->eip = new_eip;
2304 eaa728ee bellard
    env->segs[R_CS].selector = new_cs;
2305 eaa728ee bellard
    env->segs[R_CS].base = (new_cs << 4);
2306 eaa728ee bellard
}
2307 eaa728ee bellard
2308 eaa728ee bellard
/* protected mode call */
2309 eaa728ee bellard
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2310 eaa728ee bellard
                            int shift, int next_eip_addend)
2311 eaa728ee bellard
{
2312 eaa728ee bellard
    int new_stack, i;
2313 eaa728ee bellard
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2314 1c918eba blueswir1
    uint32_t ss = 0, ss_e1 = 0, ss_e2 = 0, sp, type, ss_dpl, sp_mask;
2315 eaa728ee bellard
    uint32_t val, limit, old_sp_mask;
2316 eaa728ee bellard
    target_ulong ssp, old_ssp, next_eip;
2317 eaa728ee bellard
2318 eaa728ee bellard
    next_eip = env->eip + next_eip_addend;
2319 d12d51d5 aliguori
    LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift);
2320 d12d51d5 aliguori
    LOG_PCALL_STATE(env);
2321 eaa728ee bellard
    if ((new_cs & 0xfffc) == 0)
2322 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
2323 eaa728ee bellard
    if (load_segment(&e1, &e2, new_cs) != 0)
2324 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2325 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2326 d12d51d5 aliguori
    LOG_PCALL("desc=%08x:%08x\n", e1, e2);
2327 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
2328 eaa728ee bellard
        if (!(e2 & DESC_CS_MASK))
2329 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2330 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2331 eaa728ee bellard
        if (e2 & DESC_C_MASK) {
2332 eaa728ee bellard
            /* conforming code segment */
2333 eaa728ee bellard
            if (dpl > cpl)
2334 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2335 eaa728ee bellard
        } else {
2336 eaa728ee bellard
            /* non conforming code segment */
2337 eaa728ee bellard
            rpl = new_cs & 3;
2338 eaa728ee bellard
            if (rpl > cpl)
2339 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2340 eaa728ee bellard
            if (dpl != cpl)
2341 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2342 eaa728ee bellard
        }
2343 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2344 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2345 eaa728ee bellard
2346 eaa728ee bellard
#ifdef TARGET_X86_64
2347 eaa728ee bellard
        /* XXX: check 16/32 bit cases in long mode */
2348 eaa728ee bellard
        if (shift == 2) {
2349 eaa728ee bellard
            target_ulong rsp;
2350 eaa728ee bellard
            /* 64 bit case */
2351 eaa728ee bellard
            rsp = ESP;
2352 eaa728ee bellard
            PUSHQ(rsp, env->segs[R_CS].selector);
2353 eaa728ee bellard
            PUSHQ(rsp, next_eip);
2354 eaa728ee bellard
            /* from this point, not restartable */
2355 eaa728ee bellard
            ESP = rsp;
2356 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2357 eaa728ee bellard
                                   get_seg_base(e1, e2),
2358 eaa728ee bellard
                                   get_seg_limit(e1, e2), e2);
2359 eaa728ee bellard
            EIP