Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 0b97134b

History | View | Annotate | Download (153.7 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 eaa728ee bellard
 * License along with this library; if not, write to the Free Software
18 eaa728ee bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 eaa728ee bellard
 */
20 eaa728ee bellard
#define CPU_NO_GLOBAL_REGS
21 eaa728ee bellard
#include "exec.h"
22 eaa728ee bellard
#include "host-utils.h"
23 eaa728ee bellard
24 eaa728ee bellard
//#define DEBUG_PCALL
25 eaa728ee bellard
26 eaa728ee bellard
#if 0
27 eaa728ee bellard
#define raise_exception_err(a, b)\
28 eaa728ee bellard
do {\
29 eaa728ee bellard
    if (logfile)\
30 eaa728ee bellard
        fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
31 eaa728ee bellard
    (raise_exception_err)(a, b);\
32 eaa728ee bellard
} while (0)
33 eaa728ee bellard
#endif
34 eaa728ee bellard
35 eaa728ee bellard
const uint8_t parity_table[256] = {
36 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
37 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
38 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
40 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
41 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
42 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
44 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
47 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
52 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
53 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
61 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
62 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
63 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
64 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
65 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
66 eaa728ee bellard
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
67 eaa728ee bellard
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
68 eaa728ee bellard
};
69 eaa728ee bellard
70 eaa728ee bellard
/* modulo 17 table */
71 eaa728ee bellard
const uint8_t rclw_table[32] = {
72 eaa728ee bellard
    0, 1, 2, 3, 4, 5, 6, 7,
73 eaa728ee bellard
    8, 9,10,11,12,13,14,15,
74 eaa728ee bellard
   16, 0, 1, 2, 3, 4, 5, 6,
75 eaa728ee bellard
    7, 8, 9,10,11,12,13,14,
76 eaa728ee bellard
};
77 eaa728ee bellard
78 eaa728ee bellard
/* modulo 9 table */
79 eaa728ee bellard
const uint8_t rclb_table[32] = {
80 eaa728ee bellard
    0, 1, 2, 3, 4, 5, 6, 7,
81 eaa728ee bellard
    8, 0, 1, 2, 3, 4, 5, 6,
82 eaa728ee bellard
    7, 8, 0, 1, 2, 3, 4, 5,
83 eaa728ee bellard
    6, 7, 8, 0, 1, 2, 3, 4,
84 eaa728ee bellard
};
85 eaa728ee bellard
86 eaa728ee bellard
const CPU86_LDouble f15rk[7] =
87 eaa728ee bellard
{
88 eaa728ee bellard
    0.00000000000000000000L,
89 eaa728ee bellard
    1.00000000000000000000L,
90 eaa728ee bellard
    3.14159265358979323851L,  /*pi*/
91 eaa728ee bellard
    0.30102999566398119523L,  /*lg2*/
92 eaa728ee bellard
    0.69314718055994530943L,  /*ln2*/
93 eaa728ee bellard
    1.44269504088896340739L,  /*l2e*/
94 eaa728ee bellard
    3.32192809488736234781L,  /*l2t*/
95 eaa728ee bellard
};
96 eaa728ee bellard
97 eaa728ee bellard
/* broken thread support */
98 eaa728ee bellard
99 b1d8e52e blueswir1
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
100 eaa728ee bellard
101 eaa728ee bellard
void helper_lock(void)
102 eaa728ee bellard
{
103 eaa728ee bellard
    spin_lock(&global_cpu_lock);
104 eaa728ee bellard
}
105 eaa728ee bellard
106 eaa728ee bellard
void helper_unlock(void)
107 eaa728ee bellard
{
108 eaa728ee bellard
    spin_unlock(&global_cpu_lock);
109 eaa728ee bellard
}
110 eaa728ee bellard
111 eaa728ee bellard
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
112 eaa728ee bellard
{
113 eaa728ee bellard
    load_eflags(t0, update_mask);
114 eaa728ee bellard
}
115 eaa728ee bellard
116 eaa728ee bellard
target_ulong helper_read_eflags(void)
117 eaa728ee bellard
{
118 eaa728ee bellard
    uint32_t eflags;
119 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
120 eaa728ee bellard
    eflags |= (DF & DF_MASK);
121 eaa728ee bellard
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
122 eaa728ee bellard
    return eflags;
123 eaa728ee bellard
}
124 eaa728ee bellard
125 eaa728ee bellard
/* return non zero if error */
126 eaa728ee bellard
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
127 eaa728ee bellard
                               int selector)
128 eaa728ee bellard
{
129 eaa728ee bellard
    SegmentCache *dt;
130 eaa728ee bellard
    int index;
131 eaa728ee bellard
    target_ulong ptr;
132 eaa728ee bellard
133 eaa728ee bellard
    if (selector & 0x4)
134 eaa728ee bellard
        dt = &env->ldt;
135 eaa728ee bellard
    else
136 eaa728ee bellard
        dt = &env->gdt;
137 eaa728ee bellard
    index = selector & ~7;
138 eaa728ee bellard
    if ((index + 7) > dt->limit)
139 eaa728ee bellard
        return -1;
140 eaa728ee bellard
    ptr = dt->base + index;
141 eaa728ee bellard
    *e1_ptr = ldl_kernel(ptr);
142 eaa728ee bellard
    *e2_ptr = ldl_kernel(ptr + 4);
143 eaa728ee bellard
    return 0;
144 eaa728ee bellard
}
145 eaa728ee bellard
146 eaa728ee bellard
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
147 eaa728ee bellard
{
148 eaa728ee bellard
    unsigned int limit;
149 eaa728ee bellard
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
150 eaa728ee bellard
    if (e2 & DESC_G_MASK)
151 eaa728ee bellard
        limit = (limit << 12) | 0xfff;
152 eaa728ee bellard
    return limit;
153 eaa728ee bellard
}
154 eaa728ee bellard
155 eaa728ee bellard
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
156 eaa728ee bellard
{
157 eaa728ee bellard
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
158 eaa728ee bellard
}
159 eaa728ee bellard
160 eaa728ee bellard
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
161 eaa728ee bellard
{
162 eaa728ee bellard
    sc->base = get_seg_base(e1, e2);
163 eaa728ee bellard
    sc->limit = get_seg_limit(e1, e2);
164 eaa728ee bellard
    sc->flags = e2;
165 eaa728ee bellard
}
166 eaa728ee bellard
167 eaa728ee bellard
/* init the segment cache in vm86 mode. */
168 eaa728ee bellard
static inline void load_seg_vm(int seg, int selector)
169 eaa728ee bellard
{
170 eaa728ee bellard
    selector &= 0xffff;
171 eaa728ee bellard
    cpu_x86_load_seg_cache(env, seg, selector,
172 eaa728ee bellard
                           (selector << 4), 0xffff, 0);
173 eaa728ee bellard
}
174 eaa728ee bellard
175 eaa728ee bellard
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
176 eaa728ee bellard
                                       uint32_t *esp_ptr, int dpl)
177 eaa728ee bellard
{
178 eaa728ee bellard
    int type, index, shift;
179 eaa728ee bellard
180 eaa728ee bellard
#if 0
181 eaa728ee bellard
    {
182 eaa728ee bellard
        int i;
183 eaa728ee bellard
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
184 eaa728ee bellard
        for(i=0;i<env->tr.limit;i++) {
185 eaa728ee bellard
            printf("%02x ", env->tr.base[i]);
186 eaa728ee bellard
            if ((i & 7) == 7) printf("\n");
187 eaa728ee bellard
        }
188 eaa728ee bellard
        printf("\n");
189 eaa728ee bellard
    }
190 eaa728ee bellard
#endif
191 eaa728ee bellard
192 eaa728ee bellard
    if (!(env->tr.flags & DESC_P_MASK))
193 eaa728ee bellard
        cpu_abort(env, "invalid tss");
194 eaa728ee bellard
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
195 eaa728ee bellard
    if ((type & 7) != 1)
196 eaa728ee bellard
        cpu_abort(env, "invalid tss type");
197 eaa728ee bellard
    shift = type >> 3;
198 eaa728ee bellard
    index = (dpl * 4 + 2) << shift;
199 eaa728ee bellard
    if (index + (4 << shift) - 1 > env->tr.limit)
200 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
201 eaa728ee bellard
    if (shift == 0) {
202 eaa728ee bellard
        *esp_ptr = lduw_kernel(env->tr.base + index);
203 eaa728ee bellard
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
204 eaa728ee bellard
    } else {
205 eaa728ee bellard
        *esp_ptr = ldl_kernel(env->tr.base + index);
206 eaa728ee bellard
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
207 eaa728ee bellard
    }
208 eaa728ee bellard
}
209 eaa728ee bellard
210 eaa728ee bellard
/* XXX: merge with load_seg() */
211 eaa728ee bellard
static void tss_load_seg(int seg_reg, int selector)
212 eaa728ee bellard
{
213 eaa728ee bellard
    uint32_t e1, e2;
214 eaa728ee bellard
    int rpl, dpl, cpl;
215 eaa728ee bellard
216 eaa728ee bellard
    if ((selector & 0xfffc) != 0) {
217 eaa728ee bellard
        if (load_segment(&e1, &e2, selector) != 0)
218 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
219 eaa728ee bellard
        if (!(e2 & DESC_S_MASK))
220 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
221 eaa728ee bellard
        rpl = selector & 3;
222 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
223 eaa728ee bellard
        cpl = env->hflags & HF_CPL_MASK;
224 eaa728ee bellard
        if (seg_reg == R_CS) {
225 eaa728ee bellard
            if (!(e2 & DESC_CS_MASK))
226 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
227 eaa728ee bellard
            /* XXX: is it correct ? */
228 eaa728ee bellard
            if (dpl != rpl)
229 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
230 eaa728ee bellard
            if ((e2 & DESC_C_MASK) && dpl > rpl)
231 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
232 eaa728ee bellard
        } else if (seg_reg == R_SS) {
233 eaa728ee bellard
            /* SS must be writable data */
234 eaa728ee bellard
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
235 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
236 eaa728ee bellard
            if (dpl != cpl || dpl != rpl)
237 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
238 eaa728ee bellard
        } else {
239 eaa728ee bellard
            /* not readable code */
240 eaa728ee bellard
            if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
241 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
242 eaa728ee bellard
            /* if data or non conforming code, checks the rights */
243 eaa728ee bellard
            if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
244 eaa728ee bellard
                if (dpl < cpl || dpl < rpl)
245 eaa728ee bellard
                    raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
246 eaa728ee bellard
            }
247 eaa728ee bellard
        }
248 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
249 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
250 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector,
251 eaa728ee bellard
                       get_seg_base(e1, e2),
252 eaa728ee bellard
                       get_seg_limit(e1, e2),
253 eaa728ee bellard
                       e2);
254 eaa728ee bellard
    } else {
255 eaa728ee bellard
        if (seg_reg == R_SS || seg_reg == R_CS)
256 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
257 eaa728ee bellard
    }
258 eaa728ee bellard
}
259 eaa728ee bellard
260 eaa728ee bellard
#define SWITCH_TSS_JMP  0
261 eaa728ee bellard
#define SWITCH_TSS_IRET 1
262 eaa728ee bellard
#define SWITCH_TSS_CALL 2
263 eaa728ee bellard
264 eaa728ee bellard
/* XXX: restore CPU state in registers (PowerPC case) */
265 eaa728ee bellard
static void switch_tss(int tss_selector,
266 eaa728ee bellard
                       uint32_t e1, uint32_t e2, int source,
267 eaa728ee bellard
                       uint32_t next_eip)
268 eaa728ee bellard
{
269 eaa728ee bellard
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
270 eaa728ee bellard
    target_ulong tss_base;
271 eaa728ee bellard
    uint32_t new_regs[8], new_segs[6];
272 eaa728ee bellard
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
273 eaa728ee bellard
    uint32_t old_eflags, eflags_mask;
274 eaa728ee bellard
    SegmentCache *dt;
275 eaa728ee bellard
    int index;
276 eaa728ee bellard
    target_ulong ptr;
277 eaa728ee bellard
278 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
279 eaa728ee bellard
#ifdef DEBUG_PCALL
280 eaa728ee bellard
    if (loglevel & CPU_LOG_PCALL)
281 eaa728ee bellard
        fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
282 eaa728ee bellard
#endif
283 eaa728ee bellard
284 eaa728ee bellard
    /* if task gate, we read the TSS segment and we load it */
285 eaa728ee bellard
    if (type == 5) {
286 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
287 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
288 eaa728ee bellard
        tss_selector = e1 >> 16;
289 eaa728ee bellard
        if (tss_selector & 4)
290 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
291 eaa728ee bellard
        if (load_segment(&e1, &e2, tss_selector) != 0)
292 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
293 eaa728ee bellard
        if (e2 & DESC_S_MASK)
294 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
295 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
296 eaa728ee bellard
        if ((type & 7) != 1)
297 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
298 eaa728ee bellard
    }
299 eaa728ee bellard
300 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
301 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
302 eaa728ee bellard
303 eaa728ee bellard
    if (type & 8)
304 eaa728ee bellard
        tss_limit_max = 103;
305 eaa728ee bellard
    else
306 eaa728ee bellard
        tss_limit_max = 43;
307 eaa728ee bellard
    tss_limit = get_seg_limit(e1, e2);
308 eaa728ee bellard
    tss_base = get_seg_base(e1, e2);
309 eaa728ee bellard
    if ((tss_selector & 4) != 0 ||
310 eaa728ee bellard
        tss_limit < tss_limit_max)
311 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
312 eaa728ee bellard
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
313 eaa728ee bellard
    if (old_type & 8)
314 eaa728ee bellard
        old_tss_limit_max = 103;
315 eaa728ee bellard
    else
316 eaa728ee bellard
        old_tss_limit_max = 43;
317 eaa728ee bellard
318 eaa728ee bellard
    /* read all the registers from the new TSS */
319 eaa728ee bellard
    if (type & 8) {
320 eaa728ee bellard
        /* 32 bit */
321 eaa728ee bellard
        new_cr3 = ldl_kernel(tss_base + 0x1c);
322 eaa728ee bellard
        new_eip = ldl_kernel(tss_base + 0x20);
323 eaa728ee bellard
        new_eflags = ldl_kernel(tss_base + 0x24);
324 eaa728ee bellard
        for(i = 0; i < 8; i++)
325 eaa728ee bellard
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
326 eaa728ee bellard
        for(i = 0; i < 6; i++)
327 eaa728ee bellard
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
328 eaa728ee bellard
        new_ldt = lduw_kernel(tss_base + 0x60);
329 eaa728ee bellard
        new_trap = ldl_kernel(tss_base + 0x64);
330 eaa728ee bellard
    } else {
331 eaa728ee bellard
        /* 16 bit */
332 eaa728ee bellard
        new_cr3 = 0;
333 eaa728ee bellard
        new_eip = lduw_kernel(tss_base + 0x0e);
334 eaa728ee bellard
        new_eflags = lduw_kernel(tss_base + 0x10);
335 eaa728ee bellard
        for(i = 0; i < 8; i++)
336 eaa728ee bellard
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
337 eaa728ee bellard
        for(i = 0; i < 4; i++)
338 eaa728ee bellard
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
339 eaa728ee bellard
        new_ldt = lduw_kernel(tss_base + 0x2a);
340 eaa728ee bellard
        new_segs[R_FS] = 0;
341 eaa728ee bellard
        new_segs[R_GS] = 0;
342 eaa728ee bellard
        new_trap = 0;
343 eaa728ee bellard
    }
344 eaa728ee bellard
345 eaa728ee bellard
    /* NOTE: we must avoid memory exceptions during the task switch,
346 eaa728ee bellard
       so we make dummy accesses before */
347 eaa728ee bellard
    /* XXX: it can still fail in some cases, so a bigger hack is
348 eaa728ee bellard
       necessary to valid the TLB after having done the accesses */
349 eaa728ee bellard
350 eaa728ee bellard
    v1 = ldub_kernel(env->tr.base);
351 eaa728ee bellard
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
352 eaa728ee bellard
    stb_kernel(env->tr.base, v1);
353 eaa728ee bellard
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
354 eaa728ee bellard
355 eaa728ee bellard
    /* clear busy bit (it is restartable) */
356 eaa728ee bellard
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
357 eaa728ee bellard
        target_ulong ptr;
358 eaa728ee bellard
        uint32_t e2;
359 eaa728ee bellard
        ptr = env->gdt.base + (env->tr.selector & ~7);
360 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
361 eaa728ee bellard
        e2 &= ~DESC_TSS_BUSY_MASK;
362 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
363 eaa728ee bellard
    }
364 eaa728ee bellard
    old_eflags = compute_eflags();
365 eaa728ee bellard
    if (source == SWITCH_TSS_IRET)
366 eaa728ee bellard
        old_eflags &= ~NT_MASK;
367 eaa728ee bellard
368 eaa728ee bellard
    /* save the current state in the old TSS */
369 eaa728ee bellard
    if (type & 8) {
370 eaa728ee bellard
        /* 32 bit */
371 eaa728ee bellard
        stl_kernel(env->tr.base + 0x20, next_eip);
372 eaa728ee bellard
        stl_kernel(env->tr.base + 0x24, old_eflags);
373 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
374 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
375 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
376 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
377 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
378 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
379 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
380 eaa728ee bellard
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
381 eaa728ee bellard
        for(i = 0; i < 6; i++)
382 eaa728ee bellard
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
383 eaa728ee bellard
    } else {
384 eaa728ee bellard
        /* 16 bit */
385 eaa728ee bellard
        stw_kernel(env->tr.base + 0x0e, next_eip);
386 eaa728ee bellard
        stw_kernel(env->tr.base + 0x10, old_eflags);
387 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
388 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
389 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
390 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
391 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
392 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
393 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
394 eaa728ee bellard
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
395 eaa728ee bellard
        for(i = 0; i < 4; i++)
396 eaa728ee bellard
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
397 eaa728ee bellard
    }
398 eaa728ee bellard
399 eaa728ee bellard
    /* now if an exception occurs, it will occurs in the next task
400 eaa728ee bellard
       context */
401 eaa728ee bellard
402 eaa728ee bellard
    if (source == SWITCH_TSS_CALL) {
403 eaa728ee bellard
        stw_kernel(tss_base, env->tr.selector);
404 eaa728ee bellard
        new_eflags |= NT_MASK;
405 eaa728ee bellard
    }
406 eaa728ee bellard
407 eaa728ee bellard
    /* set busy bit */
408 eaa728ee bellard
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
409 eaa728ee bellard
        target_ulong ptr;
410 eaa728ee bellard
        uint32_t e2;
411 eaa728ee bellard
        ptr = env->gdt.base + (tss_selector & ~7);
412 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
413 eaa728ee bellard
        e2 |= DESC_TSS_BUSY_MASK;
414 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
415 eaa728ee bellard
    }
416 eaa728ee bellard
417 eaa728ee bellard
    /* set the new CPU state */
418 eaa728ee bellard
    /* from this point, any exception which occurs can give problems */
419 eaa728ee bellard
    env->cr[0] |= CR0_TS_MASK;
420 eaa728ee bellard
    env->hflags |= HF_TS_MASK;
421 eaa728ee bellard
    env->tr.selector = tss_selector;
422 eaa728ee bellard
    env->tr.base = tss_base;
423 eaa728ee bellard
    env->tr.limit = tss_limit;
424 eaa728ee bellard
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
425 eaa728ee bellard
426 eaa728ee bellard
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
427 eaa728ee bellard
        cpu_x86_update_cr3(env, new_cr3);
428 eaa728ee bellard
    }
429 eaa728ee bellard
430 eaa728ee bellard
    /* load all registers without an exception, then reload them with
431 eaa728ee bellard
       possible exception */
432 eaa728ee bellard
    env->eip = new_eip;
433 eaa728ee bellard
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
434 eaa728ee bellard
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
435 eaa728ee bellard
    if (!(type & 8))
436 eaa728ee bellard
        eflags_mask &= 0xffff;
437 eaa728ee bellard
    load_eflags(new_eflags, eflags_mask);
438 eaa728ee bellard
    /* XXX: what to do in 16 bit case ? */
439 eaa728ee bellard
    EAX = new_regs[0];
440 eaa728ee bellard
    ECX = new_regs[1];
441 eaa728ee bellard
    EDX = new_regs[2];
442 eaa728ee bellard
    EBX = new_regs[3];
443 eaa728ee bellard
    ESP = new_regs[4];
444 eaa728ee bellard
    EBP = new_regs[5];
445 eaa728ee bellard
    ESI = new_regs[6];
446 eaa728ee bellard
    EDI = new_regs[7];
447 eaa728ee bellard
    if (new_eflags & VM_MASK) {
448 eaa728ee bellard
        for(i = 0; i < 6; i++)
449 eaa728ee bellard
            load_seg_vm(i, new_segs[i]);
450 eaa728ee bellard
        /* in vm86, CPL is always 3 */
451 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
452 eaa728ee bellard
    } else {
453 eaa728ee bellard
        /* CPL is set the RPL of CS */
454 eaa728ee bellard
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
455 eaa728ee bellard
        /* first just selectors as the rest may trigger exceptions */
456 eaa728ee bellard
        for(i = 0; i < 6; i++)
457 eaa728ee bellard
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
458 eaa728ee bellard
    }
459 eaa728ee bellard
460 eaa728ee bellard
    env->ldt.selector = new_ldt & ~4;
461 eaa728ee bellard
    env->ldt.base = 0;
462 eaa728ee bellard
    env->ldt.limit = 0;
463 eaa728ee bellard
    env->ldt.flags = 0;
464 eaa728ee bellard
465 eaa728ee bellard
    /* load the LDT */
466 eaa728ee bellard
    if (new_ldt & 4)
467 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
468 eaa728ee bellard
469 eaa728ee bellard
    if ((new_ldt & 0xfffc) != 0) {
470 eaa728ee bellard
        dt = &env->gdt;
471 eaa728ee bellard
        index = new_ldt & ~7;
472 eaa728ee bellard
        if ((index + 7) > dt->limit)
473 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
474 eaa728ee bellard
        ptr = dt->base + index;
475 eaa728ee bellard
        e1 = ldl_kernel(ptr);
476 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
477 eaa728ee bellard
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
478 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
479 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
480 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
481 eaa728ee bellard
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
482 eaa728ee bellard
    }
483 eaa728ee bellard
484 eaa728ee bellard
    /* load the segments */
485 eaa728ee bellard
    if (!(new_eflags & VM_MASK)) {
486 eaa728ee bellard
        tss_load_seg(R_CS, new_segs[R_CS]);
487 eaa728ee bellard
        tss_load_seg(R_SS, new_segs[R_SS]);
488 eaa728ee bellard
        tss_load_seg(R_ES, new_segs[R_ES]);
489 eaa728ee bellard
        tss_load_seg(R_DS, new_segs[R_DS]);
490 eaa728ee bellard
        tss_load_seg(R_FS, new_segs[R_FS]);
491 eaa728ee bellard
        tss_load_seg(R_GS, new_segs[R_GS]);
492 eaa728ee bellard
    }
493 eaa728ee bellard
494 eaa728ee bellard
    /* check that EIP is in the CS segment limits */
495 eaa728ee bellard
    if (new_eip > env->segs[R_CS].limit) {
496 eaa728ee bellard
        /* XXX: different exception if CALL ? */
497 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
498 eaa728ee bellard
    }
499 01df040b aliguori
500 01df040b aliguori
#ifndef CONFIG_USER_ONLY
501 01df040b aliguori
    /* reset local breakpoints */
502 01df040b aliguori
    if (env->dr[7] & 0x55) {
503 01df040b aliguori
        for (i = 0; i < 4; i++) {
504 01df040b aliguori
            if (hw_breakpoint_enabled(env->dr[7], i) == 0x1)
505 01df040b aliguori
                hw_breakpoint_remove(env, i);
506 01df040b aliguori
        }
507 01df040b aliguori
        env->dr[7] &= ~0x55;
508 01df040b aliguori
    }
509 01df040b aliguori
#endif
510 eaa728ee bellard
}
511 eaa728ee bellard
512 eaa728ee bellard
/* check if Port I/O is allowed in TSS */
513 eaa728ee bellard
static inline void check_io(int addr, int size)
514 eaa728ee bellard
{
515 eaa728ee bellard
    int io_offset, val, mask;
516 eaa728ee bellard
517 eaa728ee bellard
    /* TSS must be a valid 32 bit one */
518 eaa728ee bellard
    if (!(env->tr.flags & DESC_P_MASK) ||
519 eaa728ee bellard
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
520 eaa728ee bellard
        env->tr.limit < 103)
521 eaa728ee bellard
        goto fail;
522 eaa728ee bellard
    io_offset = lduw_kernel(env->tr.base + 0x66);
523 eaa728ee bellard
    io_offset += (addr >> 3);
524 eaa728ee bellard
    /* Note: the check needs two bytes */
525 eaa728ee bellard
    if ((io_offset + 1) > env->tr.limit)
526 eaa728ee bellard
        goto fail;
527 eaa728ee bellard
    val = lduw_kernel(env->tr.base + io_offset);
528 eaa728ee bellard
    val >>= (addr & 7);
529 eaa728ee bellard
    mask = (1 << size) - 1;
530 eaa728ee bellard
    /* all bits must be zero to allow the I/O */
531 eaa728ee bellard
    if ((val & mask) != 0) {
532 eaa728ee bellard
    fail:
533 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
534 eaa728ee bellard
    }
535 eaa728ee bellard
}
536 eaa728ee bellard
537 eaa728ee bellard
void helper_check_iob(uint32_t t0)
538 eaa728ee bellard
{
539 eaa728ee bellard
    check_io(t0, 1);
540 eaa728ee bellard
}
541 eaa728ee bellard
542 eaa728ee bellard
void helper_check_iow(uint32_t t0)
543 eaa728ee bellard
{
544 eaa728ee bellard
    check_io(t0, 2);
545 eaa728ee bellard
}
546 eaa728ee bellard
547 eaa728ee bellard
void helper_check_iol(uint32_t t0)
548 eaa728ee bellard
{
549 eaa728ee bellard
    check_io(t0, 4);
550 eaa728ee bellard
}
551 eaa728ee bellard
552 eaa728ee bellard
void helper_outb(uint32_t port, uint32_t data)
553 eaa728ee bellard
{
554 eaa728ee bellard
    cpu_outb(env, port, data & 0xff);
555 eaa728ee bellard
}
556 eaa728ee bellard
557 eaa728ee bellard
target_ulong helper_inb(uint32_t port)
558 eaa728ee bellard
{
559 eaa728ee bellard
    return cpu_inb(env, port);
560 eaa728ee bellard
}
561 eaa728ee bellard
562 eaa728ee bellard
void helper_outw(uint32_t port, uint32_t data)
563 eaa728ee bellard
{
564 eaa728ee bellard
    cpu_outw(env, port, data & 0xffff);
565 eaa728ee bellard
}
566 eaa728ee bellard
567 eaa728ee bellard
target_ulong helper_inw(uint32_t port)
568 eaa728ee bellard
{
569 eaa728ee bellard
    return cpu_inw(env, port);
570 eaa728ee bellard
}
571 eaa728ee bellard
572 eaa728ee bellard
void helper_outl(uint32_t port, uint32_t data)
573 eaa728ee bellard
{
574 eaa728ee bellard
    cpu_outl(env, port, data);
575 eaa728ee bellard
}
576 eaa728ee bellard
577 eaa728ee bellard
target_ulong helper_inl(uint32_t port)
578 eaa728ee bellard
{
579 eaa728ee bellard
    return cpu_inl(env, port);
580 eaa728ee bellard
}
581 eaa728ee bellard
582 eaa728ee bellard
static inline unsigned int get_sp_mask(unsigned int e2)
583 eaa728ee bellard
{
584 eaa728ee bellard
    if (e2 & DESC_B_MASK)
585 eaa728ee bellard
        return 0xffffffff;
586 eaa728ee bellard
    else
587 eaa728ee bellard
        return 0xffff;
588 eaa728ee bellard
}
589 eaa728ee bellard
590 eaa728ee bellard
#ifdef TARGET_X86_64
591 eaa728ee bellard
#define SET_ESP(val, sp_mask)\
592 eaa728ee bellard
do {\
593 eaa728ee bellard
    if ((sp_mask) == 0xffff)\
594 eaa728ee bellard
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
595 eaa728ee bellard
    else if ((sp_mask) == 0xffffffffLL)\
596 eaa728ee bellard
        ESP = (uint32_t)(val);\
597 eaa728ee bellard
    else\
598 eaa728ee bellard
        ESP = (val);\
599 eaa728ee bellard
} while (0)
600 eaa728ee bellard
#else
601 eaa728ee bellard
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
602 eaa728ee bellard
#endif
603 eaa728ee bellard
604 c0a04f0e aliguori
/* in 64-bit machines, this can overflow. So this segment addition macro
605 c0a04f0e aliguori
 * can be used to trim the value to 32-bit whenever needed */
606 c0a04f0e aliguori
#define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
607 c0a04f0e aliguori
608 eaa728ee bellard
/* XXX: add a is_user flag to have proper security support */
609 eaa728ee bellard
#define PUSHW(ssp, sp, sp_mask, val)\
610 eaa728ee bellard
{\
611 eaa728ee bellard
    sp -= 2;\
612 eaa728ee bellard
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
613 eaa728ee bellard
}
614 eaa728ee bellard
615 eaa728ee bellard
#define PUSHL(ssp, sp, sp_mask, val)\
616 eaa728ee bellard
{\
617 eaa728ee bellard
    sp -= 4;\
618 c0a04f0e aliguori
    stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
619 eaa728ee bellard
}
620 eaa728ee bellard
621 eaa728ee bellard
#define POPW(ssp, sp, sp_mask, val)\
622 eaa728ee bellard
{\
623 eaa728ee bellard
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
624 eaa728ee bellard
    sp += 2;\
625 eaa728ee bellard
}
626 eaa728ee bellard
627 eaa728ee bellard
#define POPL(ssp, sp, sp_mask, val)\
628 eaa728ee bellard
{\
629 c0a04f0e aliguori
    val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
630 eaa728ee bellard
    sp += 4;\
631 eaa728ee bellard
}
632 eaa728ee bellard
633 eaa728ee bellard
/* protected mode interrupt */
634 eaa728ee bellard
static void do_interrupt_protected(int intno, int is_int, int error_code,
635 eaa728ee bellard
                                   unsigned int next_eip, int is_hw)
636 eaa728ee bellard
{
637 eaa728ee bellard
    SegmentCache *dt;
638 eaa728ee bellard
    target_ulong ptr, ssp;
639 eaa728ee bellard
    int type, dpl, selector, ss_dpl, cpl;
640 eaa728ee bellard
    int has_error_code, new_stack, shift;
641 eaa728ee bellard
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
642 eaa728ee bellard
    uint32_t old_eip, sp_mask;
643 eaa728ee bellard
644 eaa728ee bellard
    has_error_code = 0;
645 eaa728ee bellard
    if (!is_int && !is_hw) {
646 eaa728ee bellard
        switch(intno) {
647 eaa728ee bellard
        case 8:
648 eaa728ee bellard
        case 10:
649 eaa728ee bellard
        case 11:
650 eaa728ee bellard
        case 12:
651 eaa728ee bellard
        case 13:
652 eaa728ee bellard
        case 14:
653 eaa728ee bellard
        case 17:
654 eaa728ee bellard
            has_error_code = 1;
655 eaa728ee bellard
            break;
656 eaa728ee bellard
        }
657 eaa728ee bellard
    }
658 eaa728ee bellard
    if (is_int)
659 eaa728ee bellard
        old_eip = next_eip;
660 eaa728ee bellard
    else
661 eaa728ee bellard
        old_eip = env->eip;
662 eaa728ee bellard
663 eaa728ee bellard
    dt = &env->idt;
664 eaa728ee bellard
    if (intno * 8 + 7 > dt->limit)
665 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
666 eaa728ee bellard
    ptr = dt->base + intno * 8;
667 eaa728ee bellard
    e1 = ldl_kernel(ptr);
668 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
669 eaa728ee bellard
    /* check gate type */
670 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
671 eaa728ee bellard
    switch(type) {
672 eaa728ee bellard
    case 5: /* task gate */
673 eaa728ee bellard
        /* must do that check here to return the correct error code */
674 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
675 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
676 eaa728ee bellard
        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
677 eaa728ee bellard
        if (has_error_code) {
678 eaa728ee bellard
            int type;
679 eaa728ee bellard
            uint32_t mask;
680 eaa728ee bellard
            /* push the error code */
681 eaa728ee bellard
            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
682 eaa728ee bellard
            shift = type >> 3;
683 eaa728ee bellard
            if (env->segs[R_SS].flags & DESC_B_MASK)
684 eaa728ee bellard
                mask = 0xffffffff;
685 eaa728ee bellard
            else
686 eaa728ee bellard
                mask = 0xffff;
687 eaa728ee bellard
            esp = (ESP - (2 << shift)) & mask;
688 eaa728ee bellard
            ssp = env->segs[R_SS].base + esp;
689 eaa728ee bellard
            if (shift)
690 eaa728ee bellard
                stl_kernel(ssp, error_code);
691 eaa728ee bellard
            else
692 eaa728ee bellard
                stw_kernel(ssp, error_code);
693 eaa728ee bellard
            SET_ESP(esp, mask);
694 eaa728ee bellard
        }
695 eaa728ee bellard
        return;
696 eaa728ee bellard
    case 6: /* 286 interrupt gate */
697 eaa728ee bellard
    case 7: /* 286 trap gate */
698 eaa728ee bellard
    case 14: /* 386 interrupt gate */
699 eaa728ee bellard
    case 15: /* 386 trap gate */
700 eaa728ee bellard
        break;
701 eaa728ee bellard
    default:
702 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
703 eaa728ee bellard
        break;
704 eaa728ee bellard
    }
705 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
706 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
707 1235fc06 ths
    /* check privilege if software int */
708 eaa728ee bellard
    if (is_int && dpl < cpl)
709 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
710 eaa728ee bellard
    /* check valid bit */
711 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
712 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
713 eaa728ee bellard
    selector = e1 >> 16;
714 eaa728ee bellard
    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
715 eaa728ee bellard
    if ((selector & 0xfffc) == 0)
716 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
717 eaa728ee bellard
718 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
719 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
720 eaa728ee bellard
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
721 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
722 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
723 eaa728ee bellard
    if (dpl > cpl)
724 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
725 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
726 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
727 eaa728ee bellard
    if (!(e2 & DESC_C_MASK) && dpl < cpl) {
728 eaa728ee bellard
        /* to inner privilege */
729 eaa728ee bellard
        get_ss_esp_from_tss(&ss, &esp, dpl);
730 eaa728ee bellard
        if ((ss & 0xfffc) == 0)
731 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
732 eaa728ee bellard
        if ((ss & 3) != dpl)
733 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
734 eaa728ee bellard
        if (load_segment(&ss_e1, &ss_e2, ss) != 0)
735 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
736 eaa728ee bellard
        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
737 eaa728ee bellard
        if (ss_dpl != dpl)
738 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
739 eaa728ee bellard
        if (!(ss_e2 & DESC_S_MASK) ||
740 eaa728ee bellard
            (ss_e2 & DESC_CS_MASK) ||
741 eaa728ee bellard
            !(ss_e2 & DESC_W_MASK))
742 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
743 eaa728ee bellard
        if (!(ss_e2 & DESC_P_MASK))
744 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
745 eaa728ee bellard
        new_stack = 1;
746 eaa728ee bellard
        sp_mask = get_sp_mask(ss_e2);
747 eaa728ee bellard
        ssp = get_seg_base(ss_e1, ss_e2);
748 eaa728ee bellard
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
749 eaa728ee bellard
        /* to same privilege */
750 eaa728ee bellard
        if (env->eflags & VM_MASK)
751 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
752 eaa728ee bellard
        new_stack = 0;
753 eaa728ee bellard
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
754 eaa728ee bellard
        ssp = env->segs[R_SS].base;
755 eaa728ee bellard
        esp = ESP;
756 eaa728ee bellard
        dpl = cpl;
757 eaa728ee bellard
    } else {
758 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
759 eaa728ee bellard
        new_stack = 0; /* avoid warning */
760 eaa728ee bellard
        sp_mask = 0; /* avoid warning */
761 eaa728ee bellard
        ssp = 0; /* avoid warning */
762 eaa728ee bellard
        esp = 0; /* avoid warning */
763 eaa728ee bellard
    }
764 eaa728ee bellard
765 eaa728ee bellard
    shift = type >> 3;
766 eaa728ee bellard
767 eaa728ee bellard
#if 0
768 eaa728ee bellard
    /* XXX: check that enough room is available */
769 eaa728ee bellard
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
770 eaa728ee bellard
    if (env->eflags & VM_MASK)
771 eaa728ee bellard
        push_size += 8;
772 eaa728ee bellard
    push_size <<= shift;
773 eaa728ee bellard
#endif
774 eaa728ee bellard
    if (shift == 1) {
775 eaa728ee bellard
        if (new_stack) {
776 eaa728ee bellard
            if (env->eflags & VM_MASK) {
777 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
778 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
779 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
780 eaa728ee bellard
                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
781 eaa728ee bellard
            }
782 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
783 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, ESP);
784 eaa728ee bellard
        }
785 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, compute_eflags());
786 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
787 eaa728ee bellard
        PUSHL(ssp, esp, sp_mask, old_eip);
788 eaa728ee bellard
        if (has_error_code) {
789 eaa728ee bellard
            PUSHL(ssp, esp, sp_mask, error_code);
790 eaa728ee bellard
        }
791 eaa728ee bellard
    } else {
792 eaa728ee bellard
        if (new_stack) {
793 eaa728ee bellard
            if (env->eflags & VM_MASK) {
794 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
795 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
796 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
797 eaa728ee bellard
                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
798 eaa728ee bellard
            }
799 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
800 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, ESP);
801 eaa728ee bellard
        }
802 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, compute_eflags());
803 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
804 eaa728ee bellard
        PUSHW(ssp, esp, sp_mask, old_eip);
805 eaa728ee bellard
        if (has_error_code) {
806 eaa728ee bellard
            PUSHW(ssp, esp, sp_mask, error_code);
807 eaa728ee bellard
        }
808 eaa728ee bellard
    }
809 eaa728ee bellard
810 eaa728ee bellard
    if (new_stack) {
811 eaa728ee bellard
        if (env->eflags & VM_MASK) {
812 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
813 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
814 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
815 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
816 eaa728ee bellard
        }
817 eaa728ee bellard
        ss = (ss & ~3) | dpl;
818 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, ss,
819 eaa728ee bellard
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
820 eaa728ee bellard
    }
821 eaa728ee bellard
    SET_ESP(esp, sp_mask);
822 eaa728ee bellard
823 eaa728ee bellard
    selector = (selector & ~3) | dpl;
824 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, selector,
825 eaa728ee bellard
                   get_seg_base(e1, e2),
826 eaa728ee bellard
                   get_seg_limit(e1, e2),
827 eaa728ee bellard
                   e2);
828 eaa728ee bellard
    cpu_x86_set_cpl(env, dpl);
829 eaa728ee bellard
    env->eip = offset;
830 eaa728ee bellard
831 eaa728ee bellard
    /* interrupt gate clear IF mask */
832 eaa728ee bellard
    if ((type & 1) == 0) {
833 eaa728ee bellard
        env->eflags &= ~IF_MASK;
834 eaa728ee bellard
    }
835 eaa728ee bellard
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
836 eaa728ee bellard
}
837 eaa728ee bellard
838 eaa728ee bellard
#ifdef TARGET_X86_64
839 eaa728ee bellard
840 eaa728ee bellard
#define PUSHQ(sp, val)\
841 eaa728ee bellard
{\
842 eaa728ee bellard
    sp -= 8;\
843 eaa728ee bellard
    stq_kernel(sp, (val));\
844 eaa728ee bellard
}
845 eaa728ee bellard
846 eaa728ee bellard
#define POPQ(sp, val)\
847 eaa728ee bellard
{\
848 eaa728ee bellard
    val = ldq_kernel(sp);\
849 eaa728ee bellard
    sp += 8;\
850 eaa728ee bellard
}
851 eaa728ee bellard
852 eaa728ee bellard
static inline target_ulong get_rsp_from_tss(int level)
853 eaa728ee bellard
{
854 eaa728ee bellard
    int index;
855 eaa728ee bellard
856 eaa728ee bellard
#if 0
857 eaa728ee bellard
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
858 eaa728ee bellard
           env->tr.base, env->tr.limit);
859 eaa728ee bellard
#endif
860 eaa728ee bellard
861 eaa728ee bellard
    if (!(env->tr.flags & DESC_P_MASK))
862 eaa728ee bellard
        cpu_abort(env, "invalid tss");
863 eaa728ee bellard
    index = 8 * level + 4;
864 eaa728ee bellard
    if ((index + 7) > env->tr.limit)
865 eaa728ee bellard
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
866 eaa728ee bellard
    return ldq_kernel(env->tr.base + index);
867 eaa728ee bellard
}
868 eaa728ee bellard
869 eaa728ee bellard
/* 64 bit interrupt */
870 eaa728ee bellard
static void do_interrupt64(int intno, int is_int, int error_code,
871 eaa728ee bellard
                           target_ulong next_eip, int is_hw)
872 eaa728ee bellard
{
873 eaa728ee bellard
    SegmentCache *dt;
874 eaa728ee bellard
    target_ulong ptr;
875 eaa728ee bellard
    int type, dpl, selector, cpl, ist;
876 eaa728ee bellard
    int has_error_code, new_stack;
877 eaa728ee bellard
    uint32_t e1, e2, e3, ss;
878 eaa728ee bellard
    target_ulong old_eip, esp, offset;
879 eaa728ee bellard
880 eaa728ee bellard
    has_error_code = 0;
881 eaa728ee bellard
    if (!is_int && !is_hw) {
882 eaa728ee bellard
        switch(intno) {
883 eaa728ee bellard
        case 8:
884 eaa728ee bellard
        case 10:
885 eaa728ee bellard
        case 11:
886 eaa728ee bellard
        case 12:
887 eaa728ee bellard
        case 13:
888 eaa728ee bellard
        case 14:
889 eaa728ee bellard
        case 17:
890 eaa728ee bellard
            has_error_code = 1;
891 eaa728ee bellard
            break;
892 eaa728ee bellard
        }
893 eaa728ee bellard
    }
894 eaa728ee bellard
    if (is_int)
895 eaa728ee bellard
        old_eip = next_eip;
896 eaa728ee bellard
    else
897 eaa728ee bellard
        old_eip = env->eip;
898 eaa728ee bellard
899 eaa728ee bellard
    dt = &env->idt;
900 eaa728ee bellard
    if (intno * 16 + 15 > dt->limit)
901 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
902 eaa728ee bellard
    ptr = dt->base + intno * 16;
903 eaa728ee bellard
    e1 = ldl_kernel(ptr);
904 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
905 eaa728ee bellard
    e3 = ldl_kernel(ptr + 8);
906 eaa728ee bellard
    /* check gate type */
907 eaa728ee bellard
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
908 eaa728ee bellard
    switch(type) {
909 eaa728ee bellard
    case 14: /* 386 interrupt gate */
910 eaa728ee bellard
    case 15: /* 386 trap gate */
911 eaa728ee bellard
        break;
912 eaa728ee bellard
    default:
913 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
914 eaa728ee bellard
        break;
915 eaa728ee bellard
    }
916 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
917 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
918 1235fc06 ths
    /* check privilege if software int */
919 eaa728ee bellard
    if (is_int && dpl < cpl)
920 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
921 eaa728ee bellard
    /* check valid bit */
922 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
923 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
924 eaa728ee bellard
    selector = e1 >> 16;
925 eaa728ee bellard
    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
926 eaa728ee bellard
    ist = e2 & 7;
927 eaa728ee bellard
    if ((selector & 0xfffc) == 0)
928 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
929 eaa728ee bellard
930 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
931 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
932 eaa728ee bellard
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
933 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
934 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
935 eaa728ee bellard
    if (dpl > cpl)
936 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
937 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
938 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
939 eaa728ee bellard
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
940 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
941 eaa728ee bellard
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
942 eaa728ee bellard
        /* to inner privilege */
943 eaa728ee bellard
        if (ist != 0)
944 eaa728ee bellard
            esp = get_rsp_from_tss(ist + 3);
945 eaa728ee bellard
        else
946 eaa728ee bellard
            esp = get_rsp_from_tss(dpl);
947 eaa728ee bellard
        esp &= ~0xfLL; /* align stack */
948 eaa728ee bellard
        ss = 0;
949 eaa728ee bellard
        new_stack = 1;
950 eaa728ee bellard
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
951 eaa728ee bellard
        /* to same privilege */
952 eaa728ee bellard
        if (env->eflags & VM_MASK)
953 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
954 eaa728ee bellard
        new_stack = 0;
955 eaa728ee bellard
        if (ist != 0)
956 eaa728ee bellard
            esp = get_rsp_from_tss(ist + 3);
957 eaa728ee bellard
        else
958 eaa728ee bellard
            esp = ESP;
959 eaa728ee bellard
        esp &= ~0xfLL; /* align stack */
960 eaa728ee bellard
        dpl = cpl;
961 eaa728ee bellard
    } else {
962 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
963 eaa728ee bellard
        new_stack = 0; /* avoid warning */
964 eaa728ee bellard
        esp = 0; /* avoid warning */
965 eaa728ee bellard
    }
966 eaa728ee bellard
967 eaa728ee bellard
    PUSHQ(esp, env->segs[R_SS].selector);
968 eaa728ee bellard
    PUSHQ(esp, ESP);
969 eaa728ee bellard
    PUSHQ(esp, compute_eflags());
970 eaa728ee bellard
    PUSHQ(esp, env->segs[R_CS].selector);
971 eaa728ee bellard
    PUSHQ(esp, old_eip);
972 eaa728ee bellard
    if (has_error_code) {
973 eaa728ee bellard
        PUSHQ(esp, error_code);
974 eaa728ee bellard
    }
975 eaa728ee bellard
976 eaa728ee bellard
    if (new_stack) {
977 eaa728ee bellard
        ss = 0 | dpl;
978 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
979 eaa728ee bellard
    }
980 eaa728ee bellard
    ESP = esp;
981 eaa728ee bellard
982 eaa728ee bellard
    selector = (selector & ~3) | dpl;
983 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, selector,
984 eaa728ee bellard
                   get_seg_base(e1, e2),
985 eaa728ee bellard
                   get_seg_limit(e1, e2),
986 eaa728ee bellard
                   e2);
987 eaa728ee bellard
    cpu_x86_set_cpl(env, dpl);
988 eaa728ee bellard
    env->eip = offset;
989 eaa728ee bellard
990 eaa728ee bellard
    /* interrupt gate clear IF mask */
991 eaa728ee bellard
    if ((type & 1) == 0) {
992 eaa728ee bellard
        env->eflags &= ~IF_MASK;
993 eaa728ee bellard
    }
994 eaa728ee bellard
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
995 eaa728ee bellard
}
996 eaa728ee bellard
#endif
997 eaa728ee bellard
998 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
999 eaa728ee bellard
void helper_syscall(int next_eip_addend)
1000 eaa728ee bellard
{
1001 eaa728ee bellard
    env->exception_index = EXCP_SYSCALL;
1002 eaa728ee bellard
    env->exception_next_eip = env->eip + next_eip_addend;
1003 eaa728ee bellard
    cpu_loop_exit();
1004 eaa728ee bellard
}
1005 eaa728ee bellard
#else
1006 eaa728ee bellard
void helper_syscall(int next_eip_addend)
1007 eaa728ee bellard
{
1008 eaa728ee bellard
    int selector;
1009 eaa728ee bellard
1010 eaa728ee bellard
    if (!(env->efer & MSR_EFER_SCE)) {
1011 eaa728ee bellard
        raise_exception_err(EXCP06_ILLOP, 0);
1012 eaa728ee bellard
    }
1013 eaa728ee bellard
    selector = (env->star >> 32) & 0xffff;
1014 eaa728ee bellard
#ifdef TARGET_X86_64
1015 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1016 eaa728ee bellard
        int code64;
1017 eaa728ee bellard
1018 eaa728ee bellard
        ECX = env->eip + next_eip_addend;
1019 eaa728ee bellard
        env->regs[11] = compute_eflags();
1020 eaa728ee bellard
1021 eaa728ee bellard
        code64 = env->hflags & HF_CS64_MASK;
1022 eaa728ee bellard
1023 eaa728ee bellard
        cpu_x86_set_cpl(env, 0);
1024 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1025 eaa728ee bellard
                           0, 0xffffffff,
1026 eaa728ee bellard
                               DESC_G_MASK | DESC_P_MASK |
1027 eaa728ee bellard
                               DESC_S_MASK |
1028 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1029 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1030 eaa728ee bellard
                               0, 0xffffffff,
1031 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1032 eaa728ee bellard
                               DESC_S_MASK |
1033 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1034 eaa728ee bellard
        env->eflags &= ~env->fmask;
1035 eaa728ee bellard
        load_eflags(env->eflags, 0);
1036 eaa728ee bellard
        if (code64)
1037 eaa728ee bellard
            env->eip = env->lstar;
1038 eaa728ee bellard
        else
1039 eaa728ee bellard
            env->eip = env->cstar;
1040 eaa728ee bellard
    } else
1041 eaa728ee bellard
#endif
1042 eaa728ee bellard
    {
1043 eaa728ee bellard
        ECX = (uint32_t)(env->eip + next_eip_addend);
1044 eaa728ee bellard
1045 eaa728ee bellard
        cpu_x86_set_cpl(env, 0);
1046 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1047 eaa728ee bellard
                           0, 0xffffffff,
1048 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1049 eaa728ee bellard
                               DESC_S_MASK |
1050 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1051 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1052 eaa728ee bellard
                               0, 0xffffffff,
1053 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1054 eaa728ee bellard
                               DESC_S_MASK |
1055 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1056 eaa728ee bellard
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1057 eaa728ee bellard
        env->eip = (uint32_t)env->star;
1058 eaa728ee bellard
    }
1059 eaa728ee bellard
}
1060 eaa728ee bellard
#endif
1061 eaa728ee bellard
1062 eaa728ee bellard
void helper_sysret(int dflag)
1063 eaa728ee bellard
{
1064 eaa728ee bellard
    int cpl, selector;
1065 eaa728ee bellard
1066 eaa728ee bellard
    if (!(env->efer & MSR_EFER_SCE)) {
1067 eaa728ee bellard
        raise_exception_err(EXCP06_ILLOP, 0);
1068 eaa728ee bellard
    }
1069 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
1070 eaa728ee bellard
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1071 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
1072 eaa728ee bellard
    }
1073 eaa728ee bellard
    selector = (env->star >> 48) & 0xffff;
1074 eaa728ee bellard
#ifdef TARGET_X86_64
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 eaa728ee bellard
    } else
1101 eaa728ee bellard
#endif
1102 eaa728ee bellard
    {
1103 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1104 eaa728ee bellard
                               0, 0xffffffff,
1105 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1106 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1107 eaa728ee bellard
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1108 eaa728ee bellard
        env->eip = (uint32_t)ECX;
1109 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1110 eaa728ee bellard
                               0, 0xffffffff,
1111 eaa728ee bellard
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1112 eaa728ee bellard
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1113 eaa728ee bellard
                               DESC_W_MASK | DESC_A_MASK);
1114 eaa728ee bellard
        env->eflags |= IF_MASK;
1115 eaa728ee bellard
        cpu_x86_set_cpl(env, 3);
1116 eaa728ee bellard
    }
1117 eaa728ee bellard
#ifdef USE_KQEMU
1118 eaa728ee bellard
    if (kqemu_is_ok(env)) {
1119 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK)
1120 eaa728ee bellard
            CC_OP = CC_OP_EFLAGS;
1121 eaa728ee bellard
        env->exception_index = -1;
1122 eaa728ee bellard
        cpu_loop_exit();
1123 eaa728ee bellard
    }
1124 eaa728ee bellard
#endif
1125 eaa728ee bellard
}
1126 eaa728ee bellard
1127 eaa728ee bellard
/* real mode interrupt */
1128 eaa728ee bellard
static void do_interrupt_real(int intno, int is_int, int error_code,
1129 eaa728ee bellard
                              unsigned int next_eip)
1130 eaa728ee bellard
{
1131 eaa728ee bellard
    SegmentCache *dt;
1132 eaa728ee bellard
    target_ulong ptr, ssp;
1133 eaa728ee bellard
    int selector;
1134 eaa728ee bellard
    uint32_t offset, esp;
1135 eaa728ee bellard
    uint32_t old_cs, old_eip;
1136 eaa728ee bellard
1137 eaa728ee bellard
    /* real mode (simpler !) */
1138 eaa728ee bellard
    dt = &env->idt;
1139 eaa728ee bellard
    if (intno * 4 + 3 > dt->limit)
1140 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1141 eaa728ee bellard
    ptr = dt->base + intno * 4;
1142 eaa728ee bellard
    offset = lduw_kernel(ptr);
1143 eaa728ee bellard
    selector = lduw_kernel(ptr + 2);
1144 eaa728ee bellard
    esp = ESP;
1145 eaa728ee bellard
    ssp = env->segs[R_SS].base;
1146 eaa728ee bellard
    if (is_int)
1147 eaa728ee bellard
        old_eip = next_eip;
1148 eaa728ee bellard
    else
1149 eaa728ee bellard
        old_eip = env->eip;
1150 eaa728ee bellard
    old_cs = env->segs[R_CS].selector;
1151 eaa728ee bellard
    /* XXX: use SS segment size ? */
1152 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, compute_eflags());
1153 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, old_cs);
1154 eaa728ee bellard
    PUSHW(ssp, esp, 0xffff, old_eip);
1155 eaa728ee bellard
1156 eaa728ee bellard
    /* update processor state */
1157 eaa728ee bellard
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1158 eaa728ee bellard
    env->eip = offset;
1159 eaa728ee bellard
    env->segs[R_CS].selector = selector;
1160 eaa728ee bellard
    env->segs[R_CS].base = (selector << 4);
1161 eaa728ee bellard
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1162 eaa728ee bellard
}
1163 eaa728ee bellard
1164 eaa728ee bellard
/* fake user mode interrupt */
1165 eaa728ee bellard
void do_interrupt_user(int intno, int is_int, int error_code,
1166 eaa728ee bellard
                       target_ulong next_eip)
1167 eaa728ee bellard
{
1168 eaa728ee bellard
    SegmentCache *dt;
1169 eaa728ee bellard
    target_ulong ptr;
1170 eaa728ee bellard
    int dpl, cpl, shift;
1171 eaa728ee bellard
    uint32_t e2;
1172 eaa728ee bellard
1173 eaa728ee bellard
    dt = &env->idt;
1174 eaa728ee bellard
    if (env->hflags & HF_LMA_MASK) {
1175 eaa728ee bellard
        shift = 4;
1176 eaa728ee bellard
    } else {
1177 eaa728ee bellard
        shift = 3;
1178 eaa728ee bellard
    }
1179 eaa728ee bellard
    ptr = dt->base + (intno << shift);
1180 eaa728ee bellard
    e2 = ldl_kernel(ptr + 4);
1181 eaa728ee bellard
1182 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1183 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
1184 1235fc06 ths
    /* check privilege if software int */
1185 eaa728ee bellard
    if (is_int && dpl < cpl)
1186 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1187 eaa728ee bellard
1188 eaa728ee bellard
    /* Since we emulate only user space, we cannot do more than
1189 eaa728ee bellard
       exiting the emulation with the suitable exception and error
1190 eaa728ee bellard
       code */
1191 eaa728ee bellard
    if (is_int)
1192 eaa728ee bellard
        EIP = next_eip;
1193 eaa728ee bellard
}
1194 eaa728ee bellard
1195 eaa728ee bellard
/*
1196 eaa728ee bellard
 * Begin execution of an interruption. is_int is TRUE if coming from
1197 eaa728ee bellard
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1198 eaa728ee bellard
 * instruction. It is only relevant if is_int is TRUE.
1199 eaa728ee bellard
 */
1200 eaa728ee bellard
void do_interrupt(int intno, int is_int, int error_code,
1201 eaa728ee bellard
                  target_ulong next_eip, int is_hw)
1202 eaa728ee bellard
{
1203 eaa728ee bellard
    if (loglevel & CPU_LOG_INT) {
1204 eaa728ee bellard
        if ((env->cr[0] & CR0_PE_MASK)) {
1205 eaa728ee bellard
            static int count;
1206 eaa728ee bellard
            fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1207 eaa728ee bellard
                    count, intno, error_code, is_int,
1208 eaa728ee bellard
                    env->hflags & HF_CPL_MASK,
1209 eaa728ee bellard
                    env->segs[R_CS].selector, EIP,
1210 eaa728ee bellard
                    (int)env->segs[R_CS].base + EIP,
1211 eaa728ee bellard
                    env->segs[R_SS].selector, ESP);
1212 eaa728ee bellard
            if (intno == 0x0e) {
1213 eaa728ee bellard
                fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1214 eaa728ee bellard
            } else {
1215 eaa728ee bellard
                fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1216 eaa728ee bellard
            }
1217 eaa728ee bellard
            fprintf(logfile, "\n");
1218 eaa728ee bellard
            cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1219 eaa728ee bellard
#if 0
1220 eaa728ee bellard
            {
1221 eaa728ee bellard
                int i;
1222 eaa728ee bellard
                uint8_t *ptr;
1223 eaa728ee bellard
                fprintf(logfile, "       code=");
1224 eaa728ee bellard
                ptr = env->segs[R_CS].base + env->eip;
1225 eaa728ee bellard
                for(i = 0; i < 16; i++) {
1226 eaa728ee bellard
                    fprintf(logfile, " %02x", ldub(ptr + i));
1227 eaa728ee bellard
                }
1228 eaa728ee bellard
                fprintf(logfile, "\n");
1229 eaa728ee bellard
            }
1230 eaa728ee bellard
#endif
1231 eaa728ee bellard
            count++;
1232 eaa728ee bellard
        }
1233 eaa728ee bellard
    }
1234 eaa728ee bellard
    if (env->cr[0] & CR0_PE_MASK) {
1235 eb38c52c blueswir1
#ifdef TARGET_X86_64
1236 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
1237 eaa728ee bellard
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1238 eaa728ee bellard
        } else
1239 eaa728ee bellard
#endif
1240 eaa728ee bellard
        {
1241 eaa728ee bellard
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1242 eaa728ee bellard
        }
1243 eaa728ee bellard
    } else {
1244 eaa728ee bellard
        do_interrupt_real(intno, is_int, error_code, next_eip);
1245 eaa728ee bellard
    }
1246 eaa728ee bellard
}
1247 eaa728ee bellard
1248 eaa728ee bellard
/*
1249 eaa728ee bellard
 * Check nested exceptions and change to double or triple fault if
1250 eaa728ee bellard
 * needed. It should only be called, if this is not an interrupt.
1251 eaa728ee bellard
 * Returns the new exception number.
1252 eaa728ee bellard
 */
1253 eaa728ee bellard
static int check_exception(int intno, int *error_code)
1254 eaa728ee bellard
{
1255 eaa728ee bellard
    int first_contributory = env->old_exception == 0 ||
1256 eaa728ee bellard
                              (env->old_exception >= 10 &&
1257 eaa728ee bellard
                               env->old_exception <= 13);
1258 eaa728ee bellard
    int second_contributory = intno == 0 ||
1259 eaa728ee bellard
                               (intno >= 10 && intno <= 13);
1260 eaa728ee bellard
1261 eaa728ee bellard
    if (loglevel & CPU_LOG_INT)
1262 eaa728ee bellard
        fprintf(logfile, "check_exception old: 0x%x new 0x%x\n",
1263 eaa728ee bellard
                env->old_exception, intno);
1264 eaa728ee bellard
1265 eaa728ee bellard
    if (env->old_exception == EXCP08_DBLE)
1266 eaa728ee bellard
        cpu_abort(env, "triple fault");
1267 eaa728ee bellard
1268 eaa728ee bellard
    if ((first_contributory && second_contributory)
1269 eaa728ee bellard
        || (env->old_exception == EXCP0E_PAGE &&
1270 eaa728ee bellard
            (second_contributory || (intno == EXCP0E_PAGE)))) {
1271 eaa728ee bellard
        intno = EXCP08_DBLE;
1272 eaa728ee bellard
        *error_code = 0;
1273 eaa728ee bellard
    }
1274 eaa728ee bellard
1275 eaa728ee bellard
    if (second_contributory || (intno == EXCP0E_PAGE) ||
1276 eaa728ee bellard
        (intno == EXCP08_DBLE))
1277 eaa728ee bellard
        env->old_exception = intno;
1278 eaa728ee bellard
1279 eaa728ee bellard
    return intno;
1280 eaa728ee bellard
}
1281 eaa728ee bellard
1282 eaa728ee bellard
/*
1283 eaa728ee bellard
 * Signal an interruption. It is executed in the main CPU loop.
1284 eaa728ee bellard
 * is_int is TRUE if coming from the int instruction. next_eip is the
1285 eaa728ee bellard
 * EIP value AFTER the interrupt instruction. It is only relevant if
1286 eaa728ee bellard
 * is_int is TRUE.
1287 eaa728ee bellard
 */
1288 eaa728ee bellard
void raise_interrupt(int intno, int is_int, int error_code,
1289 eaa728ee bellard
                     int next_eip_addend)
1290 eaa728ee bellard
{
1291 eaa728ee bellard
    if (!is_int) {
1292 eaa728ee bellard
        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1293 eaa728ee bellard
        intno = check_exception(intno, &error_code);
1294 872929aa bellard
    } else {
1295 872929aa bellard
        helper_svm_check_intercept_param(SVM_EXIT_SWINT, 0);
1296 eaa728ee bellard
    }
1297 eaa728ee bellard
1298 eaa728ee bellard
    env->exception_index = intno;
1299 eaa728ee bellard
    env->error_code = error_code;
1300 eaa728ee bellard
    env->exception_is_int = is_int;
1301 eaa728ee bellard
    env->exception_next_eip = env->eip + next_eip_addend;
1302 eaa728ee bellard
    cpu_loop_exit();
1303 eaa728ee bellard
}
1304 eaa728ee bellard
1305 eaa728ee bellard
/* shortcuts to generate exceptions */
1306 eaa728ee bellard
1307 eaa728ee bellard
void (raise_exception_err)(int exception_index, int error_code)
1308 eaa728ee bellard
{
1309 eaa728ee bellard
    raise_interrupt(exception_index, 0, error_code, 0);
1310 eaa728ee bellard
}
1311 eaa728ee bellard
1312 eaa728ee bellard
void raise_exception(int exception_index)
1313 eaa728ee bellard
{
1314 eaa728ee bellard
    raise_interrupt(exception_index, 0, 0, 0);
1315 eaa728ee bellard
}
1316 eaa728ee bellard
1317 eaa728ee bellard
/* SMM support */
1318 eaa728ee bellard
1319 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
1320 eaa728ee bellard
1321 eaa728ee bellard
void do_smm_enter(void)
1322 eaa728ee bellard
{
1323 eaa728ee bellard
}
1324 eaa728ee bellard
1325 eaa728ee bellard
void helper_rsm(void)
1326 eaa728ee bellard
{
1327 eaa728ee bellard
}
1328 eaa728ee bellard
1329 eaa728ee bellard
#else
1330 eaa728ee bellard
1331 eaa728ee bellard
#ifdef TARGET_X86_64
1332 eaa728ee bellard
#define SMM_REVISION_ID 0x00020064
1333 eaa728ee bellard
#else
1334 eaa728ee bellard
#define SMM_REVISION_ID 0x00020000
1335 eaa728ee bellard
#endif
1336 eaa728ee bellard
1337 eaa728ee bellard
void do_smm_enter(void)
1338 eaa728ee bellard
{
1339 eaa728ee bellard
    target_ulong sm_state;
1340 eaa728ee bellard
    SegmentCache *dt;
1341 eaa728ee bellard
    int i, offset;
1342 eaa728ee bellard
1343 eaa728ee bellard
    if (loglevel & CPU_LOG_INT) {
1344 eaa728ee bellard
        fprintf(logfile, "SMM: enter\n");
1345 eaa728ee bellard
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1346 eaa728ee bellard
    }
1347 eaa728ee bellard
1348 eaa728ee bellard
    env->hflags |= HF_SMM_MASK;
1349 eaa728ee bellard
    cpu_smm_update(env);
1350 eaa728ee bellard
1351 eaa728ee bellard
    sm_state = env->smbase + 0x8000;
1352 eaa728ee bellard
1353 eaa728ee bellard
#ifdef TARGET_X86_64
1354 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1355 eaa728ee bellard
        dt = &env->segs[i];
1356 eaa728ee bellard
        offset = 0x7e00 + i * 16;
1357 eaa728ee bellard
        stw_phys(sm_state + offset, dt->selector);
1358 eaa728ee bellard
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1359 eaa728ee bellard
        stl_phys(sm_state + offset + 4, dt->limit);
1360 eaa728ee bellard
        stq_phys(sm_state + offset + 8, dt->base);
1361 eaa728ee bellard
    }
1362 eaa728ee bellard
1363 eaa728ee bellard
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1364 eaa728ee bellard
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1365 eaa728ee bellard
1366 eaa728ee bellard
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1367 eaa728ee bellard
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1368 eaa728ee bellard
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1369 eaa728ee bellard
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1370 eaa728ee bellard
1371 eaa728ee bellard
    stq_phys(sm_state + 0x7e88, env->idt.base);
1372 eaa728ee bellard
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1373 eaa728ee bellard
1374 eaa728ee bellard
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1375 eaa728ee bellard
    stq_phys(sm_state + 0x7e98, env->tr.base);
1376 eaa728ee bellard
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1377 eaa728ee bellard
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1378 eaa728ee bellard
1379 eaa728ee bellard
    stq_phys(sm_state + 0x7ed0, env->efer);
1380 eaa728ee bellard
1381 eaa728ee bellard
    stq_phys(sm_state + 0x7ff8, EAX);
1382 eaa728ee bellard
    stq_phys(sm_state + 0x7ff0, ECX);
1383 eaa728ee bellard
    stq_phys(sm_state + 0x7fe8, EDX);
1384 eaa728ee bellard
    stq_phys(sm_state + 0x7fe0, EBX);
1385 eaa728ee bellard
    stq_phys(sm_state + 0x7fd8, ESP);
1386 eaa728ee bellard
    stq_phys(sm_state + 0x7fd0, EBP);
1387 eaa728ee bellard
    stq_phys(sm_state + 0x7fc8, ESI);
1388 eaa728ee bellard
    stq_phys(sm_state + 0x7fc0, EDI);
1389 eaa728ee bellard
    for(i = 8; i < 16; i++)
1390 eaa728ee bellard
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1391 eaa728ee bellard
    stq_phys(sm_state + 0x7f78, env->eip);
1392 eaa728ee bellard
    stl_phys(sm_state + 0x7f70, compute_eflags());
1393 eaa728ee bellard
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1394 eaa728ee bellard
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1395 eaa728ee bellard
1396 eaa728ee bellard
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1397 eaa728ee bellard
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1398 eaa728ee bellard
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1399 eaa728ee bellard
1400 eaa728ee bellard
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1401 eaa728ee bellard
    stl_phys(sm_state + 0x7f00, env->smbase);
1402 eaa728ee bellard
#else
1403 eaa728ee bellard
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1404 eaa728ee bellard
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1405 eaa728ee bellard
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1406 eaa728ee bellard
    stl_phys(sm_state + 0x7ff0, env->eip);
1407 eaa728ee bellard
    stl_phys(sm_state + 0x7fec, EDI);
1408 eaa728ee bellard
    stl_phys(sm_state + 0x7fe8, ESI);
1409 eaa728ee bellard
    stl_phys(sm_state + 0x7fe4, EBP);
1410 eaa728ee bellard
    stl_phys(sm_state + 0x7fe0, ESP);
1411 eaa728ee bellard
    stl_phys(sm_state + 0x7fdc, EBX);
1412 eaa728ee bellard
    stl_phys(sm_state + 0x7fd8, EDX);
1413 eaa728ee bellard
    stl_phys(sm_state + 0x7fd4, ECX);
1414 eaa728ee bellard
    stl_phys(sm_state + 0x7fd0, EAX);
1415 eaa728ee bellard
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1416 eaa728ee bellard
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1417 eaa728ee bellard
1418 eaa728ee bellard
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1419 eaa728ee bellard
    stl_phys(sm_state + 0x7f64, env->tr.base);
1420 eaa728ee bellard
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1421 eaa728ee bellard
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1422 eaa728ee bellard
1423 eaa728ee bellard
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1424 eaa728ee bellard
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1425 eaa728ee bellard
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1426 eaa728ee bellard
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1427 eaa728ee bellard
1428 eaa728ee bellard
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1429 eaa728ee bellard
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1430 eaa728ee bellard
1431 eaa728ee bellard
    stl_phys(sm_state + 0x7f58, env->idt.base);
1432 eaa728ee bellard
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1433 eaa728ee bellard
1434 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1435 eaa728ee bellard
        dt = &env->segs[i];
1436 eaa728ee bellard
        if (i < 3)
1437 eaa728ee bellard
            offset = 0x7f84 + i * 12;
1438 eaa728ee bellard
        else
1439 eaa728ee bellard
            offset = 0x7f2c + (i - 3) * 12;
1440 eaa728ee bellard
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1441 eaa728ee bellard
        stl_phys(sm_state + offset + 8, dt->base);
1442 eaa728ee bellard
        stl_phys(sm_state + offset + 4, dt->limit);
1443 eaa728ee bellard
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1444 eaa728ee bellard
    }
1445 eaa728ee bellard
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1446 eaa728ee bellard
1447 eaa728ee bellard
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1448 eaa728ee bellard
    stl_phys(sm_state + 0x7ef8, env->smbase);
1449 eaa728ee bellard
#endif
1450 eaa728ee bellard
    /* init SMM cpu state */
1451 eaa728ee bellard
1452 eaa728ee bellard
#ifdef TARGET_X86_64
1453 5efc27bb bellard
    cpu_load_efer(env, 0);
1454 eaa728ee bellard
#endif
1455 eaa728ee bellard
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1456 eaa728ee bellard
    env->eip = 0x00008000;
1457 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1458 eaa728ee bellard
                           0xffffffff, 0);
1459 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1460 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1461 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1462 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1463 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1464 eaa728ee bellard
1465 eaa728ee bellard
    cpu_x86_update_cr0(env,
1466 eaa728ee bellard
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1467 eaa728ee bellard
    cpu_x86_update_cr4(env, 0);
1468 eaa728ee bellard
    env->dr[7] = 0x00000400;
1469 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
1470 eaa728ee bellard
}
1471 eaa728ee bellard
1472 eaa728ee bellard
void helper_rsm(void)
1473 eaa728ee bellard
{
1474 eaa728ee bellard
    target_ulong sm_state;
1475 eaa728ee bellard
    int i, offset;
1476 eaa728ee bellard
    uint32_t val;
1477 eaa728ee bellard
1478 eaa728ee bellard
    sm_state = env->smbase + 0x8000;
1479 eaa728ee bellard
#ifdef TARGET_X86_64
1480 5efc27bb bellard
    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
1481 eaa728ee bellard
1482 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1483 eaa728ee bellard
        offset = 0x7e00 + i * 16;
1484 eaa728ee bellard
        cpu_x86_load_seg_cache(env, i,
1485 eaa728ee bellard
                               lduw_phys(sm_state + offset),
1486 eaa728ee bellard
                               ldq_phys(sm_state + offset + 8),
1487 eaa728ee bellard
                               ldl_phys(sm_state + offset + 4),
1488 eaa728ee bellard
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1489 eaa728ee bellard
    }
1490 eaa728ee bellard
1491 eaa728ee bellard
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1492 eaa728ee bellard
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1493 eaa728ee bellard
1494 eaa728ee bellard
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1495 eaa728ee bellard
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1496 eaa728ee bellard
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1497 eaa728ee bellard
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1498 eaa728ee bellard
1499 eaa728ee bellard
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1500 eaa728ee bellard
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1501 eaa728ee bellard
1502 eaa728ee bellard
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1503 eaa728ee bellard
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1504 eaa728ee bellard
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1505 eaa728ee bellard
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1506 eaa728ee bellard
1507 eaa728ee bellard
    EAX = ldq_phys(sm_state + 0x7ff8);
1508 eaa728ee bellard
    ECX = ldq_phys(sm_state + 0x7ff0);
1509 eaa728ee bellard
    EDX = ldq_phys(sm_state + 0x7fe8);
1510 eaa728ee bellard
    EBX = ldq_phys(sm_state + 0x7fe0);
1511 eaa728ee bellard
    ESP = ldq_phys(sm_state + 0x7fd8);
1512 eaa728ee bellard
    EBP = ldq_phys(sm_state + 0x7fd0);
1513 eaa728ee bellard
    ESI = ldq_phys(sm_state + 0x7fc8);
1514 eaa728ee bellard
    EDI = ldq_phys(sm_state + 0x7fc0);
1515 eaa728ee bellard
    for(i = 8; i < 16; i++)
1516 eaa728ee bellard
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1517 eaa728ee bellard
    env->eip = ldq_phys(sm_state + 0x7f78);
1518 eaa728ee bellard
    load_eflags(ldl_phys(sm_state + 0x7f70),
1519 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1520 eaa728ee bellard
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1521 eaa728ee bellard
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1522 eaa728ee bellard
1523 eaa728ee bellard
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1524 eaa728ee bellard
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1525 eaa728ee bellard
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1526 eaa728ee bellard
1527 eaa728ee bellard
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1528 eaa728ee bellard
    if (val & 0x20000) {
1529 eaa728ee bellard
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1530 eaa728ee bellard
    }
1531 eaa728ee bellard
#else
1532 eaa728ee bellard
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1533 eaa728ee bellard
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1534 eaa728ee bellard
    load_eflags(ldl_phys(sm_state + 0x7ff4),
1535 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1536 eaa728ee bellard
    env->eip = ldl_phys(sm_state + 0x7ff0);
1537 eaa728ee bellard
    EDI = ldl_phys(sm_state + 0x7fec);
1538 eaa728ee bellard
    ESI = ldl_phys(sm_state + 0x7fe8);
1539 eaa728ee bellard
    EBP = ldl_phys(sm_state + 0x7fe4);
1540 eaa728ee bellard
    ESP = ldl_phys(sm_state + 0x7fe0);
1541 eaa728ee bellard
    EBX = ldl_phys(sm_state + 0x7fdc);
1542 eaa728ee bellard
    EDX = ldl_phys(sm_state + 0x7fd8);
1543 eaa728ee bellard
    ECX = ldl_phys(sm_state + 0x7fd4);
1544 eaa728ee bellard
    EAX = ldl_phys(sm_state + 0x7fd0);
1545 eaa728ee bellard
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1546 eaa728ee bellard
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1547 eaa728ee bellard
1548 eaa728ee bellard
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1549 eaa728ee bellard
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1550 eaa728ee bellard
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1551 eaa728ee bellard
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1552 eaa728ee bellard
1553 eaa728ee bellard
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1554 eaa728ee bellard
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1555 eaa728ee bellard
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1556 eaa728ee bellard
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1557 eaa728ee bellard
1558 eaa728ee bellard
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1559 eaa728ee bellard
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1560 eaa728ee bellard
1561 eaa728ee bellard
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1562 eaa728ee bellard
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1563 eaa728ee bellard
1564 eaa728ee bellard
    for(i = 0; i < 6; i++) {
1565 eaa728ee bellard
        if (i < 3)
1566 eaa728ee bellard
            offset = 0x7f84 + i * 12;
1567 eaa728ee bellard
        else
1568 eaa728ee bellard
            offset = 0x7f2c + (i - 3) * 12;
1569 eaa728ee bellard
        cpu_x86_load_seg_cache(env, i,
1570 eaa728ee bellard
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1571 eaa728ee bellard
                               ldl_phys(sm_state + offset + 8),
1572 eaa728ee bellard
                               ldl_phys(sm_state + offset + 4),
1573 eaa728ee bellard
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1574 eaa728ee bellard
    }
1575 eaa728ee bellard
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1576 eaa728ee bellard
1577 eaa728ee bellard
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1578 eaa728ee bellard
    if (val & 0x20000) {
1579 eaa728ee bellard
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1580 eaa728ee bellard
    }
1581 eaa728ee bellard
#endif
1582 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
1583 eaa728ee bellard
    env->hflags &= ~HF_SMM_MASK;
1584 eaa728ee bellard
    cpu_smm_update(env);
1585 eaa728ee bellard
1586 eaa728ee bellard
    if (loglevel & CPU_LOG_INT) {
1587 eaa728ee bellard
        fprintf(logfile, "SMM: after RSM\n");
1588 eaa728ee bellard
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1589 eaa728ee bellard
    }
1590 eaa728ee bellard
}
1591 eaa728ee bellard
1592 eaa728ee bellard
#endif /* !CONFIG_USER_ONLY */
1593 eaa728ee bellard
1594 eaa728ee bellard
1595 eaa728ee bellard
/* division, flags are undefined */
1596 eaa728ee bellard
1597 eaa728ee bellard
void helper_divb_AL(target_ulong t0)
1598 eaa728ee bellard
{
1599 eaa728ee bellard
    unsigned int num, den, q, r;
1600 eaa728ee bellard
1601 eaa728ee bellard
    num = (EAX & 0xffff);
1602 eaa728ee bellard
    den = (t0 & 0xff);
1603 eaa728ee bellard
    if (den == 0) {
1604 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1605 eaa728ee bellard
    }
1606 eaa728ee bellard
    q = (num / den);
1607 eaa728ee bellard
    if (q > 0xff)
1608 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1609 eaa728ee bellard
    q &= 0xff;
1610 eaa728ee bellard
    r = (num % den) & 0xff;
1611 eaa728ee bellard
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1612 eaa728ee bellard
}
1613 eaa728ee bellard
1614 eaa728ee bellard
void helper_idivb_AL(target_ulong t0)
1615 eaa728ee bellard
{
1616 eaa728ee bellard
    int num, den, q, r;
1617 eaa728ee bellard
1618 eaa728ee bellard
    num = (int16_t)EAX;
1619 eaa728ee bellard
    den = (int8_t)t0;
1620 eaa728ee bellard
    if (den == 0) {
1621 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1622 eaa728ee bellard
    }
1623 eaa728ee bellard
    q = (num / den);
1624 eaa728ee bellard
    if (q != (int8_t)q)
1625 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1626 eaa728ee bellard
    q &= 0xff;
1627 eaa728ee bellard
    r = (num % den) & 0xff;
1628 eaa728ee bellard
    EAX = (EAX & ~0xffff) | (r << 8) | q;
1629 eaa728ee bellard
}
1630 eaa728ee bellard
1631 eaa728ee bellard
void helper_divw_AX(target_ulong t0)
1632 eaa728ee bellard
{
1633 eaa728ee bellard
    unsigned int num, den, q, r;
1634 eaa728ee bellard
1635 eaa728ee bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1636 eaa728ee bellard
    den = (t0 & 0xffff);
1637 eaa728ee bellard
    if (den == 0) {
1638 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1639 eaa728ee bellard
    }
1640 eaa728ee bellard
    q = (num / den);
1641 eaa728ee bellard
    if (q > 0xffff)
1642 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1643 eaa728ee bellard
    q &= 0xffff;
1644 eaa728ee bellard
    r = (num % den) & 0xffff;
1645 eaa728ee bellard
    EAX = (EAX & ~0xffff) | q;
1646 eaa728ee bellard
    EDX = (EDX & ~0xffff) | r;
1647 eaa728ee bellard
}
1648 eaa728ee bellard
1649 eaa728ee bellard
void helper_idivw_AX(target_ulong t0)
1650 eaa728ee bellard
{
1651 eaa728ee bellard
    int num, den, q, r;
1652 eaa728ee bellard
1653 eaa728ee bellard
    num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1654 eaa728ee bellard
    den = (int16_t)t0;
1655 eaa728ee bellard
    if (den == 0) {
1656 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1657 eaa728ee bellard
    }
1658 eaa728ee bellard
    q = (num / den);
1659 eaa728ee bellard
    if (q != (int16_t)q)
1660 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1661 eaa728ee bellard
    q &= 0xffff;
1662 eaa728ee bellard
    r = (num % den) & 0xffff;
1663 eaa728ee bellard
    EAX = (EAX & ~0xffff) | q;
1664 eaa728ee bellard
    EDX = (EDX & ~0xffff) | r;
1665 eaa728ee bellard
}
1666 eaa728ee bellard
1667 eaa728ee bellard
void helper_divl_EAX(target_ulong t0)
1668 eaa728ee bellard
{
1669 eaa728ee bellard
    unsigned int den, r;
1670 eaa728ee bellard
    uint64_t num, q;
1671 eaa728ee bellard
1672 eaa728ee bellard
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1673 eaa728ee bellard
    den = t0;
1674 eaa728ee bellard
    if (den == 0) {
1675 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1676 eaa728ee bellard
    }
1677 eaa728ee bellard
    q = (num / den);
1678 eaa728ee bellard
    r = (num % den);
1679 eaa728ee bellard
    if (q > 0xffffffff)
1680 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1681 eaa728ee bellard
    EAX = (uint32_t)q;
1682 eaa728ee bellard
    EDX = (uint32_t)r;
1683 eaa728ee bellard
}
1684 eaa728ee bellard
1685 eaa728ee bellard
void helper_idivl_EAX(target_ulong t0)
1686 eaa728ee bellard
{
1687 eaa728ee bellard
    int den, r;
1688 eaa728ee bellard
    int64_t num, q;
1689 eaa728ee bellard
1690 eaa728ee bellard
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1691 eaa728ee bellard
    den = t0;
1692 eaa728ee bellard
    if (den == 0) {
1693 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1694 eaa728ee bellard
    }
1695 eaa728ee bellard
    q = (num / den);
1696 eaa728ee bellard
    r = (num % den);
1697 eaa728ee bellard
    if (q != (int32_t)q)
1698 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
1699 eaa728ee bellard
    EAX = (uint32_t)q;
1700 eaa728ee bellard
    EDX = (uint32_t)r;
1701 eaa728ee bellard
}
1702 eaa728ee bellard
1703 eaa728ee bellard
/* bcd */
1704 eaa728ee bellard
1705 eaa728ee bellard
/* XXX: exception */
1706 eaa728ee bellard
void helper_aam(int base)
1707 eaa728ee bellard
{
1708 eaa728ee bellard
    int al, ah;
1709 eaa728ee bellard
    al = EAX & 0xff;
1710 eaa728ee bellard
    ah = al / base;
1711 eaa728ee bellard
    al = al % base;
1712 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1713 eaa728ee bellard
    CC_DST = al;
1714 eaa728ee bellard
}
1715 eaa728ee bellard
1716 eaa728ee bellard
void helper_aad(int base)
1717 eaa728ee bellard
{
1718 eaa728ee bellard
    int al, ah;
1719 eaa728ee bellard
    al = EAX & 0xff;
1720 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1721 eaa728ee bellard
    al = ((ah * base) + al) & 0xff;
1722 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al;
1723 eaa728ee bellard
    CC_DST = al;
1724 eaa728ee bellard
}
1725 eaa728ee bellard
1726 eaa728ee bellard
void helper_aaa(void)
1727 eaa728ee bellard
{
1728 eaa728ee bellard
    int icarry;
1729 eaa728ee bellard
    int al, ah, af;
1730 eaa728ee bellard
    int eflags;
1731 eaa728ee bellard
1732 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1733 eaa728ee bellard
    af = eflags & CC_A;
1734 eaa728ee bellard
    al = EAX & 0xff;
1735 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1736 eaa728ee bellard
1737 eaa728ee bellard
    icarry = (al > 0xf9);
1738 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1739 eaa728ee bellard
        al = (al + 6) & 0x0f;
1740 eaa728ee bellard
        ah = (ah + 1 + icarry) & 0xff;
1741 eaa728ee bellard
        eflags |= CC_C | CC_A;
1742 eaa728ee bellard
    } else {
1743 eaa728ee bellard
        eflags &= ~(CC_C | CC_A);
1744 eaa728ee bellard
        al &= 0x0f;
1745 eaa728ee bellard
    }
1746 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1747 eaa728ee bellard
    CC_SRC = eflags;
1748 eaa728ee bellard
    FORCE_RET();
1749 eaa728ee bellard
}
1750 eaa728ee bellard
1751 eaa728ee bellard
void helper_aas(void)
1752 eaa728ee bellard
{
1753 eaa728ee bellard
    int icarry;
1754 eaa728ee bellard
    int al, ah, af;
1755 eaa728ee bellard
    int eflags;
1756 eaa728ee bellard
1757 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1758 eaa728ee bellard
    af = eflags & CC_A;
1759 eaa728ee bellard
    al = EAX & 0xff;
1760 eaa728ee bellard
    ah = (EAX >> 8) & 0xff;
1761 eaa728ee bellard
1762 eaa728ee bellard
    icarry = (al < 6);
1763 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1764 eaa728ee bellard
        al = (al - 6) & 0x0f;
1765 eaa728ee bellard
        ah = (ah - 1 - icarry) & 0xff;
1766 eaa728ee bellard
        eflags |= CC_C | CC_A;
1767 eaa728ee bellard
    } else {
1768 eaa728ee bellard
        eflags &= ~(CC_C | CC_A);
1769 eaa728ee bellard
        al &= 0x0f;
1770 eaa728ee bellard
    }
1771 eaa728ee bellard
    EAX = (EAX & ~0xffff) | al | (ah << 8);
1772 eaa728ee bellard
    CC_SRC = eflags;
1773 eaa728ee bellard
    FORCE_RET();
1774 eaa728ee bellard
}
1775 eaa728ee bellard
1776 eaa728ee bellard
void helper_daa(void)
1777 eaa728ee bellard
{
1778 eaa728ee bellard
    int al, af, cf;
1779 eaa728ee bellard
    int eflags;
1780 eaa728ee bellard
1781 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1782 eaa728ee bellard
    cf = eflags & CC_C;
1783 eaa728ee bellard
    af = eflags & CC_A;
1784 eaa728ee bellard
    al = EAX & 0xff;
1785 eaa728ee bellard
1786 eaa728ee bellard
    eflags = 0;
1787 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1788 eaa728ee bellard
        al = (al + 6) & 0xff;
1789 eaa728ee bellard
        eflags |= CC_A;
1790 eaa728ee bellard
    }
1791 eaa728ee bellard
    if ((al > 0x9f) || cf) {
1792 eaa728ee bellard
        al = (al + 0x60) & 0xff;
1793 eaa728ee bellard
        eflags |= CC_C;
1794 eaa728ee bellard
    }
1795 eaa728ee bellard
    EAX = (EAX & ~0xff) | al;
1796 eaa728ee bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1797 eaa728ee bellard
    eflags |= (al == 0) << 6; /* zf */
1798 eaa728ee bellard
    eflags |= parity_table[al]; /* pf */
1799 eaa728ee bellard
    eflags |= (al & 0x80); /* sf */
1800 eaa728ee bellard
    CC_SRC = eflags;
1801 eaa728ee bellard
    FORCE_RET();
1802 eaa728ee bellard
}
1803 eaa728ee bellard
1804 eaa728ee bellard
void helper_das(void)
1805 eaa728ee bellard
{
1806 eaa728ee bellard
    int al, al1, af, cf;
1807 eaa728ee bellard
    int eflags;
1808 eaa728ee bellard
1809 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1810 eaa728ee bellard
    cf = eflags & CC_C;
1811 eaa728ee bellard
    af = eflags & CC_A;
1812 eaa728ee bellard
    al = EAX & 0xff;
1813 eaa728ee bellard
1814 eaa728ee bellard
    eflags = 0;
1815 eaa728ee bellard
    al1 = al;
1816 eaa728ee bellard
    if (((al & 0x0f) > 9 ) || af) {
1817 eaa728ee bellard
        eflags |= CC_A;
1818 eaa728ee bellard
        if (al < 6 || cf)
1819 eaa728ee bellard
            eflags |= CC_C;
1820 eaa728ee bellard
        al = (al - 6) & 0xff;
1821 eaa728ee bellard
    }
1822 eaa728ee bellard
    if ((al1 > 0x99) || cf) {
1823 eaa728ee bellard
        al = (al - 0x60) & 0xff;
1824 eaa728ee bellard
        eflags |= CC_C;
1825 eaa728ee bellard
    }
1826 eaa728ee bellard
    EAX = (EAX & ~0xff) | al;
1827 eaa728ee bellard
    /* well, speed is not an issue here, so we compute the flags by hand */
1828 eaa728ee bellard
    eflags |= (al == 0) << 6; /* zf */
1829 eaa728ee bellard
    eflags |= parity_table[al]; /* pf */
1830 eaa728ee bellard
    eflags |= (al & 0x80); /* sf */
1831 eaa728ee bellard
    CC_SRC = eflags;
1832 eaa728ee bellard
    FORCE_RET();
1833 eaa728ee bellard
}
1834 eaa728ee bellard
1835 eaa728ee bellard
void helper_into(int next_eip_addend)
1836 eaa728ee bellard
{
1837 eaa728ee bellard
    int eflags;
1838 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1839 eaa728ee bellard
    if (eflags & CC_O) {
1840 eaa728ee bellard
        raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1841 eaa728ee bellard
    }
1842 eaa728ee bellard
}
1843 eaa728ee bellard
1844 eaa728ee bellard
void helper_cmpxchg8b(target_ulong a0)
1845 eaa728ee bellard
{
1846 eaa728ee bellard
    uint64_t d;
1847 eaa728ee bellard
    int eflags;
1848 eaa728ee bellard
1849 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1850 eaa728ee bellard
    d = ldq(a0);
1851 eaa728ee bellard
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1852 eaa728ee bellard
        stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1853 eaa728ee bellard
        eflags |= CC_Z;
1854 eaa728ee bellard
    } else {
1855 278ed7c3 bellard
        /* always do the store */
1856 278ed7c3 bellard
        stq(a0, d); 
1857 eaa728ee bellard
        EDX = (uint32_t)(d >> 32);
1858 eaa728ee bellard
        EAX = (uint32_t)d;
1859 eaa728ee bellard
        eflags &= ~CC_Z;
1860 eaa728ee bellard
    }
1861 eaa728ee bellard
    CC_SRC = eflags;
1862 eaa728ee bellard
}
1863 eaa728ee bellard
1864 eaa728ee bellard
#ifdef TARGET_X86_64
1865 eaa728ee bellard
void helper_cmpxchg16b(target_ulong a0)
1866 eaa728ee bellard
{
1867 eaa728ee bellard
    uint64_t d0, d1;
1868 eaa728ee bellard
    int eflags;
1869 eaa728ee bellard
1870 278ed7c3 bellard
    if ((a0 & 0xf) != 0)
1871 278ed7c3 bellard
        raise_exception(EXCP0D_GPF);
1872 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
1873 eaa728ee bellard
    d0 = ldq(a0);
1874 eaa728ee bellard
    d1 = ldq(a0 + 8);
1875 eaa728ee bellard
    if (d0 == EAX && d1 == EDX) {
1876 eaa728ee bellard
        stq(a0, EBX);
1877 eaa728ee bellard
        stq(a0 + 8, ECX);
1878 eaa728ee bellard
        eflags |= CC_Z;
1879 eaa728ee bellard
    } else {
1880 278ed7c3 bellard
        /* always do the store */
1881 278ed7c3 bellard
        stq(a0, d0); 
1882 278ed7c3 bellard
        stq(a0 + 8, d1); 
1883 eaa728ee bellard
        EDX = d1;
1884 eaa728ee bellard
        EAX = d0;
1885 eaa728ee bellard
        eflags &= ~CC_Z;
1886 eaa728ee bellard
    }
1887 eaa728ee bellard
    CC_SRC = eflags;
1888 eaa728ee bellard
}
1889 eaa728ee bellard
#endif
1890 eaa728ee bellard
1891 eaa728ee bellard
void helper_single_step(void)
1892 eaa728ee bellard
{
1893 01df040b aliguori
#ifndef CONFIG_USER_ONLY
1894 01df040b aliguori
    check_hw_breakpoints(env, 1);
1895 01df040b aliguori
    env->dr[6] |= DR6_BS;
1896 01df040b aliguori
#endif
1897 01df040b aliguori
    raise_exception(EXCP01_DB);
1898 eaa728ee bellard
}
1899 eaa728ee bellard
1900 eaa728ee bellard
void helper_cpuid(void)
1901 eaa728ee bellard
{
1902 6fd805e1 aliguori
    uint32_t eax, ebx, ecx, edx;
1903 eaa728ee bellard
1904 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1905 e737b32a balrog
1906 6fd805e1 aliguori
    cpu_x86_cpuid(env, (uint32_t)EAX, &eax, &ebx, &ecx, &edx);
1907 6fd805e1 aliguori
    EAX = eax;
1908 6fd805e1 aliguori
    EBX = ebx;
1909 6fd805e1 aliguori
    ECX = ecx;
1910 6fd805e1 aliguori
    EDX = edx;
1911 eaa728ee bellard
}
1912 eaa728ee bellard
1913 eaa728ee bellard
void helper_enter_level(int level, int data32, target_ulong t1)
1914 eaa728ee bellard
{
1915 eaa728ee bellard
    target_ulong ssp;
1916 eaa728ee bellard
    uint32_t esp_mask, esp, ebp;
1917 eaa728ee bellard
1918 eaa728ee bellard
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1919 eaa728ee bellard
    ssp = env->segs[R_SS].base;
1920 eaa728ee bellard
    ebp = EBP;
1921 eaa728ee bellard
    esp = ESP;
1922 eaa728ee bellard
    if (data32) {
1923 eaa728ee bellard
        /* 32 bit */
1924 eaa728ee bellard
        esp -= 4;
1925 eaa728ee bellard
        while (--level) {
1926 eaa728ee bellard
            esp -= 4;
1927 eaa728ee bellard
            ebp -= 4;
1928 eaa728ee bellard
            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1929 eaa728ee bellard
        }
1930 eaa728ee bellard
        esp -= 4;
1931 eaa728ee bellard
        stl(ssp + (esp & esp_mask), t1);
1932 eaa728ee bellard
    } else {
1933 eaa728ee bellard
        /* 16 bit */
1934 eaa728ee bellard
        esp -= 2;
1935 eaa728ee bellard
        while (--level) {
1936 eaa728ee bellard
            esp -= 2;
1937 eaa728ee bellard
            ebp -= 2;
1938 eaa728ee bellard
            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1939 eaa728ee bellard
        }
1940 eaa728ee bellard
        esp -= 2;
1941 eaa728ee bellard
        stw(ssp + (esp & esp_mask), t1);
1942 eaa728ee bellard
    }
1943 eaa728ee bellard
}
1944 eaa728ee bellard
1945 eaa728ee bellard
#ifdef TARGET_X86_64
1946 eaa728ee bellard
void helper_enter64_level(int level, int data64, target_ulong t1)
1947 eaa728ee bellard
{
1948 eaa728ee bellard
    target_ulong esp, ebp;
1949 eaa728ee bellard
    ebp = EBP;
1950 eaa728ee bellard
    esp = ESP;
1951 eaa728ee bellard
1952 eaa728ee bellard
    if (data64) {
1953 eaa728ee bellard
        /* 64 bit */
1954 eaa728ee bellard
        esp -= 8;
1955 eaa728ee bellard
        while (--level) {
1956 eaa728ee bellard
            esp -= 8;
1957 eaa728ee bellard
            ebp -= 8;
1958 eaa728ee bellard
            stq(esp, ldq(ebp));
1959 eaa728ee bellard
        }
1960 eaa728ee bellard
        esp -= 8;
1961 eaa728ee bellard
        stq(esp, t1);
1962 eaa728ee bellard
    } else {
1963 eaa728ee bellard
        /* 16 bit */
1964 eaa728ee bellard
        esp -= 2;
1965 eaa728ee bellard
        while (--level) {
1966 eaa728ee bellard
            esp -= 2;
1967 eaa728ee bellard
            ebp -= 2;
1968 eaa728ee bellard
            stw(esp, lduw(ebp));
1969 eaa728ee bellard
        }
1970 eaa728ee bellard
        esp -= 2;
1971 eaa728ee bellard
        stw(esp, t1);
1972 eaa728ee bellard
    }
1973 eaa728ee bellard
}
1974 eaa728ee bellard
#endif
1975 eaa728ee bellard
1976 eaa728ee bellard
void helper_lldt(int selector)
1977 eaa728ee bellard
{
1978 eaa728ee bellard
    SegmentCache *dt;
1979 eaa728ee bellard
    uint32_t e1, e2;
1980 eaa728ee bellard
    int index, entry_limit;
1981 eaa728ee bellard
    target_ulong ptr;
1982 eaa728ee bellard
1983 eaa728ee bellard
    selector &= 0xffff;
1984 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
1985 eaa728ee bellard
        /* XXX: NULL selector case: invalid LDT */
1986 eaa728ee bellard
        env->ldt.base = 0;
1987 eaa728ee bellard
        env->ldt.limit = 0;
1988 eaa728ee bellard
    } else {
1989 eaa728ee bellard
        if (selector & 0x4)
1990 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1991 eaa728ee bellard
        dt = &env->gdt;
1992 eaa728ee bellard
        index = selector & ~7;
1993 eaa728ee bellard
#ifdef TARGET_X86_64
1994 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK)
1995 eaa728ee bellard
            entry_limit = 15;
1996 eaa728ee bellard
        else
1997 eaa728ee bellard
#endif
1998 eaa728ee bellard
            entry_limit = 7;
1999 eaa728ee bellard
        if ((index + entry_limit) > dt->limit)
2000 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2001 eaa728ee bellard
        ptr = dt->base + index;
2002 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2003 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2004 eaa728ee bellard
        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2005 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2006 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2007 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2008 eaa728ee bellard
#ifdef TARGET_X86_64
2009 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
2010 eaa728ee bellard
            uint32_t e3;
2011 eaa728ee bellard
            e3 = ldl_kernel(ptr + 8);
2012 eaa728ee bellard
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2013 eaa728ee bellard
            env->ldt.base |= (target_ulong)e3 << 32;
2014 eaa728ee bellard
        } else
2015 eaa728ee bellard
#endif
2016 eaa728ee bellard
        {
2017 eaa728ee bellard
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
2018 eaa728ee bellard
        }
2019 eaa728ee bellard
    }
2020 eaa728ee bellard
    env->ldt.selector = selector;
2021 eaa728ee bellard
}
2022 eaa728ee bellard
2023 eaa728ee bellard
void helper_ltr(int selector)
2024 eaa728ee bellard
{
2025 eaa728ee bellard
    SegmentCache *dt;
2026 eaa728ee bellard
    uint32_t e1, e2;
2027 eaa728ee bellard
    int index, type, entry_limit;
2028 eaa728ee bellard
    target_ulong ptr;
2029 eaa728ee bellard
2030 eaa728ee bellard
    selector &= 0xffff;
2031 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2032 eaa728ee bellard
        /* NULL selector case: invalid TR */
2033 eaa728ee bellard
        env->tr.base = 0;
2034 eaa728ee bellard
        env->tr.limit = 0;
2035 eaa728ee bellard
        env->tr.flags = 0;
2036 eaa728ee bellard
    } else {
2037 eaa728ee bellard
        if (selector & 0x4)
2038 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2039 eaa728ee bellard
        dt = &env->gdt;
2040 eaa728ee bellard
        index = selector & ~7;
2041 eaa728ee bellard
#ifdef TARGET_X86_64
2042 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK)
2043 eaa728ee bellard
            entry_limit = 15;
2044 eaa728ee bellard
        else
2045 eaa728ee bellard
#endif
2046 eaa728ee bellard
            entry_limit = 7;
2047 eaa728ee bellard
        if ((index + entry_limit) > dt->limit)
2048 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2049 eaa728ee bellard
        ptr = dt->base + index;
2050 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2051 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2052 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2053 eaa728ee bellard
        if ((e2 & DESC_S_MASK) ||
2054 eaa728ee bellard
            (type != 1 && type != 9))
2055 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2056 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2057 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2058 eaa728ee bellard
#ifdef TARGET_X86_64
2059 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK) {
2060 eaa728ee bellard
            uint32_t e3, e4;
2061 eaa728ee bellard
            e3 = ldl_kernel(ptr + 8);
2062 eaa728ee bellard
            e4 = ldl_kernel(ptr + 12);
2063 eaa728ee bellard
            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2064 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2065 eaa728ee bellard
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2066 eaa728ee bellard
            env->tr.base |= (target_ulong)e3 << 32;
2067 eaa728ee bellard
        } else
2068 eaa728ee bellard
#endif
2069 eaa728ee bellard
        {
2070 eaa728ee bellard
            load_seg_cache_raw_dt(&env->tr, e1, e2);
2071 eaa728ee bellard
        }
2072 eaa728ee bellard
        e2 |= DESC_TSS_BUSY_MASK;
2073 eaa728ee bellard
        stl_kernel(ptr + 4, e2);
2074 eaa728ee bellard
    }
2075 eaa728ee bellard
    env->tr.selector = selector;
2076 eaa728ee bellard
}
2077 eaa728ee bellard
2078 eaa728ee bellard
/* only works if protected mode and not VM86. seg_reg must be != R_CS */
2079 eaa728ee bellard
void helper_load_seg(int seg_reg, int selector)
2080 eaa728ee bellard
{
2081 eaa728ee bellard
    uint32_t e1, e2;
2082 eaa728ee bellard
    int cpl, dpl, rpl;
2083 eaa728ee bellard
    SegmentCache *dt;
2084 eaa728ee bellard
    int index;
2085 eaa728ee bellard
    target_ulong ptr;
2086 eaa728ee bellard
2087 eaa728ee bellard
    selector &= 0xffff;
2088 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2089 eaa728ee bellard
    if ((selector & 0xfffc) == 0) {
2090 eaa728ee bellard
        /* null selector case */
2091 eaa728ee bellard
        if (seg_reg == R_SS
2092 eaa728ee bellard
#ifdef TARGET_X86_64
2093 eaa728ee bellard
            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2094 eaa728ee bellard
#endif
2095 eaa728ee bellard
            )
2096 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, 0);
2097 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2098 eaa728ee bellard
    } else {
2099 eaa728ee bellard
2100 eaa728ee bellard
        if (selector & 0x4)
2101 eaa728ee bellard
            dt = &env->ldt;
2102 eaa728ee bellard
        else
2103 eaa728ee bellard
            dt = &env->gdt;
2104 eaa728ee bellard
        index = selector & ~7;
2105 eaa728ee bellard
        if ((index + 7) > dt->limit)
2106 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2107 eaa728ee bellard
        ptr = dt->base + index;
2108 eaa728ee bellard
        e1 = ldl_kernel(ptr);
2109 eaa728ee bellard
        e2 = ldl_kernel(ptr + 4);
2110 eaa728ee bellard
2111 eaa728ee bellard
        if (!(e2 & DESC_S_MASK))
2112 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2113 eaa728ee bellard
        rpl = selector & 3;
2114 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2115 eaa728ee bellard
        if (seg_reg == R_SS) {
2116 eaa728ee bellard
            /* must be writable segment */
2117 eaa728ee bellard
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2118 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2119 eaa728ee bellard
            if (rpl != cpl || dpl != cpl)
2120 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2121 eaa728ee bellard
        } else {
2122 eaa728ee bellard
            /* must be readable segment */
2123 eaa728ee bellard
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2124 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2125 eaa728ee bellard
2126 eaa728ee bellard
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2127 eaa728ee bellard
                /* if not conforming code, test rights */
2128 eaa728ee bellard
                if (dpl < cpl || dpl < rpl)
2129 eaa728ee bellard
                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2130 eaa728ee bellard
            }
2131 eaa728ee bellard
        }
2132 eaa728ee bellard
2133 eaa728ee bellard
        if (!(e2 & DESC_P_MASK)) {
2134 eaa728ee bellard
            if (seg_reg == R_SS)
2135 eaa728ee bellard
                raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2136 eaa728ee bellard
            else
2137 eaa728ee bellard
                raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2138 eaa728ee bellard
        }
2139 eaa728ee bellard
2140 eaa728ee bellard
        /* set the access bit if not already set */
2141 eaa728ee bellard
        if (!(e2 & DESC_A_MASK)) {
2142 eaa728ee bellard
            e2 |= DESC_A_MASK;
2143 eaa728ee bellard
            stl_kernel(ptr + 4, e2);
2144 eaa728ee bellard
        }
2145 eaa728ee bellard
2146 eaa728ee bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector,
2147 eaa728ee bellard
                       get_seg_base(e1, e2),
2148 eaa728ee bellard
                       get_seg_limit(e1, e2),
2149 eaa728ee bellard
                       e2);
2150 eaa728ee bellard
#if 0
2151 eaa728ee bellard
        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2152 eaa728ee bellard
                selector, (unsigned long)sc->base, sc->limit, sc->flags);
2153 eaa728ee bellard
#endif
2154 eaa728ee bellard
    }
2155 eaa728ee bellard
}
2156 eaa728ee bellard
2157 eaa728ee bellard
/* protected mode jump */
2158 eaa728ee bellard
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2159 eaa728ee bellard
                           int next_eip_addend)
2160 eaa728ee bellard
{
2161 eaa728ee bellard
    int gate_cs, type;
2162 eaa728ee bellard
    uint32_t e1, e2, cpl, dpl, rpl, limit;
2163 eaa728ee bellard
    target_ulong next_eip;
2164 eaa728ee bellard
2165 eaa728ee bellard
    if ((new_cs & 0xfffc) == 0)
2166 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
2167 eaa728ee bellard
    if (load_segment(&e1, &e2, new_cs) != 0)
2168 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2169 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2170 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
2171 eaa728ee bellard
        if (!(e2 & DESC_CS_MASK))
2172 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2173 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2174 eaa728ee bellard
        if (e2 & DESC_C_MASK) {
2175 eaa728ee bellard
            /* conforming code segment */
2176 eaa728ee bellard
            if (dpl > cpl)
2177 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2178 eaa728ee bellard
        } else {
2179 eaa728ee bellard
            /* non conforming code segment */
2180 eaa728ee bellard
            rpl = new_cs & 3;
2181 eaa728ee bellard
            if (rpl > cpl)
2182 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2183 eaa728ee bellard
            if (dpl != cpl)
2184 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2185 eaa728ee bellard
        }
2186 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2187 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2188 eaa728ee bellard
        limit = get_seg_limit(e1, e2);
2189 eaa728ee bellard
        if (new_eip > limit &&
2190 eaa728ee bellard
            !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2191 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2192 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2193 eaa728ee bellard
                       get_seg_base(e1, e2), limit, e2);
2194 eaa728ee bellard
        EIP = new_eip;
2195 eaa728ee bellard
    } else {
2196 eaa728ee bellard
        /* jump to call or task gate */
2197 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2198 eaa728ee bellard
        rpl = new_cs & 3;
2199 eaa728ee bellard
        cpl = env->hflags & HF_CPL_MASK;
2200 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2201 eaa728ee bellard
        switch(type) {
2202 eaa728ee bellard
        case 1: /* 286 TSS */
2203 eaa728ee bellard
        case 9: /* 386 TSS */
2204 eaa728ee bellard
        case 5: /* task gate */
2205 eaa728ee bellard
            if (dpl < cpl || dpl < rpl)
2206 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2207 eaa728ee bellard
            next_eip = env->eip + next_eip_addend;
2208 eaa728ee bellard
            switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2209 eaa728ee bellard
            CC_OP = CC_OP_EFLAGS;
2210 eaa728ee bellard
            break;
2211 eaa728ee bellard
        case 4: /* 286 call gate */
2212 eaa728ee bellard
        case 12: /* 386 call gate */
2213 eaa728ee bellard
            if ((dpl < cpl) || (dpl < rpl))
2214 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2215 eaa728ee bellard
            if (!(e2 & DESC_P_MASK))
2216 eaa728ee bellard
                raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2217 eaa728ee bellard
            gate_cs = e1 >> 16;
2218 eaa728ee bellard
            new_eip = (e1 & 0xffff);
2219 eaa728ee bellard
            if (type == 12)
2220 eaa728ee bellard
                new_eip |= (e2 & 0xffff0000);
2221 eaa728ee bellard
            if (load_segment(&e1, &e2, gate_cs) != 0)
2222 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2223 eaa728ee bellard
            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2224 eaa728ee bellard
            /* must be code segment */
2225 eaa728ee bellard
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2226 eaa728ee bellard
                 (DESC_S_MASK | DESC_CS_MASK)))
2227 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2228 eaa728ee bellard
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2229 eaa728ee bellard
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2230 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2231 eaa728ee bellard
            if (!(e2 & DESC_P_MASK))
2232 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2233 eaa728ee bellard
            limit = get_seg_limit(e1, e2);
2234 eaa728ee bellard
            if (new_eip > limit)
2235 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, 0);
2236 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2237 eaa728ee bellard
                                   get_seg_base(e1, e2), limit, e2);
2238 eaa728ee bellard
            EIP = new_eip;
2239 eaa728ee bellard
            break;
2240 eaa728ee bellard
        default:
2241 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2242 eaa728ee bellard
            break;
2243 eaa728ee bellard
        }
2244 eaa728ee bellard
    }
2245 eaa728ee bellard
}
2246 eaa728ee bellard
2247 eaa728ee bellard
/* real mode call */
2248 eaa728ee bellard
void helper_lcall_real(int new_cs, target_ulong new_eip1,
2249 eaa728ee bellard
                       int shift, int next_eip)
2250 eaa728ee bellard
{
2251 eaa728ee bellard
    int new_eip;
2252 eaa728ee bellard
    uint32_t esp, esp_mask;
2253 eaa728ee bellard
    target_ulong ssp;
2254 eaa728ee bellard
2255 eaa728ee bellard
    new_eip = new_eip1;
2256 eaa728ee bellard
    esp = ESP;
2257 eaa728ee bellard
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
2258 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2259 eaa728ee bellard
    if (shift) {
2260 eaa728ee bellard
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2261 eaa728ee bellard
        PUSHL(ssp, esp, esp_mask, next_eip);
2262 eaa728ee bellard
    } else {
2263 eaa728ee bellard
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2264 eaa728ee bellard
        PUSHW(ssp, esp, esp_mask, next_eip);
2265 eaa728ee bellard
    }
2266 eaa728ee bellard
2267 eaa728ee bellard
    SET_ESP(esp, esp_mask);
2268 eaa728ee bellard
    env->eip = new_eip;
2269 eaa728ee bellard
    env->segs[R_CS].selector = new_cs;
2270 eaa728ee bellard
    env->segs[R_CS].base = (new_cs << 4);
2271 eaa728ee bellard
}
2272 eaa728ee bellard
2273 eaa728ee bellard
/* protected mode call */
2274 eaa728ee bellard
void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2275 eaa728ee bellard
                            int shift, int next_eip_addend)
2276 eaa728ee bellard
{
2277 eaa728ee bellard
    int new_stack, i;
2278 eaa728ee bellard
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2279 eaa728ee bellard
    uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
2280 eaa728ee bellard
    uint32_t val, limit, old_sp_mask;
2281 eaa728ee bellard
    target_ulong ssp, old_ssp, next_eip;
2282 eaa728ee bellard
2283 eaa728ee bellard
    next_eip = env->eip + next_eip_addend;
2284 eaa728ee bellard
#ifdef DEBUG_PCALL
2285 eaa728ee bellard
    if (loglevel & CPU_LOG_PCALL) {
2286 eaa728ee bellard
        fprintf(logfile, "lcall %04x:%08x s=%d\n",
2287 eaa728ee bellard
                new_cs, (uint32_t)new_eip, shift);
2288 eaa728ee bellard
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2289 eaa728ee bellard
    }
2290 eaa728ee bellard
#endif
2291 eaa728ee bellard
    if ((new_cs & 0xfffc) == 0)
2292 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
2293 eaa728ee bellard
    if (load_segment(&e1, &e2, new_cs) != 0)
2294 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2295 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2296 eaa728ee bellard
#ifdef DEBUG_PCALL
2297 eaa728ee bellard
    if (loglevel & CPU_LOG_PCALL) {
2298 eaa728ee bellard
        fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
2299 eaa728ee bellard
    }
2300 eaa728ee bellard
#endif
2301 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
2302 eaa728ee bellard
        if (!(e2 & DESC_CS_MASK))
2303 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2304 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2305 eaa728ee bellard
        if (e2 & DESC_C_MASK) {
2306 eaa728ee bellard
            /* conforming code segment */
2307 eaa728ee bellard
            if (dpl > cpl)
2308 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2309 eaa728ee bellard
        } else {
2310 eaa728ee bellard
            /* non conforming code segment */
2311 eaa728ee bellard
            rpl = new_cs & 3;
2312 eaa728ee bellard
            if (rpl > cpl)
2313 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2314 eaa728ee bellard
            if (dpl != cpl)
2315 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2316 eaa728ee bellard
        }
2317 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2318 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2319 eaa728ee bellard
2320 eaa728ee bellard
#ifdef TARGET_X86_64
2321 eaa728ee bellard
        /* XXX: check 16/32 bit cases in long mode */
2322 eaa728ee bellard
        if (shift == 2) {
2323 eaa728ee bellard
            target_ulong rsp;
2324 eaa728ee bellard
            /* 64 bit case */
2325 eaa728ee bellard
            rsp = ESP;
2326 eaa728ee bellard
            PUSHQ(rsp, env->segs[R_CS].selector);
2327 eaa728ee bellard
            PUSHQ(rsp, next_eip);
2328 eaa728ee bellard
            /* from this point, not restartable */
2329 eaa728ee bellard
            ESP = rsp;
2330 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2331 eaa728ee bellard
                                   get_seg_base(e1, e2),
2332 eaa728ee bellard
                                   get_seg_limit(e1, e2), e2);
2333 eaa728ee bellard
            EIP = new_eip;
2334 eaa728ee bellard
        } else
2335 eaa728ee bellard
#endif
2336 eaa728ee bellard
        {
2337 eaa728ee bellard
            sp = ESP;
2338 eaa728ee bellard
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2339 eaa728ee bellard
            ssp = env->segs[R_SS].base;
2340 eaa728ee bellard
            if (shift) {
2341 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2342 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, next_eip);
2343 eaa728ee bellard
            } else {
2344 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2345 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, next_eip);
2346 eaa728ee bellard
            }
2347 eaa728ee bellard
2348 eaa728ee bellard
            limit = get_seg_limit(e1, e2);
2349 eaa728ee bellard
            if (new_eip > limit)
2350 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2351 eaa728ee bellard
            /* from this point, not restartable */
2352 eaa728ee bellard
            SET_ESP(sp, sp_mask);
2353 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2354 eaa728ee bellard
                                   get_seg_base(e1, e2), limit, e2);
2355 eaa728ee bellard
            EIP = new_eip;
2356 eaa728ee bellard
        }
2357 eaa728ee bellard
    } else {
2358 eaa728ee bellard
        /* check gate type */
2359 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2360 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2361 eaa728ee bellard
        rpl = new_cs & 3;
2362 eaa728ee bellard
        switch(type) {
2363 eaa728ee bellard
        case 1: /* available 286 TSS */
2364 eaa728ee bellard
        case 9: /* available 386 TSS */
2365 eaa728ee bellard
        case 5: /* task gate */
2366 eaa728ee bellard
            if (dpl < cpl || dpl < rpl)
2367 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2368 eaa728ee bellard
            switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2369 eaa728ee bellard
            CC_OP = CC_OP_EFLAGS;
2370 eaa728ee bellard
            return;
2371 eaa728ee bellard
        case 4: /* 286 call gate */
2372 eaa728ee bellard
        case 12: /* 386 call gate */
2373 eaa728ee bellard
            break;
2374 eaa728ee bellard
        default:
2375 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2376 eaa728ee bellard
            break;
2377 eaa728ee bellard
        }
2378 eaa728ee bellard
        shift = type >> 3;
2379 eaa728ee bellard
2380 eaa728ee bellard
        if (dpl < cpl || dpl < rpl)
2381 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2382 eaa728ee bellard
        /* check valid bit */
2383 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2384 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2385 eaa728ee bellard
        selector = e1 >> 16;
2386 eaa728ee bellard
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2387 eaa728ee bellard
        param_count = e2 & 0x1f;
2388 eaa728ee bellard
        if ((selector & 0xfffc) == 0)
2389 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, 0);
2390 eaa728ee bellard
2391 eaa728ee bellard
        if (load_segment(&e1, &e2, selector) != 0)
2392 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2393 eaa728ee bellard
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2394 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2395 eaa728ee bellard
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2396 eaa728ee bellard
        if (dpl > cpl)
2397 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2398 eaa728ee bellard
        if (!(e2 & DESC_P_MASK))
2399 eaa728ee bellard
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2400 eaa728ee bellard
2401 eaa728ee bellard
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2402 eaa728ee bellard
            /* to inner privilege */
2403 eaa728ee bellard
            get_ss_esp_from_tss(&ss, &sp, dpl);
2404 eaa728ee bellard
#ifdef DEBUG_PCALL
2405 eaa728ee bellard
            if (loglevel & CPU_LOG_PCALL)
2406 eaa728ee bellard
                fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2407 eaa728ee bellard
                        ss, sp, param_count, ESP);
2408 eaa728ee bellard
#endif
2409 eaa728ee bellard
            if ((ss & 0xfffc) == 0)
2410 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2411 eaa728ee bellard
            if ((ss & 3) != dpl)
2412 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2413 eaa728ee bellard
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2414 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2415 eaa728ee bellard
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2416 eaa728ee bellard
            if (ss_dpl != dpl)
2417 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2418 eaa728ee bellard
            if (!(ss_e2 & DESC_S_MASK) ||
2419 eaa728ee bellard
                (ss_e2 & DESC_CS_MASK) ||
2420 eaa728ee bellard
                !(ss_e2 & DESC_W_MASK))
2421 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2422 eaa728ee bellard
            if (!(ss_e2 & DESC_P_MASK))
2423 eaa728ee bellard
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2424 eaa728ee bellard
2425 eaa728ee bellard
            //            push_size = ((param_count * 2) + 8) << shift;
2426 eaa728ee bellard
2427 eaa728ee bellard
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2428 eaa728ee bellard
            old_ssp = env->segs[R_SS].base;
2429 eaa728ee bellard
2430 eaa728ee bellard
            sp_mask = get_sp_mask(ss_e2);
2431 eaa728ee bellard
            ssp = get_seg_base(ss_e1, ss_e2);
2432 eaa728ee bellard
            if (shift) {
2433 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2434 eaa728ee bellard
                PUSHL(ssp, sp, sp_mask, ESP);
2435 eaa728ee bellard
                for(i = param_count - 1; i >= 0; i--) {
2436 eaa728ee bellard
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2437 eaa728ee bellard
                    PUSHL(ssp, sp, sp_mask, val);
2438 eaa728ee bellard
                }
2439 eaa728ee bellard
            } else {
2440 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2441 eaa728ee bellard
                PUSHW(ssp, sp, sp_mask, ESP);
2442 eaa728ee bellard
                for(i = param_count - 1; i >= 0; i--) {
2443 eaa728ee bellard
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2444 eaa728ee bellard
                    PUSHW(ssp, sp, sp_mask, val);
2445 eaa728ee bellard
                }
2446 eaa728ee bellard
            }
2447 eaa728ee bellard
            new_stack = 1;
2448 eaa728ee bellard
        } else {
2449 eaa728ee bellard
            /* to same privilege */
2450 eaa728ee bellard
            sp = ESP;
2451 eaa728ee bellard
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
2452 eaa728ee bellard
            ssp = env->segs[R_SS].base;
2453 eaa728ee bellard
            //            push_size = (4 << shift);
2454 eaa728ee bellard
            new_stack = 0;
2455 eaa728ee bellard
        }
2456 eaa728ee bellard
2457 eaa728ee bellard
        if (shift) {
2458 eaa728ee bellard
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2459 eaa728ee bellard
            PUSHL(ssp, sp, sp_mask, next_eip);
2460 eaa728ee bellard
        } else {
2461 eaa728ee bellard
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2462 eaa728ee bellard
            PUSHW(ssp, sp, sp_mask, next_eip);
2463 eaa728ee bellard
        }
2464 eaa728ee bellard
2465 eaa728ee bellard
        /* from this point, not restartable */
2466 eaa728ee bellard
2467 eaa728ee bellard
        if (new_stack) {
2468 eaa728ee bellard
            ss = (ss & ~3) | dpl;
2469 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_SS, ss,
2470 eaa728ee bellard
                                   ssp,
2471 eaa728ee bellard
                                   get_seg_limit(ss_e1, ss_e2),
2472 eaa728ee bellard
                                   ss_e2);
2473 eaa728ee bellard
        }
2474 eaa728ee bellard
2475 eaa728ee bellard
        selector = (selector & ~3) | dpl;
2476 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, selector,
2477 eaa728ee bellard
                       get_seg_base(e1, e2),
2478 eaa728ee bellard
                       get_seg_limit(e1, e2),
2479 eaa728ee bellard
                       e2);
2480 eaa728ee bellard
        cpu_x86_set_cpl(env, dpl);
2481 eaa728ee bellard
        SET_ESP(sp, sp_mask);
2482 eaa728ee bellard
        EIP = offset;
2483 eaa728ee bellard
    }
2484 eaa728ee bellard
#ifdef USE_KQEMU
2485 eaa728ee bellard
    if (kqemu_is_ok(env)) {
2486 eaa728ee bellard
        env->exception_index = -1;
2487 eaa728ee bellard
        cpu_loop_exit();
2488 eaa728ee bellard
    }
2489 eaa728ee bellard
#endif
2490 eaa728ee bellard
}
2491 eaa728ee bellard
2492 eaa728ee bellard
/* real and vm86 mode iret */
2493 eaa728ee bellard
void helper_iret_real(int shift)
2494 eaa728ee bellard
{
2495 eaa728ee bellard
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2496 eaa728ee bellard
    target_ulong ssp;
2497 eaa728ee bellard
    int eflags_mask;
2498 eaa728ee bellard
2499 eaa728ee bellard
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2500 eaa728ee bellard
    sp = ESP;
2501 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2502 eaa728ee bellard
    if (shift == 1) {
2503 eaa728ee bellard
        /* 32 bits */
2504 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_eip);
2505 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_cs);
2506 eaa728ee bellard
        new_cs &= 0xffff;
2507 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_eflags);
2508 eaa728ee bellard
    } else {
2509 eaa728ee bellard
        /* 16 bits */
2510 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_eip);
2511 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_cs);
2512 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_eflags);
2513 eaa728ee bellard
    }
2514 eaa728ee bellard
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2515 bdadc0b5 malc
    env->segs[R_CS].selector = new_cs;
2516 bdadc0b5 malc
    env->segs[R_CS].base = (new_cs << 4);
2517 eaa728ee bellard
    env->eip = new_eip;
2518 eaa728ee bellard
    if (env->eflags & VM_MASK)
2519 eaa728ee bellard
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2520 eaa728ee bellard
    else
2521 eaa728ee bellard
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2522 eaa728ee bellard
    if (shift == 0)
2523 eaa728ee bellard
        eflags_mask &= 0xffff;
2524 eaa728ee bellard
    load_eflags(new_eflags, eflags_mask);
2525 db620f46 bellard
    env->hflags2 &= ~HF2_NMI_MASK;
2526 eaa728ee bellard
}
2527 eaa728ee bellard
2528 eaa728ee bellard
static inline void validate_seg(int seg_reg, int cpl)
2529 eaa728ee bellard
{
2530 eaa728ee bellard
    int dpl;
2531 eaa728ee bellard
    uint32_t e2;
2532 eaa728ee bellard
2533 eaa728ee bellard
    /* XXX: on x86_64, we do not want to nullify FS and GS because
2534 eaa728ee bellard
       they may still contain a valid base. I would be interested to
2535 eaa728ee bellard
       know how a real x86_64 CPU behaves */
2536 eaa728ee bellard
    if ((seg_reg == R_FS || seg_reg == R_GS) &&
2537 eaa728ee bellard
        (env->segs[seg_reg].selector & 0xfffc) == 0)
2538 eaa728ee bellard
        return;
2539 eaa728ee bellard
2540 eaa728ee bellard
    e2 = env->segs[seg_reg].flags;
2541 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2542 eaa728ee bellard
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2543 eaa728ee bellard
        /* data or non conforming code segment */
2544 eaa728ee bellard
        if (dpl < cpl) {
2545 eaa728ee bellard
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2546 eaa728ee bellard
        }
2547 eaa728ee bellard
    }
2548 eaa728ee bellard
}
2549 eaa728ee bellard
2550 eaa728ee bellard
/* protected mode iret */
2551 eaa728ee bellard
static inline void helper_ret_protected(int shift, int is_iret, int addend)
2552 eaa728ee bellard
{
2553 eaa728ee bellard
    uint32_t new_cs, new_eflags, new_ss;
2554 eaa728ee bellard
    uint32_t new_es, new_ds, new_fs, new_gs;
2555 eaa728ee bellard
    uint32_t e1, e2, ss_e1, ss_e2;
2556 eaa728ee bellard
    int cpl, dpl, rpl, eflags_mask, iopl;
2557 eaa728ee bellard
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2558 eaa728ee bellard
2559 eaa728ee bellard
#ifdef TARGET_X86_64
2560 eaa728ee bellard
    if (shift == 2)
2561 eaa728ee bellard
        sp_mask = -1;
2562 eaa728ee bellard
    else
2563 eaa728ee bellard
#endif
2564 eaa728ee bellard
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
2565 eaa728ee bellard
    sp = ESP;
2566 eaa728ee bellard
    ssp = env->segs[R_SS].base;
2567 eaa728ee bellard
    new_eflags = 0; /* avoid warning */
2568 eaa728ee bellard
#ifdef TARGET_X86_64
2569 eaa728ee bellard
    if (shift == 2) {
2570 eaa728ee bellard
        POPQ(sp, new_eip);
2571 eaa728ee bellard
        POPQ(sp, new_cs);
2572 eaa728ee bellard
        new_cs &= 0xffff;
2573 eaa728ee bellard
        if (is_iret) {
2574 eaa728ee bellard
            POPQ(sp, new_eflags);
2575 eaa728ee bellard
        }
2576 eaa728ee bellard
    } else
2577 eaa728ee bellard
#endif
2578 eaa728ee bellard
    if (shift == 1) {
2579 eaa728ee bellard
        /* 32 bits */
2580 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_eip);
2581 eaa728ee bellard
        POPL(ssp, sp, sp_mask, new_cs);
2582 eaa728ee bellard
        new_cs &= 0xffff;
2583 eaa728ee bellard
        if (is_iret) {
2584 eaa728ee bellard
            POPL(ssp, sp, sp_mask, new_eflags);
2585 eaa728ee bellard
            if (new_eflags & VM_MASK)
2586 eaa728ee bellard
                goto return_to_vm86;
2587 eaa728ee bellard
        }
2588 eaa728ee bellard
    } else {
2589 eaa728ee bellard
        /* 16 bits */
2590 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_eip);
2591 eaa728ee bellard
        POPW(ssp, sp, sp_mask, new_cs);
2592 eaa728ee bellard
        if (is_iret)
2593 eaa728ee bellard
            POPW(ssp, sp, sp_mask, new_eflags);
2594 eaa728ee bellard
    }
2595 eaa728ee bellard
#ifdef DEBUG_PCALL
2596 eaa728ee bellard
    if (loglevel & CPU_LOG_PCALL) {
2597 eaa728ee bellard
        fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2598 eaa728ee bellard
                new_cs, new_eip, shift, addend);
2599 eaa728ee bellard
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2600 eaa728ee bellard
    }
2601 eaa728ee bellard
#endif
2602 eaa728ee bellard
    if ((new_cs & 0xfffc) == 0)
2603 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2604 eaa728ee bellard
    if (load_segment(&e1, &e2, new_cs) != 0)
2605 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2606 eaa728ee bellard
    if (!(e2 & DESC_S_MASK) ||
2607 eaa728ee bellard
        !(e2 & DESC_CS_MASK))
2608 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2609 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2610 eaa728ee bellard
    rpl = new_cs & 3;
2611 eaa728ee bellard
    if (rpl < cpl)
2612 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2613 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2614 eaa728ee bellard
    if (e2 & DESC_C_MASK) {
2615 eaa728ee bellard
        if (dpl > rpl)
2616 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2617 eaa728ee bellard
    } else {
2618 eaa728ee bellard
        if (dpl != rpl)
2619 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2620 eaa728ee bellard
    }
2621 eaa728ee bellard
    if (!(e2 & DESC_P_MASK))
2622 eaa728ee bellard
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2623 eaa728ee bellard
2624 eaa728ee bellard
    sp += addend;
2625 eaa728ee bellard
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2626 eaa728ee bellard
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2627 1235fc06 ths
        /* return to same privilege level */
2628 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2629 eaa728ee bellard
                       get_seg_base(e1, e2),
2630 eaa728ee bellard
                       get_seg_limit(e1, e2),
2631 eaa728ee bellard
                       e2);
2632 eaa728ee bellard
    } else {
2633 eaa728ee bellard
        /* return to different privilege level */
2634 eaa728ee bellard
#ifdef TARGET_X86_64
2635 eaa728ee bellard
        if (shift == 2) {
2636 eaa728ee bellard
            POPQ(sp, new_esp);
2637 eaa728ee bellard
            POPQ(sp, new_ss);
2638 eaa728ee bellard
            new_ss &= 0xffff;
2639 eaa728ee bellard
        } else
2640 eaa728ee bellard
#endif
2641 eaa728ee bellard
        if (shift == 1) {
2642 eaa728ee bellard
            /* 32 bits */
2643 eaa728ee bellard
            POPL(ssp, sp, sp_mask, new_esp);
2644 eaa728ee bellard
            POPL(ssp, sp, sp_mask, new_ss);
2645 eaa728ee bellard
            new_ss &= 0xffff;
2646 eaa728ee bellard
        } else {
2647 eaa728ee bellard
            /* 16 bits */
2648 eaa728ee bellard
            POPW(ssp, sp, sp_mask, new_esp);
2649 eaa728ee bellard
            POPW(ssp, sp, sp_mask, new_ss);
2650 eaa728ee bellard
        }
2651 eaa728ee bellard
#ifdef DEBUG_PCALL
2652 eaa728ee bellard
        if (loglevel & CPU_LOG_PCALL) {
2653 eaa728ee bellard
            fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
2654 eaa728ee bellard
                    new_ss, new_esp);
2655 eaa728ee bellard
        }
2656 eaa728ee bellard
#endif
2657 eaa728ee bellard
        if ((new_ss & 0xfffc) == 0) {
2658 eaa728ee bellard
#ifdef TARGET_X86_64
2659 eaa728ee bellard
            /* NULL ss is allowed in long mode if cpl != 3*/
2660 eaa728ee bellard
            /* XXX: test CS64 ? */
2661 eaa728ee bellard
            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2662 eaa728ee bellard
                cpu_x86_load_seg_cache(env, R_SS, new_ss,
2663 eaa728ee bellard
                                       0, 0xffffffff,
2664 eaa728ee bellard
                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2665 eaa728ee bellard
                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2666 eaa728ee bellard
                                       DESC_W_MASK | DESC_A_MASK);
2667 eaa728ee bellard
                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2668 eaa728ee bellard
            } else
2669 eaa728ee bellard
#endif
2670 eaa728ee bellard
            {
2671 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, 0);
2672 eaa728ee bellard
            }
2673 eaa728ee bellard
        } else {
2674 eaa728ee bellard
            if ((new_ss & 3) != rpl)
2675 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2676 eaa728ee bellard
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2677 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2678 eaa728ee bellard
            if (!(ss_e2 & DESC_S_MASK) ||
2679 eaa728ee bellard
                (ss_e2 & DESC_CS_MASK) ||
2680 eaa728ee bellard
                !(ss_e2 & DESC_W_MASK))
2681 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2682 eaa728ee bellard
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2683 eaa728ee bellard
            if (dpl != rpl)
2684 eaa728ee bellard
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2685 eaa728ee bellard
            if (!(ss_e2 & DESC_P_MASK))
2686 eaa728ee bellard
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2687 eaa728ee bellard
            cpu_x86_load_seg_cache(env, R_SS, new_ss,
2688 eaa728ee bellard
                                   get_seg_base(ss_e1, ss_e2),
2689 eaa728ee bellard
                                   get_seg_limit(ss_e1, ss_e2),
2690 eaa728ee bellard
                                   ss_e2);
2691 eaa728ee bellard
        }
2692 eaa728ee bellard
2693 eaa728ee bellard
        cpu_x86_load_seg_cache(env, R_CS, new_cs,
2694 eaa728ee bellard
                       get_seg_base(e1, e2),
2695 eaa728ee bellard
                       get_seg_limit(e1, e2),
2696 eaa728ee bellard
                       e2);
2697 eaa728ee bellard
        cpu_x86_set_cpl(env, rpl);
2698 eaa728ee bellard
        sp = new_esp;
2699 eaa728ee bellard
#ifdef TARGET_X86_64
2700 eaa728ee bellard
        if (env->hflags & HF_CS64_MASK)
2701 eaa728ee bellard
            sp_mask = -1;
2702 eaa728ee bellard
        else
2703 eaa728ee bellard
#endif
2704 eaa728ee bellard
            sp_mask = get_sp_mask(ss_e2);
2705 eaa728ee bellard
2706 eaa728ee bellard
        /* validate data segments */
2707 eaa728ee bellard
        validate_seg(R_ES, rpl);
2708 eaa728ee bellard
        validate_seg(R_DS, rpl);
2709 eaa728ee bellard
        validate_seg(R_FS, rpl);
2710 eaa728ee bellard
        validate_seg(R_GS, rpl);
2711 eaa728ee bellard
2712 eaa728ee bellard
        sp += addend;
2713 eaa728ee bellard
    }
2714 eaa728ee bellard
    SET_ESP(sp, sp_mask);
2715 eaa728ee bellard
    env->eip = new_eip;
2716 eaa728ee bellard
    if (is_iret) {
2717 eaa728ee bellard
        /* NOTE: 'cpl' is the _old_ CPL */
2718 eaa728ee bellard
        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2719 eaa728ee bellard
        if (cpl == 0)
2720 eaa728ee bellard
            eflags_mask |= IOPL_MASK;
2721 eaa728ee bellard
        iopl = (env->eflags >> IOPL_SHIFT) & 3;
2722 eaa728ee bellard
        if (cpl <= iopl)
2723 eaa728ee bellard
            eflags_mask |= IF_MASK;
2724 eaa728ee bellard
        if (shift == 0)
2725 eaa728ee bellard
            eflags_mask &= 0xffff;
2726 eaa728ee bellard
        load_eflags(new_eflags, eflags_mask);
2727 eaa728ee bellard
    }
2728 eaa728ee bellard
    return;
2729 eaa728ee bellard
2730 eaa728ee bellard
 return_to_vm86:
2731 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_esp);
2732 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_ss);
2733 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_es);
2734 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_ds);
2735 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_fs);
2736 eaa728ee bellard
    POPL(ssp, sp, sp_mask, new_gs);
2737 eaa728ee bellard
2738 eaa728ee bellard
    /* modify processor state */
2739 eaa728ee bellard
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2740 eaa728ee bellard
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2741 eaa728ee bellard
    load_seg_vm(R_CS, new_cs & 0xffff);
2742 eaa728ee bellard
    cpu_x86_set_cpl(env, 3);
2743 eaa728ee bellard
    load_seg_vm(R_SS, new_ss & 0xffff);
2744 eaa728ee bellard
    load_seg_vm(R_ES, new_es & 0xffff);
2745 eaa728ee bellard
    load_seg_vm(R_DS, new_ds & 0xffff);
2746 eaa728ee bellard
    load_seg_vm(R_FS, new_fs & 0xffff);
2747 eaa728ee bellard
    load_seg_vm(R_GS, new_gs & 0xffff);
2748 eaa728ee bellard
2749 eaa728ee bellard
    env->eip = new_eip & 0xffff;
2750 eaa728ee bellard
    ESP = new_esp;
2751 eaa728ee bellard
}
2752 eaa728ee bellard
2753 eaa728ee bellard
void helper_iret_protected(int shift, int next_eip)
2754 eaa728ee bellard
{
2755 eaa728ee bellard
    int tss_selector, type;
2756 eaa728ee bellard
    uint32_t e1, e2;
2757 eaa728ee bellard
2758 eaa728ee bellard
    /* specific case for TSS */
2759 eaa728ee bellard
    if (env->eflags & NT_MASK) {
2760 eaa728ee bellard
#ifdef TARGET_X86_64
2761 eaa728ee bellard
        if (env->hflags & HF_LMA_MASK)
2762 eaa728ee bellard
            raise_exception_err(EXCP0D_GPF, 0);
2763 eaa728ee bellard
#endif
2764 eaa728ee bellard
        tss_selector = lduw_kernel(env->tr.base + 0);
2765 eaa728ee bellard
        if (tss_selector & 4)
2766 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2767 eaa728ee bellard
        if (load_segment(&e1, &e2, tss_selector) != 0)
2768 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2769 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2770 eaa728ee bellard
        /* NOTE: we check both segment and busy TSS */
2771 eaa728ee bellard
        if (type != 3)
2772 eaa728ee bellard
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2773 eaa728ee bellard
        switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2774 eaa728ee bellard
    } else {
2775 eaa728ee bellard
        helper_ret_protected(shift, 1, 0);
2776 eaa728ee bellard
    }
2777 db620f46 bellard
    env->hflags2 &= ~HF2_NMI_MASK;
2778 eaa728ee bellard
#ifdef USE_KQEMU
2779 eaa728ee bellard
    if (kqemu_is_ok(env)) {
2780 eaa728ee bellard
        CC_OP = CC_OP_EFLAGS;
2781 eaa728ee bellard
        env->exception_index = -1;
2782 eaa728ee bellard
        cpu_loop_exit();
2783 eaa728ee bellard
    }
2784 eaa728ee bellard
#endif
2785 eaa728ee bellard
}
2786 eaa728ee bellard
2787 eaa728ee bellard
void helper_lret_protected(int shift, int addend)
2788 eaa728ee bellard
{
2789 eaa728ee bellard
    helper_ret_protected(shift, 0, addend);
2790 eaa728ee bellard
#ifdef USE_KQEMU
2791 eaa728ee bellard
    if (kqemu_is_ok(env)) {
2792 eaa728ee bellard
        env->exception_index = -1;
2793 eaa728ee bellard
        cpu_loop_exit();
2794 eaa728ee bellard
    }
2795 eaa728ee bellard
#endif
2796 eaa728ee bellard
}
2797 eaa728ee bellard
2798 eaa728ee bellard
void helper_sysenter(void)
2799 eaa728ee bellard
{
2800 eaa728ee bellard
    if (env->sysenter_cs == 0) {
2801 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
2802 eaa728ee bellard
    }
2803 eaa728ee bellard
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2804 eaa728ee bellard
    cpu_x86_set_cpl(env, 0);
2805 2436b61a balrog
2806 2436b61a balrog
#ifdef TARGET_X86_64
2807 2436b61a balrog
    if (env->hflags & HF_LMA_MASK) {
2808 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2809 2436b61a balrog
                               0, 0xffffffff,
2810 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2811 2436b61a balrog
                               DESC_S_MASK |
2812 2436b61a balrog
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2813 2436b61a balrog
    } else
2814 2436b61a balrog
#endif
2815 2436b61a balrog
    {
2816 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2817 2436b61a balrog
                               0, 0xffffffff,
2818 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2819 2436b61a balrog
                               DESC_S_MASK |
2820 2436b61a balrog
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2821 2436b61a balrog
    }
2822 eaa728ee bellard
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2823 eaa728ee bellard
                           0, 0xffffffff,
2824 eaa728ee bellard
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2825 eaa728ee bellard
                           DESC_S_MASK |
2826 eaa728ee bellard
                           DESC_W_MASK | DESC_A_MASK);
2827 eaa728ee bellard
    ESP = env->sysenter_esp;
2828 eaa728ee bellard
    EIP = env->sysenter_eip;
2829 eaa728ee bellard
}
2830 eaa728ee bellard
2831 2436b61a balrog
void helper_sysexit(int dflag)
2832 eaa728ee bellard
{
2833 eaa728ee bellard
    int cpl;
2834 eaa728ee bellard
2835 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
2836 eaa728ee bellard
    if (env->sysenter_cs == 0 || cpl != 0) {
2837 eaa728ee bellard
        raise_exception_err(EXCP0D_GPF, 0);
2838 eaa728ee bellard
    }
2839 eaa728ee bellard
    cpu_x86_set_cpl(env, 3);
2840 2436b61a balrog
#ifdef TARGET_X86_64
2841 2436b61a balrog
    if (dflag == 2) {
2842 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3,
2843 2436b61a balrog
                               0, 0xffffffff,
2844 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2845 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2846 2436b61a balrog
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
2847 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3,
2848 2436b61a balrog
                               0, 0xffffffff,
2849 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2850 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2851 2436b61a balrog
                               DESC_W_MASK | DESC_A_MASK);
2852 2436b61a balrog
    } else
2853 2436b61a balrog
#endif
2854 2436b61a balrog
    {
2855 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2856 2436b61a balrog
                               0, 0xffffffff,
2857 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2858 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2859 2436b61a balrog
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2860 2436b61a balrog
        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2861 2436b61a balrog
                               0, 0xffffffff,
2862 2436b61a balrog
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2863 2436b61a balrog
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2864 2436b61a balrog
                               DESC_W_MASK | DESC_A_MASK);
2865 2436b61a balrog
    }
2866 eaa728ee bellard
    ESP = ECX;
2867 eaa728ee bellard
    EIP = EDX;
2868 eaa728ee bellard
#ifdef USE_KQEMU
2869 eaa728ee bellard
    if (kqemu_is_ok(env)) {
2870 eaa728ee bellard
        env->exception_index = -1;
2871 eaa728ee bellard
        cpu_loop_exit();
2872 eaa728ee bellard
    }
2873 eaa728ee bellard
#endif
2874 eaa728ee bellard
}
2875 eaa728ee bellard
2876 872929aa bellard
#if defined(CONFIG_USER_ONLY)
2877 872929aa bellard
target_ulong helper_read_crN(int reg)
2878 eaa728ee bellard
{
2879 872929aa bellard
    return 0;
2880 872929aa bellard
}
2881 872929aa bellard
2882 872929aa bellard
void helper_write_crN(int reg, target_ulong t0)
2883 872929aa bellard
{
2884 872929aa bellard
}
2885 01df040b aliguori
2886 01df040b aliguori
void helper_movl_drN_T0(int reg, target_ulong t0)
2887 01df040b aliguori
{
2888 01df040b aliguori
}
2889 872929aa bellard
#else
2890 872929aa bellard
target_ulong helper_read_crN(int reg)
2891 872929aa bellard
{
2892 872929aa bellard
    target_ulong val;
2893 872929aa bellard
2894 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
2895 872929aa bellard
    switch(reg) {
2896 872929aa bellard
    default:
2897 872929aa bellard
        val = env->cr[reg];
2898 872929aa bellard
        break;
2899 872929aa bellard
    case 8:
2900 db620f46 bellard
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2901 db620f46 bellard
            val = cpu_get_apic_tpr(env);
2902 db620f46 bellard
        } else {
2903 db620f46 bellard
            val = env->v_tpr;
2904 db620f46 bellard
        }
2905 872929aa bellard
        break;
2906 872929aa bellard
    }
2907 872929aa bellard
    return val;
2908 872929aa bellard
}
2909 872929aa bellard
2910 872929aa bellard
void helper_write_crN(int reg, target_ulong t0)
2911 872929aa bellard
{
2912 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_WRITE_CR0 + reg, 0);
2913 eaa728ee bellard
    switch(reg) {
2914 eaa728ee bellard
    case 0:
2915 eaa728ee bellard
        cpu_x86_update_cr0(env, t0);
2916 eaa728ee bellard
        break;
2917 eaa728ee bellard
    case 3:
2918 eaa728ee bellard
        cpu_x86_update_cr3(env, t0);
2919 eaa728ee bellard
        break;
2920 eaa728ee bellard
    case 4:
2921 eaa728ee bellard
        cpu_x86_update_cr4(env, t0);
2922 eaa728ee bellard
        break;
2923 eaa728ee bellard
    case 8:
2924 db620f46 bellard
        if (!(env->hflags2 & HF2_VINTR_MASK)) {
2925 db620f46 bellard
            cpu_set_apic_tpr(env, t0);
2926 db620f46 bellard
        }
2927 db620f46 bellard
        env->v_tpr = t0 & 0x0f;
2928 eaa728ee bellard
        break;
2929 eaa728ee bellard
    default:
2930 eaa728ee bellard
        env->cr[reg] = t0;
2931 eaa728ee bellard
        break;
2932 eaa728ee bellard
    }
2933 eaa728ee bellard
}
2934 01df040b aliguori
2935 01df040b aliguori
void helper_movl_drN_T0(int reg, target_ulong t0)
2936 01df040b aliguori
{
2937 01df040b aliguori
    int i;
2938 01df040b aliguori
2939 01df040b aliguori
    if (reg < 4) {
2940 01df040b aliguori
        hw_breakpoint_remove(env, reg);
2941 01df040b aliguori
        env->dr[reg] = t0;
2942 01df040b aliguori
        hw_breakpoint_insert(env, reg);
2943 01df040b aliguori
    } else if (reg == 7) {
2944 01df040b aliguori
        for (i = 0; i < 4; i++)
2945 01df040b aliguori
            hw_breakpoint_remove(env, i);
2946 01df040b aliguori
        env->dr[7] = t0;
2947 01df040b aliguori
        for (i = 0; i < 4; i++)
2948 01df040b aliguori
            hw_breakpoint_insert(env, i);
2949 01df040b aliguori
    } else
2950 01df040b aliguori
        env->dr[reg] = t0;
2951 01df040b aliguori
}
2952 872929aa bellard
#endif
2953 eaa728ee bellard
2954 eaa728ee bellard
void helper_lmsw(target_ulong t0)
2955 eaa728ee bellard
{
2956 eaa728ee bellard
    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2957 eaa728ee bellard
       if already set to one. */
2958 eaa728ee bellard
    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2959 872929aa bellard
    helper_write_crN(0, t0);
2960 eaa728ee bellard
}
2961 eaa728ee bellard
2962 eaa728ee bellard
void helper_clts(void)
2963 eaa728ee bellard
{
2964 eaa728ee bellard
    env->cr[0] &= ~CR0_TS_MASK;
2965 eaa728ee bellard
    env->hflags &= ~HF_TS_MASK;
2966 eaa728ee bellard
}
2967 eaa728ee bellard
2968 eaa728ee bellard
void helper_invlpg(target_ulong addr)
2969 eaa728ee bellard
{
2970 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
2971 914178d3 bellard
    tlb_flush_page(env, addr);
2972 eaa728ee bellard
}
2973 eaa728ee bellard
2974 eaa728ee bellard
void helper_rdtsc(void)
2975 eaa728ee bellard
{
2976 eaa728ee bellard
    uint64_t val;
2977 eaa728ee bellard
2978 eaa728ee bellard
    if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2979 eaa728ee bellard
        raise_exception(EXCP0D_GPF);
2980 eaa728ee bellard
    }
2981 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
2982 872929aa bellard
2983 33c263df bellard
    val = cpu_get_tsc(env) + env->tsc_offset;
2984 eaa728ee bellard
    EAX = (uint32_t)(val);
2985 eaa728ee bellard
    EDX = (uint32_t)(val >> 32);
2986 eaa728ee bellard
}
2987 eaa728ee bellard
2988 eaa728ee bellard
void helper_rdpmc(void)
2989 eaa728ee bellard
{
2990 eaa728ee bellard
    if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
2991 eaa728ee bellard
        raise_exception(EXCP0D_GPF);
2992 eaa728ee bellard
    }
2993 eaa728ee bellard
    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
2994 eaa728ee bellard
    
2995 eaa728ee bellard
    /* currently unimplemented */
2996 eaa728ee bellard
    raise_exception_err(EXCP06_ILLOP, 0);
2997 eaa728ee bellard
}
2998 eaa728ee bellard
2999 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
3000 eaa728ee bellard
void helper_wrmsr(void)
3001 eaa728ee bellard
{
3002 eaa728ee bellard
}
3003 eaa728ee bellard
3004 eaa728ee bellard
void helper_rdmsr(void)
3005 eaa728ee bellard
{
3006 eaa728ee bellard
}
3007 eaa728ee bellard
#else
3008 eaa728ee bellard
void helper_wrmsr(void)
3009 eaa728ee bellard
{
3010 eaa728ee bellard
    uint64_t val;
3011 eaa728ee bellard
3012 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3013 872929aa bellard
3014 eaa728ee bellard
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3015 eaa728ee bellard
3016 eaa728ee bellard
    switch((uint32_t)ECX) {
3017 eaa728ee bellard
    case MSR_IA32_SYSENTER_CS:
3018 eaa728ee bellard
        env->sysenter_cs = val & 0xffff;
3019 eaa728ee bellard
        break;
3020 eaa728ee bellard
    case MSR_IA32_SYSENTER_ESP:
3021 eaa728ee bellard
        env->sysenter_esp = val;
3022 eaa728ee bellard
        break;
3023 eaa728ee bellard
    case MSR_IA32_SYSENTER_EIP:
3024 eaa728ee bellard
        env->sysenter_eip = val;
3025 eaa728ee bellard
        break;
3026 eaa728ee bellard
    case MSR_IA32_APICBASE:
3027 eaa728ee bellard
        cpu_set_apic_base(env, val);
3028 eaa728ee bellard
        break;
3029 eaa728ee bellard
    case MSR_EFER:
3030 eaa728ee bellard
        {
3031 eaa728ee bellard
            uint64_t update_mask;
3032 eaa728ee bellard
            update_mask = 0;
3033 eaa728ee bellard
            if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3034 eaa728ee bellard
                update_mask |= MSR_EFER_SCE;
3035 eaa728ee bellard
            if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3036 eaa728ee bellard
                update_mask |= MSR_EFER_LME;
3037 eaa728ee bellard
            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3038 eaa728ee bellard
                update_mask |= MSR_EFER_FFXSR;
3039 eaa728ee bellard
            if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3040 eaa728ee bellard
                update_mask |= MSR_EFER_NXE;
3041 5efc27bb bellard
            if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
3042 5efc27bb bellard
                update_mask |= MSR_EFER_SVME;
3043 5efc27bb bellard
            cpu_load_efer(env, (env->efer & ~update_mask) |
3044 5efc27bb bellard
                          (val & update_mask));
3045 eaa728ee bellard
        }
3046 eaa728ee bellard
        break;
3047 eaa728ee bellard
    case MSR_STAR:
3048 eaa728ee bellard
        env->star = val;
3049 eaa728ee bellard
        break;
3050 eaa728ee bellard
    case MSR_PAT:
3051 eaa728ee bellard
        env->pat = val;
3052 eaa728ee bellard
        break;
3053 eaa728ee bellard
    case MSR_VM_HSAVE_PA:
3054 eaa728ee bellard
        env->vm_hsave = val;
3055 eaa728ee bellard
        break;
3056 eaa728ee bellard
#ifdef TARGET_X86_64
3057 eaa728ee bellard
    case MSR_LSTAR:
3058 eaa728ee bellard
        env->lstar = val;
3059 eaa728ee bellard
        break;
3060 eaa728ee bellard
    case MSR_CSTAR:
3061 eaa728ee bellard
        env->cstar = val;
3062 eaa728ee bellard
        break;
3063 eaa728ee bellard
    case MSR_FMASK:
3064 eaa728ee bellard
        env->fmask = val;
3065 eaa728ee bellard
        break;
3066 eaa728ee bellard
    case MSR_FSBASE:
3067 eaa728ee bellard
        env->segs[R_FS].base = val;
3068 eaa728ee bellard
        break;
3069 eaa728ee bellard
    case MSR_GSBASE:
3070 eaa728ee bellard
        env->segs[R_GS].base = val;
3071 eaa728ee bellard
        break;
3072 eaa728ee bellard
    case MSR_KERNELGSBASE:
3073 eaa728ee bellard
        env->kernelgsbase = val;
3074 eaa728ee bellard
        break;
3075 eaa728ee bellard
#endif
3076 eaa728ee bellard
    default:
3077 eaa728ee bellard
        /* XXX: exception ? */
3078 eaa728ee bellard
        break;
3079 eaa728ee bellard
    }
3080 eaa728ee bellard
}
3081 eaa728ee bellard
3082 eaa728ee bellard
void helper_rdmsr(void)
3083 eaa728ee bellard
{
3084 eaa728ee bellard
    uint64_t val;
3085 872929aa bellard
3086 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3087 872929aa bellard
3088 eaa728ee bellard
    switch((uint32_t)ECX) {
3089 eaa728ee bellard
    case MSR_IA32_SYSENTER_CS:
3090 eaa728ee bellard
        val = env->sysenter_cs;
3091 eaa728ee bellard
        break;
3092 eaa728ee bellard
    case MSR_IA32_SYSENTER_ESP:
3093 eaa728ee bellard
        val = env->sysenter_esp;
3094 eaa728ee bellard
        break;
3095 eaa728ee bellard
    case MSR_IA32_SYSENTER_EIP:
3096 eaa728ee bellard
        val = env->sysenter_eip;
3097 eaa728ee bellard
        break;
3098 eaa728ee bellard
    case MSR_IA32_APICBASE:
3099 eaa728ee bellard
        val = cpu_get_apic_base(env);
3100 eaa728ee bellard
        break;
3101 eaa728ee bellard
    case MSR_EFER:
3102 eaa728ee bellard
        val = env->efer;
3103 eaa728ee bellard
        break;
3104 eaa728ee bellard
    case MSR_STAR:
3105 eaa728ee bellard
        val = env->star;
3106 eaa728ee bellard
        break;
3107 eaa728ee bellard
    case MSR_PAT:
3108 eaa728ee bellard
        val = env->pat;
3109 eaa728ee bellard
        break;
3110 eaa728ee bellard
    case MSR_VM_HSAVE_PA:
3111 eaa728ee bellard
        val = env->vm_hsave;
3112 eaa728ee bellard
        break;
3113 d5e49a81 balrog
    case MSR_IA32_PERF_STATUS:
3114 d5e49a81 balrog
        /* tsc_increment_by_tick */
3115 d5e49a81 balrog
        val = 1000ULL;
3116 d5e49a81 balrog
        /* CPU multiplier */
3117 d5e49a81 balrog
        val |= (((uint64_t)4ULL) << 40);
3118 d5e49a81 balrog
        break;
3119 eaa728ee bellard
#ifdef TARGET_X86_64
3120 eaa728ee bellard
    case MSR_LSTAR:
3121 eaa728ee bellard
        val = env->lstar;
3122 eaa728ee bellard
        break;
3123 eaa728ee bellard
    case MSR_CSTAR:
3124 eaa728ee bellard
        val = env->cstar;
3125 eaa728ee bellard
        break;
3126 eaa728ee bellard
    case MSR_FMASK:
3127 eaa728ee bellard
        val = env->fmask;
3128 eaa728ee bellard
        break;
3129 eaa728ee bellard
    case MSR_FSBASE:
3130 eaa728ee bellard
        val = env->segs[R_FS].base;
3131 eaa728ee bellard
        break;
3132 eaa728ee bellard
    case MSR_GSBASE:
3133 eaa728ee bellard
        val = env->segs[R_GS].base;
3134 eaa728ee bellard
        break;
3135 eaa728ee bellard
    case MSR_KERNELGSBASE:
3136 eaa728ee bellard
        val = env->kernelgsbase;
3137 eaa728ee bellard
        break;
3138 eaa728ee bellard
#endif
3139 da260249 bellard
#ifdef USE_KQEMU
3140 da260249 bellard
    case MSR_QPI_COMMBASE:
3141 da260249 bellard
        if (env->kqemu_enabled) {
3142 da260249 bellard
            val = kqemu_comm_base;
3143 da260249 bellard
        } else {
3144 da260249 bellard
            val = 0;
3145 da260249 bellard
        }
3146 da260249 bellard
        break;
3147 da260249 bellard
#endif
3148 eaa728ee bellard
    default:
3149 eaa728ee bellard
        /* XXX: exception ? */
3150 eaa728ee bellard
        val = 0;
3151 eaa728ee bellard
        break;
3152 eaa728ee bellard
    }
3153 eaa728ee bellard
    EAX = (uint32_t)(val);
3154 eaa728ee bellard
    EDX = (uint32_t)(val >> 32);
3155 eaa728ee bellard
}
3156 eaa728ee bellard
#endif
3157 eaa728ee bellard
3158 eaa728ee bellard
target_ulong helper_lsl(target_ulong selector1)
3159 eaa728ee bellard
{
3160 eaa728ee bellard
    unsigned int limit;
3161 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3162 eaa728ee bellard
    int rpl, dpl, cpl, type;
3163 eaa728ee bellard
3164 eaa728ee bellard
    selector = selector1 & 0xffff;
3165 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3166 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
3167 eaa728ee bellard
        goto fail;
3168 eaa728ee bellard
    rpl = selector & 3;
3169 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3170 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3171 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
3172 eaa728ee bellard
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3173 eaa728ee bellard
            /* conforming */
3174 eaa728ee bellard
        } else {
3175 eaa728ee bellard
            if (dpl < cpl || dpl < rpl)
3176 eaa728ee bellard
                goto fail;
3177 eaa728ee bellard
        }
3178 eaa728ee bellard
    } else {
3179 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3180 eaa728ee bellard
        switch(type) {
3181 eaa728ee bellard
        case 1:
3182 eaa728ee bellard
        case 2:
3183 eaa728ee bellard
        case 3:
3184 eaa728ee bellard
        case 9:
3185 eaa728ee bellard
        case 11:
3186 eaa728ee bellard
            break;
3187 eaa728ee bellard
        default:
3188 eaa728ee bellard
            goto fail;
3189 eaa728ee bellard
        }
3190 eaa728ee bellard
        if (dpl < cpl || dpl < rpl) {
3191 eaa728ee bellard
        fail:
3192 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3193 eaa728ee bellard
            return 0;
3194 eaa728ee bellard
        }
3195 eaa728ee bellard
    }
3196 eaa728ee bellard
    limit = get_seg_limit(e1, e2);
3197 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3198 eaa728ee bellard
    return limit;
3199 eaa728ee bellard
}
3200 eaa728ee bellard
3201 eaa728ee bellard
target_ulong helper_lar(target_ulong selector1)
3202 eaa728ee bellard
{
3203 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3204 eaa728ee bellard
    int rpl, dpl, cpl, type;
3205 eaa728ee bellard
3206 eaa728ee bellard
    selector = selector1 & 0xffff;
3207 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3208 eaa728ee bellard
    if ((selector & 0xfffc) == 0)
3209 eaa728ee bellard
        goto fail;
3210 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
3211 eaa728ee bellard
        goto fail;
3212 eaa728ee bellard
    rpl = selector & 3;
3213 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3214 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3215 eaa728ee bellard
    if (e2 & DESC_S_MASK) {
3216 eaa728ee bellard
        if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3217 eaa728ee bellard
            /* conforming */
3218 eaa728ee bellard
        } else {
3219 eaa728ee bellard
            if (dpl < cpl || dpl < rpl)
3220 eaa728ee bellard
                goto fail;
3221 eaa728ee bellard
        }
3222 eaa728ee bellard
    } else {
3223 eaa728ee bellard
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3224 eaa728ee bellard
        switch(type) {
3225 eaa728ee bellard
        case 1:
3226 eaa728ee bellard
        case 2:
3227 eaa728ee bellard
        case 3:
3228 eaa728ee bellard
        case 4:
3229 eaa728ee bellard
        case 5:
3230 eaa728ee bellard
        case 9:
3231 eaa728ee bellard
        case 11:
3232 eaa728ee bellard
        case 12:
3233 eaa728ee bellard
            break;
3234 eaa728ee bellard
        default:
3235 eaa728ee bellard
            goto fail;
3236 eaa728ee bellard
        }
3237 eaa728ee bellard
        if (dpl < cpl || dpl < rpl) {
3238 eaa728ee bellard
        fail:
3239 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3240 eaa728ee bellard
            return 0;
3241 eaa728ee bellard
        }
3242 eaa728ee bellard
    }
3243 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3244 eaa728ee bellard
    return e2 & 0x00f0ff00;
3245 eaa728ee bellard
}
3246 eaa728ee bellard
3247 eaa728ee bellard
void helper_verr(target_ulong selector1)
3248 eaa728ee bellard
{
3249 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3250 eaa728ee bellard
    int rpl, dpl, cpl;
3251 eaa728ee bellard
3252 eaa728ee bellard
    selector = selector1 & 0xffff;
3253 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3254 eaa728ee bellard
    if ((selector & 0xfffc) == 0)
3255 eaa728ee bellard
        goto fail;
3256 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
3257 eaa728ee bellard
        goto fail;
3258 eaa728ee bellard
    if (!(e2 & DESC_S_MASK))
3259 eaa728ee bellard
        goto fail;
3260 eaa728ee bellard
    rpl = selector & 3;
3261 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3262 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3263 eaa728ee bellard
    if (e2 & DESC_CS_MASK) {
3264 eaa728ee bellard
        if (!(e2 & DESC_R_MASK))
3265 eaa728ee bellard
            goto fail;
3266 eaa728ee bellard
        if (!(e2 & DESC_C_MASK)) {
3267 eaa728ee bellard
            if (dpl < cpl || dpl < rpl)
3268 eaa728ee bellard
                goto fail;
3269 eaa728ee bellard
        }
3270 eaa728ee bellard
    } else {
3271 eaa728ee bellard
        if (dpl < cpl || dpl < rpl) {
3272 eaa728ee bellard
        fail:
3273 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3274 eaa728ee bellard
            return;
3275 eaa728ee bellard
        }
3276 eaa728ee bellard
    }
3277 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3278 eaa728ee bellard
}
3279 eaa728ee bellard
3280 eaa728ee bellard
void helper_verw(target_ulong selector1)
3281 eaa728ee bellard
{
3282 eaa728ee bellard
    uint32_t e1, e2, eflags, selector;
3283 eaa728ee bellard
    int rpl, dpl, cpl;
3284 eaa728ee bellard
3285 eaa728ee bellard
    selector = selector1 & 0xffff;
3286 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3287 eaa728ee bellard
    if ((selector & 0xfffc) == 0)
3288 eaa728ee bellard
        goto fail;
3289 eaa728ee bellard
    if (load_segment(&e1, &e2, selector) != 0)
3290 eaa728ee bellard
        goto fail;
3291 eaa728ee bellard
    if (!(e2 & DESC_S_MASK))
3292 eaa728ee bellard
        goto fail;
3293 eaa728ee bellard
    rpl = selector & 3;
3294 eaa728ee bellard
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3295 eaa728ee bellard
    cpl = env->hflags & HF_CPL_MASK;
3296 eaa728ee bellard
    if (e2 & DESC_CS_MASK) {
3297 eaa728ee bellard
        goto fail;
3298 eaa728ee bellard
    } else {
3299 eaa728ee bellard
        if (dpl < cpl || dpl < rpl)
3300 eaa728ee bellard
            goto fail;
3301 eaa728ee bellard
        if (!(e2 & DESC_W_MASK)) {
3302 eaa728ee bellard
        fail:
3303 eaa728ee bellard
            CC_SRC = eflags & ~CC_Z;
3304 eaa728ee bellard
            return;
3305 eaa728ee bellard
        }
3306 eaa728ee bellard
    }
3307 eaa728ee bellard
    CC_SRC = eflags | CC_Z;
3308 eaa728ee bellard
}
3309 eaa728ee bellard
3310 eaa728ee bellard
/* x87 FPU helpers */
3311 eaa728ee bellard
3312 eaa728ee bellard
static void fpu_set_exception(int mask)
3313 eaa728ee bellard
{
3314 eaa728ee bellard
    env->fpus |= mask;
3315 eaa728ee bellard
    if (env->fpus & (~env->fpuc & FPUC_EM))
3316 eaa728ee bellard
        env->fpus |= FPUS_SE | FPUS_B;
3317 eaa728ee bellard
}
3318 eaa728ee bellard
3319 eaa728ee bellard
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3320 eaa728ee bellard
{
3321 eaa728ee bellard
    if (b == 0.0)
3322 eaa728ee bellard
        fpu_set_exception(FPUS_ZE);
3323 eaa728ee bellard
    return a / b;
3324 eaa728ee bellard
}
3325 eaa728ee bellard
3326 eaa728ee bellard
void fpu_raise_exception(void)
3327 eaa728ee bellard
{
3328 eaa728ee bellard
    if (env->cr[0] & CR0_NE_MASK) {
3329 eaa728ee bellard
        raise_exception(EXCP10_COPR);
3330 eaa728ee bellard
    }
3331 eaa728ee bellard
#if !defined(CONFIG_USER_ONLY)
3332 eaa728ee bellard
    else {
3333 eaa728ee bellard
        cpu_set_ferr(env);
3334 eaa728ee bellard
    }
3335 eaa728ee bellard
#endif
3336 eaa728ee bellard
}
3337 eaa728ee bellard
3338 eaa728ee bellard
void helper_flds_FT0(uint32_t val)
3339 eaa728ee bellard
{
3340 eaa728ee bellard
    union {
3341 eaa728ee bellard
        float32 f;
3342 eaa728ee bellard
        uint32_t i;
3343 eaa728ee bellard
    } u;
3344 eaa728ee bellard
    u.i = val;
3345 eaa728ee bellard
    FT0 = float32_to_floatx(u.f, &env->fp_status);
3346 eaa728ee bellard
}
3347 eaa728ee bellard
3348 eaa728ee bellard
void helper_fldl_FT0(uint64_t val)
3349 eaa728ee bellard
{
3350 eaa728ee bellard
    union {
3351 eaa728ee bellard
        float64 f;
3352 eaa728ee bellard
        uint64_t i;
3353 eaa728ee bellard
    } u;
3354 eaa728ee bellard
    u.i = val;
3355 eaa728ee bellard
    FT0 = float64_to_floatx(u.f, &env->fp_status);
3356 eaa728ee bellard
}
3357 eaa728ee bellard
3358 eaa728ee bellard
void helper_fildl_FT0(int32_t val)
3359 eaa728ee bellard
{
3360 eaa728ee bellard
    FT0 = int32_to_floatx(val, &env->fp_status);
3361 eaa728ee bellard
}
3362 eaa728ee bellard
3363 eaa728ee bellard
void helper_flds_ST0(uint32_t val)
3364 eaa728ee bellard
{
3365 eaa728ee bellard
    int new_fpstt;
3366 eaa728ee bellard
    union {
3367 eaa728ee bellard
        float32 f;
3368 eaa728ee bellard
        uint32_t i;
3369 eaa728ee bellard
    } u;
3370 eaa728ee bellard
    new_fpstt = (env->fpstt - 1) & 7;
3371 eaa728ee bellard
    u.i = val;
3372 eaa728ee bellard
    env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3373 eaa728ee bellard
    env->fpstt = new_fpstt;
3374 eaa728ee bellard
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3375 eaa728ee bellard
}
3376 eaa728ee bellard
3377 eaa728ee bellard
void helper_fldl_ST0(uint64_t val)
3378 eaa728ee bellard
{
3379 eaa728ee bellard
    int new_fpstt;
3380 eaa728ee bellard
    union {
3381 eaa728ee bellard
        float64 f;
3382 eaa728ee bellard
        uint64_t i;
3383 eaa728ee bellard
    } u;
3384 eaa728ee bellard
    new_fpstt = (env->fpstt - 1) & 7;
3385 eaa728ee bellard
    u.i = val;
3386 eaa728ee bellard
    env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3387 eaa728ee bellard
    env->fpstt = new_fpstt;
3388 eaa728ee bellard
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3389 eaa728ee bellard
}
3390 eaa728ee bellard
3391 eaa728ee bellard
void helper_fildl_ST0(int32_t val)
3392 eaa728ee bellard
{
3393 eaa728ee bellard
    int new_fpstt;
3394 eaa728ee bellard
    new_fpstt = (env->fpstt - 1) & 7;
3395 eaa728ee bellard
    env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3396 eaa728ee bellard
    env->fpstt = new_fpstt;
3397 eaa728ee bellard
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3398 eaa728ee bellard
}
3399 eaa728ee bellard
3400 eaa728ee bellard
void helper_fildll_ST0(int64_t val)
3401 eaa728ee bellard
{
3402 eaa728ee bellard
    int new_fpstt;
3403 eaa728ee bellard
    new_fpstt = (env->fpstt - 1) & 7;
3404 eaa728ee bellard
    env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3405 eaa728ee bellard
    env->fpstt = new_fpstt;
3406 eaa728ee bellard
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3407 eaa728ee bellard
}
3408 eaa728ee bellard
3409 eaa728ee bellard
uint32_t helper_fsts_ST0(void)
3410 eaa728ee bellard
{
3411 eaa728ee bellard
    union {
3412 eaa728ee bellard
        float32 f;
3413 eaa728ee bellard
        uint32_t i;
3414 eaa728ee bellard
    } u;
3415 eaa728ee bellard
    u.f = floatx_to_float32(ST0, &env->fp_status);
3416 eaa728ee bellard
    return u.i;
3417 eaa728ee bellard
}
3418 eaa728ee bellard
3419 eaa728ee bellard
uint64_t helper_fstl_ST0(void)
3420 eaa728ee bellard
{
3421 eaa728ee bellard
    union {
3422 eaa728ee bellard
        float64 f;
3423 eaa728ee bellard
        uint64_t i;
3424 eaa728ee bellard
    } u;
3425 eaa728ee bellard
    u.f = floatx_to_float64(ST0, &env->fp_status);
3426 eaa728ee bellard
    return u.i;
3427 eaa728ee bellard
}
3428 eaa728ee bellard
3429 eaa728ee bellard
int32_t helper_fist_ST0(void)
3430 eaa728ee bellard
{
3431 eaa728ee bellard
    int32_t val;
3432 eaa728ee bellard
    val = floatx_to_int32(ST0, &env->fp_status);
3433 eaa728ee bellard
    if (val != (int16_t)val)
3434 eaa728ee bellard
        val = -32768;
3435 eaa728ee bellard
    return val;
3436 eaa728ee bellard
}
3437 eaa728ee bellard
3438 eaa728ee bellard
int32_t helper_fistl_ST0(void)
3439 eaa728ee bellard
{
3440 eaa728ee bellard
    int32_t val;
3441 eaa728ee bellard
    val = floatx_to_int32(ST0, &env->fp_status);
3442 eaa728ee bellard
    return val;
3443 eaa728ee bellard
}
3444 eaa728ee bellard
3445 eaa728ee bellard
int64_t helper_fistll_ST0(void)
3446 eaa728ee bellard
{
3447 eaa728ee bellard
    int64_t val;
3448 eaa728ee bellard
    val = floatx_to_int64(ST0, &env->fp_status);
3449 eaa728ee bellard
    return val;
3450 eaa728ee bellard
}
3451 eaa728ee bellard
3452 eaa728ee bellard
int32_t helper_fistt_ST0(void)
3453 eaa728ee bellard
{
3454 eaa728ee bellard
    int32_t val;
3455 eaa728ee bellard
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3456 eaa728ee bellard
    if (val != (int16_t)val)
3457 eaa728ee bellard
        val = -32768;
3458 eaa728ee bellard
    return val;
3459 eaa728ee bellard
}
3460 eaa728ee bellard
3461 eaa728ee bellard
int32_t helper_fisttl_ST0(void)
3462 eaa728ee bellard
{
3463 eaa728ee bellard
    int32_t val;
3464 eaa728ee bellard
    val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3465 eaa728ee bellard
    return val;
3466 eaa728ee bellard
}
3467 eaa728ee bellard
3468 eaa728ee bellard
int64_t helper_fisttll_ST0(void)
3469 eaa728ee bellard
{
3470 eaa728ee bellard
    int64_t val;
3471 eaa728ee bellard
    val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3472 eaa728ee bellard
    return val;
3473 eaa728ee bellard
}
3474 eaa728ee bellard
3475 eaa728ee bellard
void helper_fldt_ST0(target_ulong ptr)
3476 eaa728ee bellard
{
3477 eaa728ee bellard
    int new_fpstt;
3478 eaa728ee bellard
    new_fpstt = (env->fpstt - 1) & 7;
3479 eaa728ee bellard
    env->fpregs[new_fpstt].d = helper_fldt(ptr);
3480 eaa728ee bellard
    env->fpstt = new_fpstt;
3481 eaa728ee bellard
    env->fptags[new_fpstt] = 0; /* validate stack entry */
3482 eaa728ee bellard
}
3483 eaa728ee bellard
3484 eaa728ee bellard
void helper_fstt_ST0(target_ulong ptr)
3485 eaa728ee bellard
{
3486 eaa728ee bellard
    helper_fstt(ST0, ptr);
3487 eaa728ee bellard
}
3488 eaa728ee bellard
3489 eaa728ee bellard
void helper_fpush(void)
3490 eaa728ee bellard
{
3491 eaa728ee bellard
    fpush();
3492 eaa728ee bellard
}
3493 eaa728ee bellard
3494 eaa728ee bellard
void helper_fpop(void)
3495 eaa728ee bellard
{
3496 eaa728ee bellard
    fpop();
3497 eaa728ee bellard
}
3498 eaa728ee bellard
3499 eaa728ee bellard
void helper_fdecstp(void)
3500 eaa728ee bellard
{
3501 eaa728ee bellard
    env->fpstt = (env->fpstt - 1) & 7;
3502 eaa728ee bellard
    env->fpus &= (~0x4700);
3503 eaa728ee bellard
}
3504 eaa728ee bellard
3505 eaa728ee bellard
void helper_fincstp(void)
3506 eaa728ee bellard
{
3507 eaa728ee bellard
    env->fpstt = (env->fpstt + 1) & 7;
3508 eaa728ee bellard
    env->fpus &= (~0x4700);
3509 eaa728ee bellard
}
3510 eaa728ee bellard
3511 eaa728ee bellard
/* FPU move */
3512 eaa728ee bellard
3513 eaa728ee bellard
void helper_ffree_STN(int st_index)
3514 eaa728ee bellard
{
3515 eaa728ee bellard
    env->fptags[(env->fpstt + st_index) & 7] = 1;
3516 eaa728ee bellard
}
3517 eaa728ee bellard
3518 eaa728ee bellard
void helper_fmov_ST0_FT0(void)
3519 eaa728ee bellard
{
3520 eaa728ee bellard
    ST0 = FT0;
3521 eaa728ee bellard
}
3522 eaa728ee bellard
3523 eaa728ee bellard
void helper_fmov_FT0_STN(int st_index)
3524 eaa728ee bellard
{
3525 eaa728ee bellard
    FT0 = ST(st_index);
3526 eaa728ee bellard
}
3527 eaa728ee bellard
3528 eaa728ee bellard
void helper_fmov_ST0_STN(int st_index)
3529 eaa728ee bellard
{
3530 eaa728ee bellard
    ST0 = ST(st_index);
3531 eaa728ee bellard
}
3532 eaa728ee bellard
3533 eaa728ee bellard
void helper_fmov_STN_ST0(int st_index)
3534 eaa728ee bellard
{
3535 eaa728ee bellard
    ST(st_index) = ST0;
3536 eaa728ee bellard
}
3537 eaa728ee bellard
3538 eaa728ee bellard
void helper_fxchg_ST0_STN(int st_index)
3539 eaa728ee bellard
{
3540 eaa728ee bellard
    CPU86_LDouble tmp;
3541 eaa728ee bellard
    tmp = ST(st_index);
3542 eaa728ee bellard
    ST(st_index) = ST0;
3543 eaa728ee bellard
    ST0 = tmp;
3544 eaa728ee bellard
}
3545 eaa728ee bellard
3546 eaa728ee bellard
/* FPU operations */
3547 eaa728ee bellard
3548 eaa728ee bellard
static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
3549 eaa728ee bellard
3550 eaa728ee bellard
void helper_fcom_ST0_FT0(void)
3551 eaa728ee bellard
{
3552 eaa728ee bellard
    int ret;
3553 eaa728ee bellard
3554 eaa728ee bellard
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3555 eaa728ee bellard
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3556 eaa728ee bellard
    FORCE_RET();
3557 eaa728ee bellard
}
3558 eaa728ee bellard
3559 eaa728ee bellard
void helper_fucom_ST0_FT0(void)
3560 eaa728ee bellard
{
3561 eaa728ee bellard
    int ret;
3562 eaa728ee bellard
3563 eaa728ee bellard
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3564 eaa728ee bellard
    env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3565 eaa728ee bellard
    FORCE_RET();
3566 eaa728ee bellard
}
3567 eaa728ee bellard
3568 eaa728ee bellard
static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
3569 eaa728ee bellard
3570 eaa728ee bellard
void helper_fcomi_ST0_FT0(void)
3571 eaa728ee bellard
{
3572 eaa728ee bellard
    int eflags;
3573 eaa728ee bellard
    int ret;
3574 eaa728ee bellard
3575 eaa728ee bellard
    ret = floatx_compare(ST0, FT0, &env->fp_status);
3576 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3577 eaa728ee bellard
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3578 eaa728ee bellard
    CC_SRC = eflags;
3579 eaa728ee bellard
    FORCE_RET();
3580 eaa728ee bellard
}
3581 eaa728ee bellard
3582 eaa728ee bellard
void helper_fucomi_ST0_FT0(void)
3583 eaa728ee bellard
{
3584 eaa728ee bellard
    int eflags;
3585 eaa728ee bellard
    int ret;
3586 eaa728ee bellard
3587 eaa728ee bellard
    ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3588 a7812ae4 pbrook
    eflags = helper_cc_compute_all(CC_OP);
3589 eaa728ee bellard
    eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3590 eaa728ee bellard
    CC_SRC = eflags;
3591 eaa728ee bellard
    FORCE_RET();
3592 eaa728ee bellard
}
3593 eaa728ee bellard
3594 eaa728ee bellard
void helper_fadd_ST0_FT0(void)
3595 eaa728ee bellard
{
3596 eaa728ee bellard
    ST0 += FT0;
3597 eaa728ee bellard
}
3598 eaa728ee bellard
3599 eaa728ee bellard
void helper_fmul_ST0_FT0(void)
3600 eaa728ee bellard
{
3601 eaa728ee bellard
    ST0 *= FT0;
3602 eaa728ee bellard
}
3603 eaa728ee bellard
3604 eaa728ee bellard
void helper_fsub_ST0_FT0(void)
3605 eaa728ee bellard
{
3606 eaa728ee bellard
    ST0 -= FT0;
3607 eaa728ee bellard
}
3608 eaa728ee bellard
3609 eaa728ee bellard
void helper_fsubr_ST0_FT0(void)
3610 eaa728ee bellard
{
3611 eaa728ee bellard
    ST0 = FT0 - ST0;
3612 eaa728ee bellard
}
3613 eaa728ee bellard
3614 eaa728ee bellard
void helper_fdiv_ST0_FT0(void)
3615 eaa728ee bellard
{
3616 eaa728ee bellard
    ST0 = helper_fdiv(ST0, FT0);
3617 eaa728ee bellard
}
3618 eaa728ee bellard
3619 eaa728ee bellard
void helper_fdivr_ST0_FT0(void)
3620 eaa728ee bellard
{
3621 eaa728ee bellard
    ST0 = helper_fdiv(FT0, ST0);
3622 eaa728ee bellard
}
3623 eaa728ee bellard
3624 eaa728ee bellard
/* fp operations between STN and ST0 */
3625 eaa728ee bellard
3626 eaa728ee bellard
void helper_fadd_STN_ST0(int st_index)
3627 eaa728ee bellard
{
3628 eaa728ee bellard
    ST(st_index) += ST0;
3629 eaa728ee bellard
}
3630 eaa728ee bellard
3631 eaa728ee bellard
void helper_fmul_STN_ST0(int st_index)
3632 eaa728ee bellard
{
3633 eaa728ee bellard
    ST(st_index) *= ST0;
3634 eaa728ee bellard
}
3635 eaa728ee bellard
3636 eaa728ee bellard
void helper_fsub_STN_ST0(int st_index)
3637 eaa728ee bellard
{
3638 eaa728ee bellard
    ST(st_index) -= ST0;
3639 eaa728ee bellard
}
3640 eaa728ee bellard
3641 eaa728ee bellard
void helper_fsubr_STN_ST0(int st_index)
3642 eaa728ee bellard
{
3643 eaa728ee bellard
    CPU86_LDouble *p;
3644 eaa728ee bellard
    p = &ST(st_index);
3645 eaa728ee bellard
    *p = ST0 - *p;
3646 eaa728ee bellard
}
3647 eaa728ee bellard
3648 eaa728ee bellard
void helper_fdiv_STN_ST0(int st_index)
3649 eaa728ee bellard
{
3650 eaa728ee bellard
    CPU86_LDouble *p;
3651 eaa728ee bellard
    p = &ST(st_index);
3652 eaa728ee bellard
    *p = helper_fdiv(*p, ST0);
3653 eaa728ee bellard
}
3654 eaa728ee bellard
3655 eaa728ee bellard
void helper_fdivr_STN_ST0(int st_index)
3656 eaa728ee bellard
{
3657 eaa728ee bellard
    CPU86_LDouble *p;
3658 eaa728ee bellard
    p = &ST(st_index);
3659 eaa728ee bellard
    *p = helper_fdiv(ST0, *p);
3660 eaa728ee bellard
}
3661 eaa728ee bellard
3662 eaa728ee bellard
/* misc FPU operations */
3663 eaa728ee bellard
void helper_fchs_ST0(void)
3664 eaa728ee bellard
{
3665 eaa728ee bellard
    ST0 = floatx_chs(ST0);
3666 eaa728ee bellard
}
3667 eaa728ee bellard
3668 eaa728ee bellard
void helper_fabs_ST0(void)
3669 eaa728ee bellard
{
3670 eaa728ee bellard
    ST0 = floatx_abs(ST0);
3671 eaa728ee bellard
}
3672 eaa728ee bellard
3673 eaa728ee bellard
void helper_fld1_ST0(void)
3674 eaa728ee bellard
{
3675 eaa728ee bellard
    ST0 = f15rk[1];
3676 eaa728ee bellard
}
3677 eaa728ee bellard
3678 eaa728ee bellard
void helper_fldl2t_ST0(void)
3679 eaa728ee bellard
{
3680 eaa728ee bellard
    ST0 = f15rk[6];
3681 eaa728ee bellard
}
3682 eaa728ee bellard
3683 eaa728ee bellard
void helper_fldl2e_ST0(void)
3684 eaa728ee bellard
{
3685 eaa728ee bellard
    ST0 = f15rk[5];
3686 eaa728ee bellard
}
3687 eaa728ee bellard
3688 eaa728ee bellard
void helper_fldpi_ST0(void)
3689 eaa728ee bellard
{
3690 eaa728ee bellard
    ST0 = f15rk[2];
3691 eaa728ee bellard
}
3692 eaa728ee bellard
3693 eaa728ee bellard
void helper_fldlg2_ST0(void)
3694 eaa728ee bellard
{
3695 eaa728ee bellard
    ST0 = f15rk[3];
3696 eaa728ee bellard
}
3697 eaa728ee bellard
3698 eaa728ee bellard
void helper_fldln2_ST0(void)
3699 eaa728ee bellard
{
3700 eaa728ee bellard
    ST0 = f15rk[4];
3701 eaa728ee bellard
}
3702 eaa728ee bellard
3703 eaa728ee bellard
void helper_fldz_ST0(void)
3704 eaa728ee bellard
{
3705 eaa728ee bellard
    ST0 = f15rk[0];
3706 eaa728ee bellard
}
3707 eaa728ee bellard
3708 eaa728ee bellard
void helper_fldz_FT0(void)
3709 eaa728ee bellard
{
3710 eaa728ee bellard
    FT0 = f15rk[0];
3711 eaa728ee bellard
}
3712 eaa728ee bellard
3713 eaa728ee bellard
uint32_t helper_fnstsw(void)
3714 eaa728ee bellard
{
3715 eaa728ee bellard
    return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3716 eaa728ee bellard
}
3717 eaa728ee bellard
3718 eaa728ee bellard
uint32_t helper_fnstcw(void)
3719 eaa728ee bellard
{
3720 eaa728ee bellard
    return env->fpuc;
3721 eaa728ee bellard
}
3722 eaa728ee bellard
3723 eaa728ee bellard
static void update_fp_status(void)
3724 eaa728ee bellard
{
3725 eaa728ee bellard
    int rnd_type;
3726 eaa728ee bellard
3727 eaa728ee bellard
    /* set rounding mode */
3728 eaa728ee bellard
    switch(env->fpuc & RC_MASK) {
3729 eaa728ee bellard
    default:
3730 eaa728ee bellard
    case RC_NEAR:
3731 eaa728ee bellard
        rnd_type = float_round_nearest_even;
3732 eaa728ee bellard
        break;
3733 eaa728ee bellard
    case RC_DOWN:
3734 eaa728ee bellard
        rnd_type = float_round_down;
3735 eaa728ee bellard
        break;
3736 eaa728ee bellard
    case RC_UP:
3737 eaa728ee bellard
        rnd_type = float_round_up;
3738 eaa728ee bellard
        break;
3739 eaa728ee bellard
    case RC_CHOP:
3740 eaa728ee bellard
        rnd_type = float_round_to_zero;
3741 eaa728ee bellard
        break;
3742 eaa728ee bellard
    }
3743 eaa728ee bellard
    set_float_rounding_mode(rnd_type, &env->fp_status);
3744 eaa728ee bellard
#ifdef FLOATX80
3745 eaa728ee bellard
    switch((env->fpuc >> 8) & 3) {
3746 eaa728ee bellard
    case 0:
3747 eaa728ee bellard
        rnd_type = 32;
3748 eaa728ee bellard
        break;
3749 eaa728ee bellard
    case 2:
3750 eaa728ee bellard
        rnd_type = 64;
3751 eaa728ee bellard
        break;
3752 eaa728ee bellard
    case 3:
3753 eaa728ee bellard
    default:
3754 eaa728ee bellard
        rnd_type = 80;
3755 eaa728ee bellard
        break;
3756 eaa728ee bellard
    }
3757 eaa728ee bellard
    set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3758 eaa728ee bellard
#endif
3759 eaa728ee bellard
}
3760 eaa728ee bellard
3761 eaa728ee bellard
void helper_fldcw(uint32_t val)
3762 eaa728ee bellard
{
3763 eaa728ee bellard
    env->fpuc = val;
3764 eaa728ee bellard
    update_fp_status();
3765 eaa728ee bellard
}
3766 eaa728ee bellard
3767 eaa728ee bellard
void helper_fclex(void)
3768 eaa728ee bellard
{
3769 eaa728ee bellard
    env->fpus &= 0x7f00;
3770 eaa728ee bellard
}
3771 eaa728ee bellard
3772 eaa728ee bellard
void helper_fwait(void)
3773 eaa728ee bellard
{
3774 eaa728ee bellard
    if (env->fpus & FPUS_SE)
3775 eaa728ee bellard
        fpu_raise_exception();
3776 eaa728ee bellard
    FORCE_RET();
3777 eaa728ee bellard
}
3778 eaa728ee bellard
3779 eaa728ee bellard
void helper_fninit(void)
3780 eaa728ee bellard
{
3781 eaa728ee bellard
    env->fpus = 0;
3782 eaa728ee bellard
    env->fpstt = 0;
3783 eaa728ee bellard
    env->fpuc = 0x37f;
3784 eaa728ee bellard
    env->fptags[0] = 1;
3785 eaa728ee bellard
    env->fptags[1] = 1;
3786 eaa728ee bellard
    env->fptags[2] = 1;
3787 eaa728ee bellard
    env->fptags[3] = 1;
3788 eaa728ee bellard
    env->fptags[4] = 1;
3789 eaa728ee bellard
    env->fptags[5] = 1;
3790 eaa728ee bellard
    env->fptags[6] = 1;
3791 eaa728ee bellard
    env->fptags[7] = 1;
3792 eaa728ee bellard
}
3793 eaa728ee bellard
3794 eaa728ee bellard
/* BCD ops */
3795 eaa728ee bellard
3796 eaa728ee bellard
void helper_fbld_ST0(target_ulong ptr)
3797 eaa728ee bellard
{
3798 eaa728ee bellard
    CPU86_LDouble tmp;
3799 eaa728ee bellard
    uint64_t val;
3800 eaa728ee bellard
    unsigned int v;
3801 eaa728ee bellard
    int i;
3802 eaa728ee bellard
3803 eaa728ee bellard
    val = 0;
3804 eaa728ee bellard
    for(i = 8; i >= 0; i--) {
3805 eaa728ee bellard
        v = ldub(ptr + i);
3806 eaa728ee bellard
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3807 eaa728ee bellard
    }
3808 eaa728ee bellard
    tmp = val;
3809 eaa728ee bellard
    if (ldub(ptr + 9) & 0x80)
3810 eaa728ee bellard
        tmp = -tmp;
3811 eaa728ee bellard
    fpush();
3812 eaa728ee bellard
    ST0 = tmp;
3813 eaa728ee bellard
}
3814 eaa728ee bellard
3815 eaa728ee bellard
void helper_fbst_ST0(target_ulong ptr)
3816 eaa728ee bellard
{
3817 eaa728ee bellard
    int v;
3818 eaa728ee bellard
    target_ulong mem_ref, mem_end;
3819 eaa728ee bellard
    int64_t val;
3820 eaa728ee bellard
3821 eaa728ee bellard
    val = floatx_to_int64(ST0, &env->fp_status);
3822 eaa728ee bellard
    mem_ref = ptr;
3823 eaa728ee bellard
    mem_end = mem_ref + 9;
3824 eaa728ee bellard
    if (val < 0) {
3825 eaa728ee bellard
        stb(mem_end, 0x80);
3826 eaa728ee bellard
        val = -val;
3827 eaa728ee bellard
    } else {
3828 eaa728ee bellard
        stb(mem_end, 0x00);
3829 eaa728ee bellard
    }
3830 eaa728ee bellard
    while (mem_ref < mem_end) {
3831 eaa728ee bellard
        if (val == 0)
3832 eaa728ee bellard
            break;
3833 eaa728ee bellard
        v = val % 100;
3834 eaa728ee bellard
        val = val / 100;
3835 eaa728ee bellard
        v = ((v / 10) << 4) | (v % 10);
3836 eaa728ee bellard
        stb(mem_ref++, v);
3837 eaa728ee bellard
    }
3838 eaa728ee bellard
    while (mem_ref < mem_end) {
3839 eaa728ee bellard
        stb(mem_ref++, 0);
3840 eaa728ee bellard
    }
3841 eaa728ee bellard
}
3842 eaa728ee bellard
3843 eaa728ee bellard
void helper_f2xm1(void)
3844 eaa728ee bellard
{
3845 eaa728ee bellard
    ST0 = pow(2.0,ST0) - 1.0;
3846 eaa728ee bellard
}
3847 eaa728ee bellard
3848 eaa728ee bellard
void helper_fyl2x(void)
3849 eaa728ee bellard
{
3850 eaa728ee bellard
    CPU86_LDouble fptemp;
3851 eaa728ee bellard
3852 eaa728ee bellard
    fptemp = ST0;
3853 eaa728ee bellard
    if (fptemp>0.0){
3854 eaa728ee bellard
        fptemp = log(fptemp)/log(2.0);         /* log2(ST) */
3855 eaa728ee bellard
        ST1 *= fptemp;
3856 eaa728ee bellard
        fpop();
3857 eaa728ee bellard
    } else {
3858 eaa728ee bellard
        env->fpus &= (~0x4700);
3859 eaa728ee bellard
        env->fpus |= 0x400;
3860 eaa728ee bellard
    }
3861 eaa728ee bellard
}
3862 eaa728ee bellard
3863 eaa728ee bellard
void helper_fptan(void)
3864 eaa728ee bellard
{
3865 eaa728ee bellard
    CPU86_LDouble fptemp;
3866 eaa728ee bellard
3867 eaa728ee bellard
    fptemp = ST0;
3868 eaa728ee bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3869 eaa728ee bellard
        env->fpus |= 0x400;
3870 eaa728ee bellard
    } else {
3871 eaa728ee bellard
        ST0 = tan(fptemp);
3872 eaa728ee bellard
        fpush();
3873 eaa728ee bellard
        ST0 = 1.0;
3874 eaa728ee bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
3875 eaa728ee bellard
        /* the above code is for  |arg| < 2**52 only */
3876 eaa728ee bellard
    }
3877 eaa728ee bellard
}
3878 eaa728ee bellard
3879 eaa728ee bellard
void helper_fpatan(void)
3880 eaa728ee bellard
{
3881 eaa728ee bellard
    CPU86_LDouble fptemp, fpsrcop;
3882 eaa728ee bellard
3883 eaa728ee bellard
    fpsrcop = ST1;
3884 eaa728ee bellard
    fptemp = ST0;
3885 eaa728ee bellard
    ST1 = atan2(fpsrcop,fptemp);
3886 eaa728ee bellard
    fpop();
3887 eaa728ee bellard
}
3888 eaa728ee bellard
3889 eaa728ee bellard
void helper_fxtract(void)
3890 eaa728ee bellard
{
3891 eaa728ee bellard
    CPU86_LDoubleU temp;
3892 eaa728ee bellard
    unsigned int expdif;
3893 eaa728ee bellard
3894 eaa728ee bellard
    temp.d = ST0;
3895 eaa728ee bellard
    expdif = EXPD(temp) - EXPBIAS;
3896 eaa728ee bellard
    /*DP exponent bias*/
3897 eaa728ee bellard
    ST0 = expdif;
3898 eaa728ee bellard
    fpush();
3899 eaa728ee bellard
    BIASEXPONENT(temp);
3900 eaa728ee bellard
    ST0 = temp.d;
3901 eaa728ee bellard
}
3902 eaa728ee bellard
3903 eaa728ee bellard
void helper_fprem1(void)
3904 eaa728ee bellard
{
3905 eaa728ee bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
3906 eaa728ee bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
3907 eaa728ee bellard
    int expdif;
3908 eaa728ee bellard
    signed long long int q;
3909 eaa728ee bellard
3910 eaa728ee bellard
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3911 eaa728ee bellard
        ST0 = 0.0 / 0.0; /* NaN */
3912 eaa728ee bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3913 eaa728ee bellard
        return;
3914 eaa728ee bellard
    }
3915 eaa728ee bellard
3916 eaa728ee bellard
    fpsrcop = ST0;
3917 eaa728ee bellard
    fptemp = ST1;
3918 eaa728ee bellard
    fpsrcop1.d = fpsrcop;
3919 eaa728ee bellard
    fptemp1.d = fptemp;
3920 eaa728ee bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3921 eaa728ee bellard
3922 eaa728ee bellard
    if (expdif < 0) {
3923 eaa728ee bellard
        /* optimisation? taken from the AMD docs */
3924 eaa728ee bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3925 eaa728ee bellard
        /* ST0 is unchanged */
3926 eaa728ee bellard
        return;
3927 eaa728ee bellard
    }
3928 eaa728ee bellard
3929 eaa728ee bellard
    if (expdif < 53) {
3930 eaa728ee bellard
        dblq = fpsrcop / fptemp;
3931 eaa728ee bellard
        /* round dblq towards nearest integer */
3932 eaa728ee bellard
        dblq = rint(dblq);
3933 eaa728ee bellard
        ST0 = fpsrcop - fptemp * dblq;
3934 eaa728ee bellard
3935 eaa728ee bellard
        /* convert dblq to q by truncating towards zero */
3936 eaa728ee bellard
        if (dblq < 0.0)
3937 eaa728ee bellard
           q = (signed long long int)(-dblq);
3938 eaa728ee bellard
        else
3939 eaa728ee bellard
           q = (signed long long int)dblq;
3940 eaa728ee bellard
3941 eaa728ee bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3942 eaa728ee bellard
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
3943 eaa728ee bellard
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
3944 eaa728ee bellard
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
3945 eaa728ee bellard
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
3946 eaa728ee bellard
    } else {
3947 eaa728ee bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
3948 eaa728ee bellard
        fptemp = pow(2.0, expdif - 50);
3949 eaa728ee bellard
        fpsrcop = (ST0 / ST1) / fptemp;
3950 eaa728ee bellard
        /* fpsrcop = integer obtained by chopping */
3951 eaa728ee bellard
        fpsrcop = (fpsrcop < 0.0) ?
3952 eaa728ee bellard
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
3953 eaa728ee bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
3954 eaa728ee bellard
    }
3955 eaa728ee bellard
}
3956 eaa728ee bellard
3957 eaa728ee bellard
void helper_fprem(void)
3958 eaa728ee bellard
{
3959 eaa728ee bellard
    CPU86_LDouble dblq, fpsrcop, fptemp;
3960 eaa728ee bellard
    CPU86_LDoubleU fpsrcop1, fptemp1;
3961 eaa728ee bellard
    int expdif;
3962 eaa728ee bellard
    signed long long int q;
3963 eaa728ee bellard
3964 eaa728ee bellard
    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3965 eaa728ee bellard
       ST0 = 0.0 / 0.0; /* NaN */
3966 eaa728ee bellard
       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3967 eaa728ee bellard
       return;
3968 eaa728ee bellard
    }
3969 eaa728ee bellard
3970 eaa728ee bellard
    fpsrcop = (CPU86_LDouble)ST0;
3971 eaa728ee bellard
    fptemp = (CPU86_LDouble)ST1;
3972 eaa728ee bellard
    fpsrcop1.d = fpsrcop;
3973 eaa728ee bellard
    fptemp1.d = fptemp;
3974 eaa728ee bellard
    expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3975 eaa728ee bellard
3976 eaa728ee bellard
    if (expdif < 0) {
3977 eaa728ee bellard
        /* optimisation? taken from the AMD docs */
3978 eaa728ee bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3979 eaa728ee bellard
        /* ST0 is unchanged */
3980 eaa728ee bellard
        return;
3981 eaa728ee bellard
    }
3982 eaa728ee bellard
3983 eaa728ee bellard
    if ( expdif < 53 ) {
3984 eaa728ee bellard
        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
3985 eaa728ee bellard
        /* round dblq towards zero */
3986 eaa728ee bellard
        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
3987 eaa728ee bellard
        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
3988 eaa728ee bellard
3989 eaa728ee bellard
        /* convert dblq to q by truncating towards zero */
3990 eaa728ee bellard
        if (dblq < 0.0)
3991 eaa728ee bellard
           q = (signed long long int)(-dblq);
3992 eaa728ee bellard
        else
3993 eaa728ee bellard
           q = (signed long long int)dblq;
3994 eaa728ee bellard
3995 eaa728ee bellard
        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3996 eaa728ee bellard
                                /* (C0,C3,C1) <-- (q2,q1,q0) */
3997 eaa728ee bellard
        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
3998 eaa728ee bellard
        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
3999 eaa728ee bellard
        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4000 eaa728ee bellard
    } else {
4001 eaa728ee bellard
        int N = 32 + (expdif % 32); /* as per AMD docs */
4002 eaa728ee bellard
        env->fpus |= 0x400;  /* C2 <-- 1 */
4003 eaa728ee bellard
        fptemp = pow(2.0, (double)(expdif - N));
4004 eaa728ee bellard
        fpsrcop = (ST0 / ST1) / fptemp;
4005 eaa728ee bellard
        /* fpsrcop = integer obtained by chopping */
4006 eaa728ee bellard
        fpsrcop = (fpsrcop < 0.0) ?
4007 eaa728ee bellard
                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4008 eaa728ee bellard
        ST0 -= (ST1 * fpsrcop * fptemp);
4009 eaa728ee bellard
    }
4010 eaa728ee bellard
}
4011 eaa728ee bellard
4012 eaa728ee bellard
void helper_fyl2xp1(void)
4013 eaa728ee bellard
{
4014 eaa728ee bellard
    CPU86_LDouble fptemp;
4015 eaa728ee bellard
4016 eaa728ee bellard
    fptemp = ST0;
4017 eaa728ee bellard
    if ((fptemp+1.0)>0.0) {
4018 eaa728ee bellard
        fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4019 eaa728ee bellard
        ST1 *= fptemp;
4020 eaa728ee bellard
        fpop();
4021 eaa728ee bellard
    } else {
4022 eaa728ee bellard
        env->fpus &= (~0x4700);
4023 eaa728ee bellard
        env->fpus |= 0x400;
4024 eaa728ee bellard
    }
4025 eaa728ee bellard
}
4026 eaa728ee bellard
4027 eaa728ee bellard
void helper_fsqrt(void)
4028 eaa728ee bellard
{
4029 eaa728ee bellard
    CPU86_LDouble fptemp;
4030 eaa728ee bellard
4031 eaa728ee bellard
    fptemp = ST0;
4032 eaa728ee bellard
    if (fptemp<0.0) {
4033 eaa728ee bellard
        env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4034 eaa728ee bellard
        env->fpus |= 0x400;
4035 eaa728ee bellard
    }
4036 eaa728ee bellard
    ST0 = sqrt(fptemp);
4037 eaa728ee bellard
}
4038 eaa728ee bellard
4039 eaa728ee bellard
void helper_fsincos(void)
4040 eaa728ee bellard
{
4041 eaa728ee bellard
    CPU86_LDouble fptemp;
4042 eaa728ee bellard
4043 eaa728ee bellard
    fptemp = ST0;
4044 eaa728ee bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4045 eaa728ee bellard
        env->fpus |= 0x400;
4046 eaa728ee bellard
    } else {
4047 eaa728ee bellard
        ST0 = sin(fptemp);
4048 eaa728ee bellard
        fpush();
4049 eaa728ee bellard
        ST0 = cos(fptemp);
4050 eaa728ee bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4051 eaa728ee bellard
        /* the above code is for  |arg| < 2**63 only */
4052 eaa728ee bellard
    }
4053 eaa728ee bellard
}
4054 eaa728ee bellard
4055 eaa728ee bellard
void helper_frndint(void)
4056 eaa728ee bellard
{
4057 eaa728ee bellard
    ST0 = floatx_round_to_int(ST0, &env->fp_status);
4058 eaa728ee bellard
}
4059 eaa728ee bellard
4060 eaa728ee bellard
void helper_fscale(void)
4061 eaa728ee bellard
{
4062 eaa728ee bellard
    ST0 = ldexp (ST0, (int)(ST1));
4063 eaa728ee bellard
}
4064 eaa728ee bellard
4065 eaa728ee bellard
void helper_fsin(void)
4066 eaa728ee bellard
{
4067 eaa728ee bellard
    CPU86_LDouble fptemp;
4068 eaa728ee bellard
4069 eaa728ee bellard
    fptemp = ST0;
4070 eaa728ee bellard
    if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4071 eaa728ee bellard
        env->fpus |= 0x400;
4072 eaa728ee bellard
    } else {
4073 eaa728ee bellard
        ST0 = sin(fptemp);
4074 eaa728ee bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4075 eaa728ee bellard
        /* the above code is for  |arg| < 2**53 only */
4076 eaa728ee bellard
    }
4077 eaa728ee bellard
}
4078 eaa728ee bellard
4079 eaa728ee bellard
void helper_fcos(void)
4080 eaa728ee bellard
{
4081 eaa728ee bellard
    CPU86_LDouble fptemp;
4082 eaa728ee bellard
4083 eaa728ee bellard
    fptemp = ST0;
4084 eaa728ee bellard
    if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4085 eaa728ee bellard
        env->fpus |= 0x400;
4086 eaa728ee bellard
    } else {
4087 eaa728ee bellard
        ST0 = cos(fptemp);
4088 eaa728ee bellard
        env->fpus &= (~0x400);  /* C2 <-- 0 */
4089 eaa728ee bellard
        /* the above code is for  |arg5 < 2**63 only */
4090 eaa728ee bellard
    }
4091 eaa728ee bellard
}
4092 eaa728ee bellard
4093 eaa728ee bellard
void helper_fxam_ST0(void)
4094 eaa728ee bellard
{
4095 eaa728ee bellard
    CPU86_LDoubleU temp;
4096 eaa728ee bellard
    int expdif;
4097 eaa728ee bellard
4098 eaa728ee bellard
    temp.d = ST0;
4099 eaa728ee bellard
4100 eaa728ee bellard
    env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4101 eaa728ee bellard
    if (SIGND(temp))
4102 eaa728ee bellard
        env->fpus |= 0x200; /* C1 <-- 1 */
4103 eaa728ee bellard
4104 eaa728ee bellard
    /* XXX: test fptags too */
4105 eaa728ee bellard
    expdif = EXPD(temp);
4106 eaa728ee bellard
    if (expdif == MAXEXPD) {
4107 eaa728ee bellard
#ifdef USE_X86LDOUBLE
4108 eaa728ee bellard
        if (MANTD(temp) == 0x8000000000000000ULL)
4109 eaa728ee bellard
#else
4110 eaa728ee bellard
        if (MANTD(temp) == 0)
4111 eaa728ee bellard
#endif
4112 eaa728ee bellard
            env->fpus |=  0x500 /*Infinity*/;
4113 eaa728ee bellard
        else
4114 eaa728ee bellard
            env->fpus |=  0x100 /*NaN*/;
4115 eaa728ee bellard
    } else if (expdif == 0) {
4116 eaa728ee bellard
        if (MANTD(temp) == 0)
4117 eaa728ee bellard
            env->fpus |=  0x4000 /*Zero*/;
4118 eaa728ee bellard
        else
4119 eaa728ee bellard
            env->fpus |= 0x4400 /*Denormal*/;
4120 eaa728ee bellard
    } else {
4121 eaa728ee bellard
        env->fpus |= 0x400;
4122 eaa728ee bellard
    }
4123 eaa728ee bellard
}
4124 eaa728ee bellard
4125 eaa728ee bellard
void helper_fstenv(target_ulong ptr, int data32)
4126 eaa728ee bellard
{
4127 eaa728ee bellard
    int fpus, fptag, exp, i;
4128 eaa728ee bellard
    uint64_t mant;
4129 eaa728ee bellard
    CPU86_LDoubleU tmp;
4130 eaa728ee bellard
4131 eaa728ee bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4132 eaa728ee bellard
    fptag = 0;
4133 eaa728ee bellard
    for (i=7; i>=0; i--) {
4134 eaa728ee bellard
        fptag <<= 2;
4135 eaa728ee bellard
        if (env->fptags[i]) {
4136 eaa728ee bellard
            fptag |= 3;
4137 eaa728ee bellard
        } else {
4138 eaa728ee bellard
            tmp.d = env->fpregs[i].d;
4139 eaa728ee bellard
            exp = EXPD(tmp);
4140 eaa728ee bellard
            mant = MANTD(tmp);
4141 eaa728ee bellard
            if (exp == 0 && mant == 0) {
4142 eaa728ee bellard
                /* zero */
4143 eaa728ee bellard
                fptag |= 1;
4144 eaa728ee bellard
            } else if (exp == 0 || exp == MAXEXPD
4145 eaa728ee bellard
#ifdef USE_X86LDOUBLE
4146 eaa728ee bellard
                       || (mant & (1LL << 63)) == 0
4147 eaa728ee bellard
#endif
4148 eaa728ee bellard
                       ) {
4149 eaa728ee bellard
                /* NaNs, infinity, denormal */
4150 eaa728ee bellard
                fptag |= 2;
4151 eaa728ee bellard
            }
4152 eaa728ee bellard
        }
4153 eaa728ee bellard
    }
4154 eaa728ee bellard
    if (data32) {
4155 eaa728ee bellard
        /* 32 bit */
4156 eaa728ee bellard
        stl(ptr, env->fpuc);
4157 eaa728ee bellard
        stl(ptr + 4, fpus);
4158 eaa728ee bellard
        stl(ptr + 8, fptag);
4159 eaa728ee bellard
        stl(ptr + 12, 0); /* fpip */
4160 eaa728ee bellard
        stl(ptr + 16, 0); /* fpcs */
4161 eaa728ee bellard
        stl(ptr + 20, 0); /* fpoo */
4162 eaa728ee bellard
        stl(ptr + 24, 0); /* fpos */
4163 eaa728ee bellard
    } else {
4164 eaa728ee bellard
        /* 16 bit */
4165 eaa728ee bellard
        stw(ptr, env->fpuc);
4166 eaa728ee bellard
        stw(ptr + 2, fpus);
4167 eaa728ee bellard
        stw(ptr + 4, fptag);
4168 eaa728ee bellard
        stw(ptr + 6, 0);
4169 eaa728ee bellard
        stw(ptr + 8, 0);
4170 eaa728ee bellard
        stw(ptr + 10, 0);
4171 eaa728ee bellard
        stw(ptr + 12, 0);
4172 eaa728ee bellard
    }
4173 eaa728ee bellard
}
4174 eaa728ee bellard
4175 eaa728ee bellard
void helper_fldenv(target_ulong ptr, int data32)
4176 eaa728ee bellard
{
4177 eaa728ee bellard
    int i, fpus, fptag;
4178 eaa728ee bellard
4179 eaa728ee bellard
    if (data32) {
4180 eaa728ee bellard
        env->fpuc = lduw(ptr);
4181 eaa728ee bellard
        fpus = lduw(ptr + 4);
4182 eaa728ee bellard
        fptag = lduw(ptr + 8);
4183 eaa728ee bellard
    }
4184 eaa728ee bellard
    else {
4185 eaa728ee bellard
        env->fpuc = lduw(ptr);
4186 eaa728ee bellard
        fpus = lduw(ptr + 2);
4187 eaa728ee bellard
        fptag = lduw(ptr + 4);
4188 eaa728ee bellard
    }
4189 eaa728ee bellard
    env->fpstt = (fpus >> 11) & 7;
4190 eaa728ee bellard
    env->fpus = fpus & ~0x3800;
4191 eaa728ee bellard
    for(i = 0;i < 8; i++) {
4192 eaa728ee bellard
        env->fptags[i] = ((fptag & 3) == 3);
4193 eaa728ee bellard
        fptag >>= 2;
4194 eaa728ee bellard
    }
4195 eaa728ee bellard
}
4196 eaa728ee bellard
4197 eaa728ee bellard
void helper_fsave(target_ulong ptr, int data32)
4198 eaa728ee bellard
{
4199 eaa728ee bellard
    CPU86_LDouble tmp;
4200 eaa728ee bellard
    int i;
4201 eaa728ee bellard
4202 eaa728ee bellard
    helper_fstenv(ptr, data32);
4203 eaa728ee bellard
4204 eaa728ee bellard
    ptr += (14 << data32);
4205 eaa728ee bellard
    for(i = 0;i < 8; i++) {
4206 eaa728ee bellard
        tmp = ST(i);
4207 eaa728ee bellard
        helper_fstt(tmp, ptr);
4208 eaa728ee bellard
        ptr += 10;
4209 eaa728ee bellard
    }
4210 eaa728ee bellard
4211 eaa728ee bellard
    /* fninit */
4212 eaa728ee bellard
    env->fpus = 0;
4213 eaa728ee bellard
    env->fpstt = 0;
4214 eaa728ee bellard
    env->fpuc = 0x37f;
4215 eaa728ee bellard
    env->fptags[0] = 1;
4216 eaa728ee bellard
    env->fptags[1] = 1;
4217 eaa728ee bellard
    env->fptags[2] = 1;
4218 eaa728ee bellard
    env->fptags[3] = 1;
4219 eaa728ee bellard
    env->fptags[4] = 1;
4220 eaa728ee bellard
    env->fptags[5] = 1;
4221 eaa728ee bellard
    env->fptags[6] = 1;
4222 eaa728ee bellard
    env->fptags[7] = 1;
4223 eaa728ee bellard
}
4224 eaa728ee bellard
4225 eaa728ee bellard
void helper_frstor(target_ulong ptr, int data32)
4226 eaa728ee bellard
{
4227 eaa728ee bellard
    CPU86_LDouble tmp;
4228 eaa728ee bellard
    int i;
4229 eaa728ee bellard
4230 eaa728ee bellard
    helper_fldenv(ptr, data32);
4231 eaa728ee bellard
    ptr += (14 << data32);
4232 eaa728ee bellard
4233 eaa728ee bellard
    for(i = 0;i < 8; i++) {
4234 eaa728ee bellard
        tmp = helper_fldt(ptr);
4235 eaa728ee bellard
        ST(i) = tmp;
4236 eaa728ee bellard
        ptr += 10;
4237 eaa728ee bellard
    }
4238 eaa728ee bellard
}
4239 eaa728ee bellard
4240 eaa728ee bellard
void helper_fxsave(target_ulong ptr, int data64)
4241 eaa728ee bellard
{
4242 eaa728ee bellard
    int fpus, fptag, i, nb_xmm_regs;
4243 eaa728ee bellard
    CPU86_LDouble tmp;
4244 eaa728ee bellard
    target_ulong addr;
4245 eaa728ee bellard
4246 eaa728ee bellard
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4247 eaa728ee bellard
    fptag = 0;
4248 eaa728ee bellard
    for(i = 0; i < 8; i++) {
4249 eaa728ee bellard
        fptag |= (env->fptags[i] << i);
4250 eaa728ee bellard
    }
4251 eaa728ee bellard
    stw(ptr, env->fpuc);
4252 eaa728ee bellard
    stw(ptr + 2, fpus);
4253 eaa728ee bellard
    stw(ptr + 4, fptag ^ 0xff);
4254 eaa728ee bellard
#ifdef TARGET_X86_64
4255 eaa728ee bellard
    if (data64) {
4256 eaa728ee bellard
        stq(ptr + 0x08, 0); /* rip */
4257 eaa728ee bellard
        stq(ptr + 0x10, 0); /* rdp */
4258 eaa728ee bellard
    } else 
4259 eaa728ee bellard
#endif
4260 eaa728ee bellard
    {
4261 eaa728ee bellard
        stl(ptr + 0x08, 0); /* eip */
4262 eaa728ee bellard
        stl(ptr + 0x0c, 0); /* sel  */
4263 eaa728ee bellard
        stl(ptr + 0x10, 0); /* dp */
4264 eaa728ee bellard
        stl(ptr + 0x14, 0); /* sel  */
4265 eaa728ee bellard
    }
4266 eaa728ee bellard
4267 eaa728ee bellard
    addr = ptr + 0x20;
4268 eaa728ee bellard
    for(i = 0;i < 8; i++) {
4269 eaa728ee bellard
        tmp = ST(i);
4270 eaa728ee bellard
        helper_fstt(tmp, addr);
4271 eaa728ee bellard
        addr += 16;
4272 eaa728ee bellard
    }
4273 eaa728ee bellard
4274 eaa728ee bellard
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4275 eaa728ee bellard
        /* XXX: finish it */
4276 eaa728ee bellard
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4277 eaa728ee bellard
        stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4278 eaa728ee bellard
        if (env->hflags & HF_CS64_MASK)
4279 eaa728ee bellard
            nb_xmm_regs = 16;
4280 eaa728ee bellard
        else
4281 eaa728ee bellard
            nb_xmm_regs = 8;
4282 eaa728ee bellard
        addr = ptr + 0xa0;
4283 eaa728ee bellard
        for(i = 0; i < nb_xmm_regs; i++) {
4284 eaa728ee bellard
            stq(addr, env->xmm_regs[i].XMM_Q(0));
4285 eaa728ee bellard
            stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4286 eaa728ee bellard
            addr += 16;
4287 eaa728ee bellard
        }
4288 eaa728ee bellard
    }
4289 eaa728ee bellard
}
4290 eaa728ee bellard
4291 eaa728ee bellard
void helper_fxrstor(target_ulong ptr, int data64)
4292 eaa728ee bellard
{
4293 eaa728ee bellard
    int i, fpus, fptag, nb_xmm_regs;
4294 eaa728ee bellard
    CPU86_LDouble tmp;
4295 eaa728ee bellard
    target_ulong addr;
4296 eaa728ee bellard
4297 eaa728ee bellard
    env->fpuc = lduw(ptr);
4298 eaa728ee bellard
    fpus = lduw(ptr + 2);
4299 eaa728ee bellard
    fptag = lduw(ptr + 4);
4300 eaa728ee bellard
    env->fpstt = (fpus >> 11) & 7;
4301 eaa728ee bellard
    env->fpus = fpus & ~0x3800;
4302 eaa728ee bellard
    fptag ^= 0xff;
4303 eaa728ee bellard
    for(i = 0;i < 8; i++) {
4304 eaa728ee bellard
        env->fptags[i] = ((fptag >> i) & 1);
4305 eaa728ee bellard
    }
4306 eaa728ee bellard
4307 eaa728ee bellard
    addr = ptr + 0x20;
4308 eaa728ee bellard
    for(i = 0;i < 8; i++) {
4309 eaa728ee bellard
        tmp = helper_fldt(addr);
4310 eaa728ee bellard
        ST(i) = tmp;
4311 eaa728ee bellard
        addr += 16;
4312 eaa728ee bellard
    }
4313 eaa728ee bellard
4314 eaa728ee bellard
    if (env->cr[4] & CR4_OSFXSR_MASK) {
4315 eaa728ee bellard
        /* XXX: finish it */
4316 eaa728ee bellard
        env->mxcsr = ldl(ptr + 0x18);
4317 eaa728ee bellard
        //ldl(ptr + 0x1c);
4318 eaa728ee bellard
        if (env->hflags & HF_CS64_MASK)
4319 eaa728ee bellard
            nb_xmm_regs = 16;
4320 eaa728ee bellard
        else
4321 eaa728ee bellard
            nb_xmm_regs = 8;
4322 eaa728ee bellard
        addr = ptr + 0xa0;
4323 eaa728ee bellard
        for(i = 0; i < nb_xmm_regs; i++) {
4324 eaa728ee bellard
            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4325 eaa728ee bellard
            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4326 eaa728ee bellard
            addr += 16;
4327 eaa728ee bellard
        }
4328 eaa728ee bellard
    }
4329 eaa728ee bellard
}
4330 eaa728ee bellard
4331 eaa728ee bellard
#ifndef USE_X86LDOUBLE
4332 eaa728ee bellard
4333 eaa728ee bellard
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4334 eaa728ee bellard
{
4335 eaa728ee bellard
    CPU86_LDoubleU temp;
4336 eaa728ee bellard
    int e;
4337 eaa728ee bellard
4338 eaa728ee bellard
    temp.d = f;
4339 eaa728ee bellard
    /* mantissa */
4340 eaa728ee bellard
    *pmant = (MANTD(temp) << 11) | (1LL << 63);
4341 eaa728ee bellard
    /* exponent + sign */
4342 eaa728ee bellard
    e = EXPD(temp) - EXPBIAS + 16383;
4343 eaa728ee bellard
    e |= SIGND(temp) >> 16;
4344 eaa728ee bellard
    *pexp = e;
4345 eaa728ee bellard
}
4346 eaa728ee bellard
4347 eaa728ee bellard
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4348 eaa728ee bellard
{
4349 eaa728ee bellard
    CPU86_LDoubleU temp;
4350 eaa728ee bellard
    int e;
4351 eaa728ee bellard
    uint64_t ll;
4352 eaa728ee bellard
4353 eaa728ee bellard
    /* XXX: handle overflow ? */
4354 eaa728ee bellard
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4355 eaa728ee bellard
    e |= (upper >> 4) & 0x800; /* sign */
4356 eaa728ee bellard
    ll = (mant >> 11) & ((1LL << 52) - 1);
4357 eaa728ee bellard
#ifdef __arm__
4358 eaa728ee bellard
    temp.l.upper = (e << 20) | (ll >> 32);
4359 eaa728ee bellard
    temp.l.lower = ll;
4360 eaa728ee bellard
#else
4361 eaa728ee bellard
    temp.ll = ll | ((uint64_t)e << 52);
4362 eaa728ee bellard
#endif
4363 eaa728ee bellard
    return temp.d;
4364 eaa728ee bellard
}
4365 eaa728ee bellard
4366 eaa728ee bellard
#else
4367 eaa728ee bellard
4368 eaa728ee bellard
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4369 eaa728ee bellard
{
4370 eaa728ee bellard
    CPU86_LDoubleU temp;
4371 eaa728ee bellard
4372 eaa728ee bellard
    temp.d = f;
4373 eaa728ee bellard
    *pmant = temp.l.lower;
4374 eaa728ee bellard
    *pexp = temp.l.upper;
4375 eaa728ee bellard
}
4376 eaa728ee bellard
4377 eaa728ee bellard
CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4378 eaa728ee bellard
{
4379 eaa728ee bellard
    CPU86_LDoubleU temp;
4380 eaa728ee bellard
4381 eaa728ee bellard
    temp.l.upper = upper;
4382 eaa728ee bellard
    temp.l.lower = mant;
4383 eaa728ee bellard
    return temp.d;
4384 eaa728ee bellard
}
4385 eaa728ee bellard
#endif
4386 eaa728ee bellard
4387 eaa728ee bellard
#ifdef TARGET_X86_64
4388 eaa728ee bellard
4389 eaa728ee bellard
//#define DEBUG_MULDIV
4390 eaa728ee bellard
4391 eaa728ee bellard
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4392 eaa728ee bellard
{
4393 eaa728ee bellard
    *plow += a;
4394 eaa728ee bellard
    /* carry test */
4395 eaa728ee bellard
    if (*plow < a)
4396 eaa728ee bellard
        (*phigh)++;
4397 eaa728ee bellard
    *phigh += b;
4398 eaa728ee bellard
}
4399 eaa728ee bellard
4400 eaa728ee bellard
static void neg128(uint64_t *plow, uint64_t *phigh)
4401 eaa728ee bellard
{
4402 eaa728ee bellard
    *plow = ~ *plow;
4403 eaa728ee bellard
    *phigh = ~ *phigh;
4404 eaa728ee bellard
    add128(plow, phigh, 1, 0);
4405 eaa728ee bellard
}
4406 eaa728ee bellard
4407 eaa728ee bellard
/* return TRUE if overflow */
4408 eaa728ee bellard
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4409 eaa728ee bellard
{
4410 eaa728ee bellard
    uint64_t q, r, a1, a0;
4411 eaa728ee bellard
    int i, qb, ab;
4412 eaa728ee bellard
4413 eaa728ee bellard
    a0 = *plow;
4414 eaa728ee bellard
    a1 = *phigh;
4415 eaa728ee bellard
    if (a1 == 0) {
4416 eaa728ee bellard
        q = a0 / b;
4417 eaa728ee bellard
        r = a0 % b;
4418 eaa728ee bellard
        *plow = q;
4419 eaa728ee bellard
        *phigh = r;
4420 eaa728ee bellard
    } else {
4421 eaa728ee bellard
        if (a1 >= b)
4422 eaa728ee bellard
            return 1;
4423 eaa728ee bellard
        /* XXX: use a better algorithm */
4424 eaa728ee bellard
        for(i = 0; i < 64; i++) {
4425 eaa728ee bellard
            ab = a1 >> 63;
4426 eaa728ee bellard
            a1 = (a1 << 1) | (a0 >> 63);
4427 eaa728ee bellard
            if (ab || a1 >= b) {
4428 eaa728ee bellard
                a1 -= b;
4429 eaa728ee bellard
                qb = 1;
4430 eaa728ee bellard
            } else {
4431 eaa728ee bellard
                qb = 0;
4432 eaa728ee bellard
            }
4433 eaa728ee bellard
            a0 = (a0 << 1) | qb;
4434 eaa728ee bellard
        }
4435 eaa728ee bellard
#if defined(DEBUG_MULDIV)
4436 eaa728ee bellard
        printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4437 eaa728ee bellard
               *phigh, *plow, b, a0, a1);
4438 eaa728ee bellard
#endif
4439 eaa728ee bellard
        *plow = a0;
4440 eaa728ee bellard
        *phigh = a1;
4441 eaa728ee bellard
    }
4442 eaa728ee bellard
    return 0;
4443 eaa728ee bellard
}
4444 eaa728ee bellard
4445 eaa728ee bellard
/* return TRUE if overflow */
4446 eaa728ee bellard
static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4447 eaa728ee bellard
{
4448 eaa728ee bellard
    int sa, sb;
4449 eaa728ee bellard
    sa = ((int64_t)*phigh < 0);
4450 eaa728ee bellard
    if (sa)
4451 eaa728ee bellard
        neg128(plow, phigh);
4452 eaa728ee bellard
    sb = (b < 0);
4453 eaa728ee bellard
    if (sb)
4454 eaa728ee bellard
        b = -b;
4455 eaa728ee bellard
    if (div64(plow, phigh, b) != 0)
4456 eaa728ee bellard
        return 1;
4457 eaa728ee bellard
    if (sa ^ sb) {
4458 eaa728ee bellard
        if (*plow > (1ULL << 63))
4459 eaa728ee bellard
            return 1;
4460 eaa728ee bellard
        *plow = - *plow;
4461 eaa728ee bellard
    } else {
4462 eaa728ee bellard
        if (*plow >= (1ULL << 63))
4463 eaa728ee bellard
            return 1;
4464 eaa728ee bellard
    }
4465 eaa728ee bellard
    if (sa)
4466 eaa728ee bellard
        *phigh = - *phigh;
4467 eaa728ee bellard
    return 0;
4468 eaa728ee bellard
}
4469 eaa728ee bellard
4470 eaa728ee bellard
void helper_mulq_EAX_T0(target_ulong t0)
4471 eaa728ee bellard
{
4472 eaa728ee bellard
    uint64_t r0, r1;
4473 eaa728ee bellard
4474 eaa728ee bellard
    mulu64(&r0, &r1, EAX, t0);
4475 eaa728ee bellard
    EAX = r0;
4476 eaa728ee bellard
    EDX = r1;
4477 eaa728ee bellard
    CC_DST = r0;
4478 eaa728ee bellard
    CC_SRC = r1;
4479 eaa728ee bellard
}
4480 eaa728ee bellard
4481 eaa728ee bellard
void helper_imulq_EAX_T0(target_ulong t0)
4482 eaa728ee bellard
{
4483 eaa728ee bellard
    uint64_t r0, r1;
4484 eaa728ee bellard
4485 eaa728ee bellard
    muls64(&r0, &r1, EAX, t0);
4486 eaa728ee bellard
    EAX = r0;
4487 eaa728ee bellard
    EDX = r1;
4488 eaa728ee bellard
    CC_DST = r0;
4489 eaa728ee bellard
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4490 eaa728ee bellard
}
4491 eaa728ee bellard
4492 eaa728ee bellard
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4493 eaa728ee bellard
{
4494 eaa728ee bellard
    uint64_t r0, r1;
4495 eaa728ee bellard
4496 eaa728ee bellard
    muls64(&r0, &r1, t0, t1);
4497 eaa728ee bellard
    CC_DST = r0;
4498 eaa728ee bellard
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4499 eaa728ee bellard
    return r0;
4500 eaa728ee bellard
}
4501 eaa728ee bellard
4502 eaa728ee bellard
void helper_divq_EAX(target_ulong t0)
4503 eaa728ee bellard
{
4504 eaa728ee bellard
    uint64_t r0, r1;
4505 eaa728ee bellard
    if (t0 == 0) {
4506 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
4507 eaa728ee bellard
    }
4508 eaa728ee bellard
    r0 = EAX;
4509 eaa728ee bellard
    r1 = EDX;
4510 eaa728ee bellard
    if (div64(&r0, &r1, t0))
4511 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
4512 eaa728ee bellard
    EAX = r0;
4513 eaa728ee bellard
    EDX = r1;
4514 eaa728ee bellard
}
4515 eaa728ee bellard
4516 eaa728ee bellard
void helper_idivq_EAX(target_ulong t0)
4517 eaa728ee bellard
{
4518 eaa728ee bellard
    uint64_t r0, r1;
4519 eaa728ee bellard
    if (t0 == 0) {
4520 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
4521 eaa728ee bellard
    }
4522 eaa728ee bellard
    r0 = EAX;
4523 eaa728ee bellard
    r1 = EDX;
4524 eaa728ee bellard
    if (idiv64(&r0, &r1, t0))
4525 eaa728ee bellard
        raise_exception(EXCP00_DIVZ);
4526 eaa728ee bellard
    EAX = r0;
4527 eaa728ee bellard
    EDX = r1;
4528 eaa728ee bellard
}
4529 eaa728ee bellard
#endif
4530 eaa728ee bellard
4531 94451178 bellard
static void do_hlt(void)
4532 eaa728ee bellard
{
4533 eaa728ee bellard
    env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4534 ce5232c5 bellard
    env->halted = 1;
4535 eaa728ee bellard
    env->exception_index = EXCP_HLT;
4536 eaa728ee bellard
    cpu_loop_exit();
4537 eaa728ee bellard
}
4538 eaa728ee bellard
4539 94451178 bellard
void helper_hlt(int next_eip_addend)
4540 94451178 bellard
{
4541 94451178 bellard
    helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4542 94451178 bellard
    EIP += next_eip_addend;
4543 94451178 bellard
    
4544 94451178 bellard
    do_hlt();
4545 94451178 bellard
}
4546 94451178 bellard
4547 eaa728ee bellard
void helper_monitor(target_ulong ptr)
4548 eaa728ee bellard
{
4549 eaa728ee bellard
    if ((uint32_t)ECX != 0)
4550 eaa728ee bellard
        raise_exception(EXCP0D_GPF);
4551 eaa728ee bellard
    /* XXX: store address ? */
4552 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4553 eaa728ee bellard
}
4554 eaa728ee bellard
4555 94451178 bellard
void helper_mwait(int next_eip_addend)
4556 eaa728ee bellard
{
4557 eaa728ee bellard
    if ((uint32_t)ECX != 0)
4558 eaa728ee bellard
        raise_exception(EXCP0D_GPF);
4559 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4560 94451178 bellard
    EIP += next_eip_addend;
4561 94451178 bellard
4562 eaa728ee bellard
    /* XXX: not complete but not completely erroneous */
4563 eaa728ee bellard
    if (env->cpu_index != 0 || env->next_cpu != NULL) {
4564 eaa728ee bellard
        /* more than one CPU: do not sleep because another CPU may
4565 eaa728ee bellard
           wake this one */
4566 eaa728ee bellard
    } else {
4567 94451178 bellard
        do_hlt();
4568 eaa728ee bellard
    }
4569 eaa728ee bellard
}
4570 eaa728ee bellard
4571 eaa728ee bellard
void helper_debug(void)
4572 eaa728ee bellard
{
4573 eaa728ee bellard
    env->exception_index = EXCP_DEBUG;
4574 eaa728ee bellard
    cpu_loop_exit();
4575 eaa728ee bellard
}
4576 eaa728ee bellard
4577 eaa728ee bellard
void helper_raise_interrupt(int intno, int next_eip_addend)
4578 eaa728ee bellard
{
4579 eaa728ee bellard
    raise_interrupt(intno, 1, 0, next_eip_addend);
4580 eaa728ee bellard
}
4581 eaa728ee bellard
4582 eaa728ee bellard
void helper_raise_exception(int exception_index)
4583 eaa728ee bellard
{
4584 eaa728ee bellard
    raise_exception(exception_index);
4585 eaa728ee bellard
}
4586 eaa728ee bellard
4587 eaa728ee bellard
void helper_cli(void)
4588 eaa728ee bellard
{
4589 eaa728ee bellard
    env->eflags &= ~IF_MASK;
4590 eaa728ee bellard
}
4591 eaa728ee bellard
4592 eaa728ee bellard
void helper_sti(void)
4593 eaa728ee bellard
{
4594 eaa728ee bellard
    env->eflags |= IF_MASK;
4595 eaa728ee bellard
}
4596 eaa728ee bellard
4597 eaa728ee bellard
#if 0
4598 eaa728ee bellard
/* vm86plus instructions */
4599 eaa728ee bellard
void helper_cli_vm(void)
4600 eaa728ee bellard
{
4601 eaa728ee bellard
    env->eflags &= ~VIF_MASK;
4602 eaa728ee bellard
}
4603 eaa728ee bellard

4604 eaa728ee bellard
void helper_sti_vm(void)
4605 eaa728ee bellard
{
4606 eaa728ee bellard
    env->eflags |= VIF_MASK;
4607 eaa728ee bellard
    if (env->eflags & VIP_MASK) {
4608 eaa728ee bellard
        raise_exception(EXCP0D_GPF);
4609 eaa728ee bellard
    }
4610 eaa728ee bellard
}
4611 eaa728ee bellard
#endif
4612 eaa728ee bellard
4613 eaa728ee bellard
void helper_set_inhibit_irq(void)
4614 eaa728ee bellard
{
4615 eaa728ee bellard
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4616 eaa728ee bellard
}
4617 eaa728ee bellard
4618 eaa728ee bellard
void helper_reset_inhibit_irq(void)
4619 eaa728ee bellard
{
4620 eaa728ee bellard
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4621 eaa728ee bellard
}
4622 eaa728ee bellard
4623 eaa728ee bellard
void helper_boundw(target_ulong a0, int v)
4624 eaa728ee bellard
{
4625 eaa728ee bellard
    int low, high;
4626 eaa728ee bellard
    low = ldsw(a0);
4627 eaa728ee bellard
    high = ldsw(a0 + 2);
4628 eaa728ee bellard
    v = (int16_t)v;
4629 eaa728ee bellard
    if (v < low || v > high) {
4630 eaa728ee bellard
        raise_exception(EXCP05_BOUND);
4631 eaa728ee bellard
    }
4632 eaa728ee bellard
    FORCE_RET();
4633 eaa728ee bellard
}
4634 eaa728ee bellard
4635 eaa728ee bellard
void helper_boundl(target_ulong a0, int v)
4636 eaa728ee bellard
{
4637 eaa728ee bellard
    int low, high;
4638 eaa728ee bellard
    low = ldl(a0);
4639 eaa728ee bellard
    high = ldl(a0 + 4);
4640 eaa728ee bellard
    if (v < low || v > high) {
4641 eaa728ee bellard
        raise_exception(EXCP05_BOUND);
4642 eaa728ee bellard
    }
4643 eaa728ee bellard
    FORCE_RET();
4644 eaa728ee bellard
}
4645 eaa728ee bellard
4646 eaa728ee bellard
static float approx_rsqrt(float a)
4647 eaa728ee bellard
{
4648 eaa728ee bellard
    return 1.0 / sqrt(a);
4649 eaa728ee bellard
}
4650 eaa728ee bellard
4651 eaa728ee bellard
static float approx_rcp(float a)
4652 eaa728ee bellard
{
4653 eaa728ee bellard
    return 1.0 / a;
4654 eaa728ee bellard
}
4655 eaa728ee bellard
4656 eaa728ee bellard
#if !defined(CONFIG_USER_ONLY)
4657 eaa728ee bellard
4658 eaa728ee bellard
#define MMUSUFFIX _mmu
4659 eaa728ee bellard
4660 eaa728ee bellard
#define SHIFT 0
4661 eaa728ee bellard
#include "softmmu_template.h"
4662 eaa728ee bellard
4663 eaa728ee bellard
#define SHIFT 1
4664 eaa728ee bellard
#include "softmmu_template.h"
4665 eaa728ee bellard
4666 eaa728ee bellard
#define SHIFT 2
4667 eaa728ee bellard
#include "softmmu_template.h"
4668 eaa728ee bellard
4669 eaa728ee bellard
#define SHIFT 3
4670 eaa728ee bellard
#include "softmmu_template.h"
4671 eaa728ee bellard
4672 eaa728ee bellard
#endif
4673 eaa728ee bellard
4674 eaa728ee bellard
/* try to fill the TLB and return an exception if error. If retaddr is
4675 eaa728ee bellard
   NULL, it means that the function was called in C code (i.e. not
4676 eaa728ee bellard
   from generated code or from helper.c) */
4677 eaa728ee bellard
/* XXX: fix it to restore all registers */
4678 eaa728ee bellard
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4679 eaa728ee bellard
{
4680 eaa728ee bellard
    TranslationBlock *tb;
4681 eaa728ee bellard
    int ret;
4682 eaa728ee bellard
    unsigned long pc;
4683 eaa728ee bellard
    CPUX86State *saved_env;
4684 eaa728ee bellard
4685 eaa728ee bellard
    /* XXX: hack to restore env in all cases, even if not called from
4686 eaa728ee bellard
       generated code */
4687 eaa728ee bellard
    saved_env = env;
4688 eaa728ee bellard
    env = cpu_single_env;
4689 eaa728ee bellard
4690 eaa728ee bellard
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4691 eaa728ee bellard
    if (ret) {
4692 eaa728ee bellard
        if (retaddr) {
4693 eaa728ee bellard
            /* now we have a real cpu fault */
4694 eaa728ee bellard
            pc = (unsigned long)retaddr;
4695 eaa728ee bellard
            tb = tb_find_pc(pc);
4696 eaa728ee bellard
            if (tb) {
4697 eaa728ee bellard
                /* the PC is inside the translated code. It means that we have
4698 eaa728ee bellard
                   a virtual CPU fault */
4699 eaa728ee bellard
                cpu_restore_state(tb, env, pc, NULL);
4700 eaa728ee bellard
            }
4701 eaa728ee bellard
        }
4702 872929aa bellard
        raise_exception_err(env->exception_index, env->error_code);
4703 eaa728ee bellard
    }
4704 eaa728ee bellard
    env = saved_env;
4705 eaa728ee bellard
}
4706 eaa728ee bellard
4707 eaa728ee bellard
4708 eaa728ee bellard
/* Secure Virtual Machine helpers */
4709 eaa728ee bellard
4710 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
4711 eaa728ee bellard
4712 db620f46 bellard
void helper_vmrun(int aflag, int next_eip_addend)
4713 eaa728ee bellard
{ 
4714 eaa728ee bellard
}
4715 eaa728ee bellard
void helper_vmmcall(void) 
4716 eaa728ee bellard
{ 
4717 eaa728ee bellard
}
4718 914178d3 bellard
void helper_vmload(int aflag)
4719 eaa728ee bellard
{ 
4720 eaa728ee bellard
}
4721 914178d3 bellard
void helper_vmsave(int aflag)
4722 eaa728ee bellard
{ 
4723 eaa728ee bellard
}
4724 872929aa bellard
void helper_stgi(void)
4725 872929aa bellard
{
4726 872929aa bellard
}
4727 872929aa bellard
void helper_clgi(void)
4728 872929aa bellard
{
4729 872929aa bellard
}
4730 eaa728ee bellard
void helper_skinit(void) 
4731 eaa728ee bellard
{ 
4732 eaa728ee bellard
}
4733 914178d3 bellard
void helper_invlpga(int aflag)
4734 eaa728ee bellard
{ 
4735 eaa728ee bellard
}
4736 eaa728ee bellard
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4737 eaa728ee bellard
{ 
4738 eaa728ee bellard
}
4739 eaa728ee bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4740 eaa728ee bellard
{
4741 eaa728ee bellard
}
4742 eaa728ee bellard
4743 eaa728ee bellard
void helper_svm_check_io(uint32_t port, uint32_t param, 
4744 eaa728ee bellard
                         uint32_t next_eip_addend)
4745 eaa728ee bellard
{
4746 eaa728ee bellard
}
4747 eaa728ee bellard
#else
4748 eaa728ee bellard
4749 872929aa bellard
static inline void svm_save_seg(target_phys_addr_t addr,
4750 872929aa bellard
                                const SegmentCache *sc)
4751 eaa728ee bellard
{
4752 872929aa bellard
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4753 872929aa bellard
             sc->selector);
4754 872929aa bellard
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
4755 872929aa bellard
             sc->base);
4756 872929aa bellard
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4757 872929aa bellard
             sc->limit);
4758 872929aa bellard
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4759 e72210e1 bellard
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
4760 872929aa bellard
}
4761 872929aa bellard
                                
4762 872929aa bellard
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4763 872929aa bellard
{
4764 872929aa bellard
    unsigned int flags;
4765 872929aa bellard
4766 872929aa bellard
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4767 872929aa bellard
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4768 872929aa bellard
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4769 872929aa bellard
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4770 872929aa bellard
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4771 eaa728ee bellard
}
4772 eaa728ee bellard
4773 872929aa bellard
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4774 872929aa bellard
                                      CPUState *env, int seg_reg)
4775 eaa728ee bellard
{
4776 872929aa bellard
    SegmentCache sc1, *sc = &sc1;
4777 872929aa bellard
    svm_load_seg(addr, sc);
4778 872929aa bellard
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4779 872929aa bellard
                           sc->base, sc->limit, sc->flags);
4780 eaa728ee bellard
}
4781 eaa728ee bellard
4782 db620f46 bellard
void helper_vmrun(int aflag, int next_eip_addend)
4783 eaa728ee bellard
{
4784 eaa728ee bellard
    target_ulong addr;
4785 eaa728ee bellard
    uint32_t event_inj;
4786 eaa728ee bellard
    uint32_t int_ctl;
4787 eaa728ee bellard
4788 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4789 872929aa bellard
4790 914178d3 bellard
    if (aflag == 2)
4791 914178d3 bellard
        addr = EAX;
4792 914178d3 bellard
    else
4793 914178d3 bellard
        addr = (uint32_t)EAX;
4794 914178d3 bellard
4795 eaa728ee bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
4796 eaa728ee bellard
        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4797 eaa728ee bellard
4798 eaa728ee bellard
    env->vm_vmcb = addr;
4799 eaa728ee bellard
4800 eaa728ee bellard
    /* save the current CPU state in the hsave page */
4801 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4802 eaa728ee bellard
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4803 eaa728ee bellard
4804 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4805 eaa728ee bellard
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4806 eaa728ee bellard
4807 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4808 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4809 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4810 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4811 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4812 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4813 eaa728ee bellard
4814 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4815 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4816 eaa728ee bellard
4817 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4818 872929aa bellard
                  &env->segs[R_ES]);
4819 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4820 872929aa bellard
                 &env->segs[R_CS]);
4821 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4822 872929aa bellard
                 &env->segs[R_SS]);
4823 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4824 872929aa bellard
                 &env->segs[R_DS]);
4825 eaa728ee bellard
4826 db620f46 bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
4827 db620f46 bellard
             EIP + next_eip_addend);
4828 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4829 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4830 eaa728ee bellard
4831 eaa728ee bellard
    /* load the interception bitmaps so we do not need to access the
4832 eaa728ee bellard
       vmcb in svm mode */
4833 872929aa bellard
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4834 eaa728ee bellard
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4835 eaa728ee bellard
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4836 eaa728ee bellard
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4837 eaa728ee bellard
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4838 eaa728ee bellard
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4839 eaa728ee bellard
4840 872929aa bellard
    /* enable intercepts */
4841 872929aa bellard
    env->hflags |= HF_SVMI_MASK;
4842 872929aa bellard
4843 33c263df bellard
    env->tsc_offset = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.tsc_offset));
4844 33c263df bellard
4845 eaa728ee bellard
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4846 eaa728ee bellard
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4847 eaa728ee bellard
4848 eaa728ee bellard
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4849 eaa728ee bellard
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4850 eaa728ee bellard
4851 eaa728ee bellard
    /* clear exit_info_2 so we behave like the real hardware */
4852 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
4853 eaa728ee bellard
4854 eaa728ee bellard
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4855 eaa728ee bellard
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4856 eaa728ee bellard
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4857 eaa728ee bellard
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4858 eaa728ee bellard
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4859 db620f46 bellard
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
4860 eaa728ee bellard
    if (int_ctl & V_INTR_MASKING_MASK) {
4861 db620f46 bellard
        env->v_tpr = int_ctl & V_TPR_MASK;
4862 db620f46 bellard
        env->hflags2 |= HF2_VINTR_MASK;
4863 eaa728ee bellard
        if (env->eflags & IF_MASK)
4864 db620f46 bellard
            env->hflags2 |= HF2_HIF_MASK;
4865 eaa728ee bellard
    }
4866 eaa728ee bellard
4867 5efc27bb bellard
    cpu_load_efer(env, 
4868 5efc27bb bellard
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
4869 eaa728ee bellard
    env->eflags = 0;
4870 eaa728ee bellard
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4871 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4872 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
4873 eaa728ee bellard
4874 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4875 872929aa bellard
                       env, R_ES);
4876 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4877 872929aa bellard
                       env, R_CS);
4878 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4879 872929aa bellard
                       env, R_SS);
4880 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4881 872929aa bellard
                       env, R_DS);
4882 eaa728ee bellard
4883 eaa728ee bellard
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4884 eaa728ee bellard
    env->eip = EIP;
4885 eaa728ee bellard
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4886 eaa728ee bellard
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4887 eaa728ee bellard
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4888 eaa728ee bellard
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4889 eaa728ee bellard
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4890 eaa728ee bellard
4891 eaa728ee bellard
    /* FIXME: guest state consistency checks */
4892 eaa728ee bellard
4893 eaa728ee bellard
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4894 eaa728ee bellard
        case TLB_CONTROL_DO_NOTHING:
4895 eaa728ee bellard
            break;
4896 eaa728ee bellard
        case TLB_CONTROL_FLUSH_ALL_ASID:
4897 eaa728ee bellard
            /* FIXME: this is not 100% correct but should work for now */
4898 eaa728ee bellard
            tlb_flush(env, 1);
4899 eaa728ee bellard
        break;
4900 eaa728ee bellard
    }
4901 eaa728ee bellard
4902 960540b4 bellard
    env->hflags2 |= HF2_GIF_MASK;
4903 eaa728ee bellard
4904 db620f46 bellard
    if (int_ctl & V_IRQ_MASK) {
4905 db620f46 bellard
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4906 db620f46 bellard
    }
4907 db620f46 bellard
4908 eaa728ee bellard
    /* maybe we need to inject an event */
4909 eaa728ee bellard
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4910 eaa728ee bellard
    if (event_inj & SVM_EVTINJ_VALID) {
4911 eaa728ee bellard
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4912 eaa728ee bellard
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4913 eaa728ee bellard
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4914 eaa728ee bellard
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4915 eaa728ee bellard
4916 eaa728ee bellard
        if (loglevel & CPU_LOG_TB_IN_ASM)
4917 eaa728ee bellard
            fprintf(logfile, "Injecting(%#hx): ", valid_err);
4918 eaa728ee bellard
        /* FIXME: need to implement valid_err */
4919 eaa728ee bellard
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4920 eaa728ee bellard
        case SVM_EVTINJ_TYPE_INTR:
4921 eaa728ee bellard
                env->exception_index = vector;
4922 eaa728ee bellard
                env->error_code = event_inj_err;
4923 eaa728ee bellard
                env->exception_is_int = 0;
4924 eaa728ee bellard
                env->exception_next_eip = -1;
4925 eaa728ee bellard
                if (loglevel & CPU_LOG_TB_IN_ASM)
4926 eaa728ee bellard
                    fprintf(logfile, "INTR");
4927 db620f46 bellard
                /* XXX: is it always correct ? */
4928 db620f46 bellard
                do_interrupt(vector, 0, 0, 0, 1);
4929 eaa728ee bellard
                break;
4930 eaa728ee bellard
        case SVM_EVTINJ_TYPE_NMI:
4931 db620f46 bellard
                env->exception_index = EXCP02_NMI;
4932 eaa728ee bellard
                env->error_code = event_inj_err;
4933 eaa728ee bellard
                env->exception_is_int = 0;
4934 eaa728ee bellard
                env->exception_next_eip = EIP;
4935 eaa728ee bellard
                if (loglevel & CPU_LOG_TB_IN_ASM)
4936 eaa728ee bellard
                    fprintf(logfile, "NMI");
4937 db620f46 bellard
                cpu_loop_exit();
4938 eaa728ee bellard
                break;
4939 eaa728ee bellard
        case SVM_EVTINJ_TYPE_EXEPT:
4940 eaa728ee bellard
                env->exception_index = vector;
4941 eaa728ee bellard
                env->error_code = event_inj_err;
4942 eaa728ee bellard
                env->exception_is_int = 0;
4943 eaa728ee bellard
                env->exception_next_eip = -1;
4944 eaa728ee bellard
                if (loglevel & CPU_LOG_TB_IN_ASM)
4945 eaa728ee bellard
                    fprintf(logfile, "EXEPT");
4946 db620f46 bellard
                cpu_loop_exit();
4947 eaa728ee bellard
                break;
4948 eaa728ee bellard
        case SVM_EVTINJ_TYPE_SOFT:
4949 eaa728ee bellard
                env->exception_index = vector;
4950 eaa728ee bellard
                env->error_code = event_inj_err;
4951 eaa728ee bellard
                env->exception_is_int = 1;
4952 eaa728ee bellard
                env->exception_next_eip = EIP;
4953 eaa728ee bellard
                if (loglevel & CPU_LOG_TB_IN_ASM)
4954 eaa728ee bellard
                    fprintf(logfile, "SOFT");
4955 db620f46 bellard
                cpu_loop_exit();
4956 eaa728ee bellard
                break;
4957 eaa728ee bellard
        }
4958 eaa728ee bellard
        if (loglevel & CPU_LOG_TB_IN_ASM)
4959 eaa728ee bellard
            fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
4960 eaa728ee bellard
    }
4961 eaa728ee bellard
}
4962 eaa728ee bellard
4963 eaa728ee bellard
void helper_vmmcall(void)
4964 eaa728ee bellard
{
4965 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
4966 872929aa bellard
    raise_exception(EXCP06_ILLOP);
4967 eaa728ee bellard
}
4968 eaa728ee bellard
4969 914178d3 bellard
void helper_vmload(int aflag)
4970 eaa728ee bellard
{
4971 eaa728ee bellard
    target_ulong addr;
4972 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
4973 872929aa bellard
4974 914178d3 bellard
    if (aflag == 2)
4975 914178d3 bellard
        addr = EAX;
4976 914178d3 bellard
    else
4977 914178d3 bellard
        addr = (uint32_t)EAX;
4978 914178d3 bellard
4979 eaa728ee bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
4980 eaa728ee bellard
        fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4981 eaa728ee bellard
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4982 eaa728ee bellard
                env->segs[R_FS].base);
4983 eaa728ee bellard
4984 872929aa bellard
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
4985 872929aa bellard
                       env, R_FS);
4986 872929aa bellard
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
4987 872929aa bellard
                       env, R_GS);
4988 872929aa bellard
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
4989 872929aa bellard
                 &env->tr);
4990 872929aa bellard
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
4991 872929aa bellard
                 &env->ldt);
4992 eaa728ee bellard
4993 eaa728ee bellard
#ifdef TARGET_X86_64
4994 eaa728ee bellard
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
4995 eaa728ee bellard
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
4996 eaa728ee bellard
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
4997 eaa728ee bellard
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
4998 eaa728ee bellard
#endif
4999 eaa728ee bellard
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
5000 eaa728ee bellard
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
5001 eaa728ee bellard
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
5002 eaa728ee bellard
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
5003 eaa728ee bellard
}
5004 eaa728ee bellard
5005 914178d3 bellard
void helper_vmsave(int aflag)
5006 eaa728ee bellard
{
5007 eaa728ee bellard
    target_ulong addr;
5008 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5009 914178d3 bellard
5010 914178d3 bellard
    if (aflag == 2)
5011 914178d3 bellard
        addr = EAX;
5012 914178d3 bellard
    else
5013 914178d3 bellard
        addr = (uint32_t)EAX;
5014 914178d3 bellard
5015 eaa728ee bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
5016 eaa728ee bellard
        fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5017 eaa728ee bellard
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5018 eaa728ee bellard
                env->segs[R_FS].base);
5019 eaa728ee bellard
5020 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5021 872929aa bellard
                 &env->segs[R_FS]);
5022 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5023 872929aa bellard
                 &env->segs[R_GS]);
5024 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5025 872929aa bellard
                 &env->tr);
5026 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5027 872929aa bellard
                 &env->ldt);
5028 eaa728ee bellard
5029 eaa728ee bellard
#ifdef TARGET_X86_64
5030 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
5031 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
5032 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
5033 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
5034 eaa728ee bellard
#endif
5035 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
5036 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
5037 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
5038 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
5039 eaa728ee bellard
}
5040 eaa728ee bellard
5041 872929aa bellard
void helper_stgi(void)
5042 872929aa bellard
{
5043 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5044 db620f46 bellard
    env->hflags2 |= HF2_GIF_MASK;
5045 872929aa bellard
}
5046 872929aa bellard
5047 872929aa bellard
void helper_clgi(void)
5048 872929aa bellard
{
5049 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5050 db620f46 bellard
    env->hflags2 &= ~HF2_GIF_MASK;
5051 872929aa bellard
}
5052 872929aa bellard
5053 eaa728ee bellard
void helper_skinit(void)
5054 eaa728ee bellard
{
5055 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5056 872929aa bellard
    /* XXX: not implemented */
5057 872929aa bellard
    raise_exception(EXCP06_ILLOP);
5058 eaa728ee bellard
}
5059 eaa728ee bellard
5060 914178d3 bellard
void helper_invlpga(int aflag)
5061 eaa728ee bellard
{
5062 914178d3 bellard
    target_ulong addr;
5063 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5064 914178d3 bellard
    
5065 914178d3 bellard
    if (aflag == 2)
5066 914178d3 bellard
        addr = EAX;
5067 914178d3 bellard
    else
5068 914178d3 bellard
        addr = (uint32_t)EAX;
5069 914178d3 bellard
5070 914178d3 bellard
    /* XXX: could use the ASID to see if it is needed to do the
5071 914178d3 bellard
       flush */
5072 914178d3 bellard
    tlb_flush_page(env, addr);
5073 eaa728ee bellard
}
5074 eaa728ee bellard
5075 eaa728ee bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5076 eaa728ee bellard
{
5077 872929aa bellard
    if (likely(!(env->hflags & HF_SVMI_MASK)))
5078 872929aa bellard
        return;
5079 eaa728ee bellard
    switch(type) {
5080 eaa728ee bellard
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5081 872929aa bellard
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5082 eaa728ee bellard
            helper_vmexit(type, param);
5083 eaa728ee bellard
        }
5084 eaa728ee bellard
        break;
5085 872929aa bellard
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5086 872929aa bellard
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
5087 eaa728ee bellard
            helper_vmexit(type, param);
5088 eaa728ee bellard
        }
5089 eaa728ee bellard
        break;
5090 872929aa bellard
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
5091 872929aa bellard
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
5092 eaa728ee bellard
            helper_vmexit(type, param);
5093 eaa728ee bellard
        }
5094 eaa728ee bellard
        break;
5095 872929aa bellard
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
5096 872929aa bellard
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
5097 eaa728ee bellard
            helper_vmexit(type, param);
5098 eaa728ee bellard
        }
5099 eaa728ee bellard
        break;
5100 872929aa bellard
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
5101 872929aa bellard
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
5102 eaa728ee bellard
            helper_vmexit(type, param);
5103 eaa728ee bellard
        }
5104 eaa728ee bellard
        break;
5105 eaa728ee bellard
    case SVM_EXIT_MSR:
5106 872929aa bellard
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5107 eaa728ee bellard
            /* FIXME: this should be read in at vmrun (faster this way?) */
5108 eaa728ee bellard
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5109 eaa728ee bellard
            uint32_t t0, t1;
5110 eaa728ee bellard
            switch((uint32_t)ECX) {
5111 eaa728ee bellard
            case 0 ... 0x1fff:
5112 eaa728ee bellard
                t0 = (ECX * 2) % 8;
5113 eaa728ee bellard
                t1 = ECX / 8;
5114 eaa728ee bellard
                break;
5115 eaa728ee bellard
            case 0xc0000000 ... 0xc0001fff:
5116 eaa728ee bellard
                t0 = (8192 + ECX - 0xc0000000) * 2;
5117 eaa728ee bellard
                t1 = (t0 / 8);
5118 eaa728ee bellard
                t0 %= 8;
5119 eaa728ee bellard
                break;
5120 eaa728ee bellard
            case 0xc0010000 ... 0xc0011fff:
5121 eaa728ee bellard
                t0 = (16384 + ECX - 0xc0010000) * 2;
5122 eaa728ee bellard
                t1 = (t0 / 8);
5123 eaa728ee bellard
                t0 %= 8;
5124 eaa728ee bellard
                break;
5125 eaa728ee bellard
            default:
5126 eaa728ee bellard
                helper_vmexit(type, param);
5127 eaa728ee bellard
                t0 = 0;
5128 eaa728ee bellard
                t1 = 0;
5129 eaa728ee bellard
                break;
5130 eaa728ee bellard
            }
5131 eaa728ee bellard
            if (ldub_phys(addr + t1) & ((1 << param) << t0))
5132 eaa728ee bellard
                helper_vmexit(type, param);
5133 eaa728ee bellard
        }
5134 eaa728ee bellard
        break;
5135 eaa728ee bellard
    default:
5136 872929aa bellard
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5137 eaa728ee bellard
            helper_vmexit(type, param);
5138 eaa728ee bellard
        }
5139 eaa728ee bellard
        break;
5140 eaa728ee bellard
    }
5141 eaa728ee bellard
}
5142 eaa728ee bellard
5143 eaa728ee bellard
void helper_svm_check_io(uint32_t port, uint32_t param, 
5144 eaa728ee bellard
                         uint32_t next_eip_addend)
5145 eaa728ee bellard
{
5146 872929aa bellard
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5147 eaa728ee bellard
        /* FIXME: this should be read in at vmrun (faster this way?) */
5148 eaa728ee bellard
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5149 eaa728ee bellard
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5150 eaa728ee bellard
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5151 eaa728ee bellard
            /* next EIP */
5152 eaa728ee bellard
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5153 eaa728ee bellard
                     env->eip + next_eip_addend);
5154 eaa728ee bellard
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5155 eaa728ee bellard
        }
5156 eaa728ee bellard
    }
5157 eaa728ee bellard
}
5158 eaa728ee bellard
5159 eaa728ee bellard
/* Note: currently only 32 bits of exit_code are used */
5160 eaa728ee bellard
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5161 eaa728ee bellard
{
5162 eaa728ee bellard
    uint32_t int_ctl;
5163 eaa728ee bellard
5164 eaa728ee bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
5165 eaa728ee bellard
        fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5166 eaa728ee bellard
                exit_code, exit_info_1,
5167 eaa728ee bellard
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5168 eaa728ee bellard
                EIP);
5169 eaa728ee bellard
5170 eaa728ee bellard
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5171 eaa728ee bellard
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5172 eaa728ee bellard
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5173 eaa728ee bellard
    } else {
5174 eaa728ee bellard
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5175 eaa728ee bellard
    }
5176 eaa728ee bellard
5177 eaa728ee bellard
    /* Save the VM state in the vmcb */
5178 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5179 872929aa bellard
                 &env->segs[R_ES]);
5180 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5181 872929aa bellard
                 &env->segs[R_CS]);
5182 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5183 872929aa bellard
                 &env->segs[R_SS]);
5184 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5185 872929aa bellard
                 &env->segs[R_DS]);
5186 eaa728ee bellard
5187 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5188 eaa728ee bellard
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5189 eaa728ee bellard
5190 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5191 eaa728ee bellard
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5192 eaa728ee bellard
5193 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5194 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5195 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5196 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5197 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5198 eaa728ee bellard
5199 db620f46 bellard
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5200 db620f46 bellard
    int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
5201 db620f46 bellard
    int_ctl |= env->v_tpr & V_TPR_MASK;
5202 db620f46 bellard
    if (env->interrupt_request & CPU_INTERRUPT_VIRQ)
5203 db620f46 bellard
        int_ctl |= V_IRQ_MASK;
5204 db620f46 bellard
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5205 eaa728ee bellard
5206 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5207 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5208 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5209 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5210 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5211 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5212 eaa728ee bellard
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5213 eaa728ee bellard
5214 eaa728ee bellard
    /* Reload the host state from vm_hsave */
5215 db620f46 bellard
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5216 872929aa bellard
    env->hflags &= ~HF_SVMI_MASK;
5217 eaa728ee bellard
    env->intercept = 0;
5218 eaa728ee bellard
    env->intercept_exceptions = 0;
5219 eaa728ee bellard
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5220 33c263df bellard
    env->tsc_offset = 0;
5221 eaa728ee bellard
5222 eaa728ee bellard
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5223 eaa728ee bellard
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5224 eaa728ee bellard
5225 eaa728ee bellard
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5226 eaa728ee bellard
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5227 eaa728ee bellard
5228 eaa728ee bellard
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5229 eaa728ee bellard
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5230 eaa728ee bellard
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5231 5efc27bb bellard
    /* we need to set the efer after the crs so the hidden flags get
5232 5efc27bb bellard
       set properly */
5233 5efc27bb bellard
    cpu_load_efer(env, 
5234 5efc27bb bellard
                  ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
5235 eaa728ee bellard
    env->eflags = 0;
5236 eaa728ee bellard
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5237 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5238 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
5239 eaa728ee bellard
5240 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5241 872929aa bellard
                       env, R_ES);
5242 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5243 872929aa bellard
                       env, R_CS);
5244 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5245 872929aa bellard
                       env, R_SS);
5246 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5247 872929aa bellard
                       env, R_DS);
5248 eaa728ee bellard
5249 eaa728ee bellard
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5250 eaa728ee bellard
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5251 eaa728ee bellard
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5252 eaa728ee bellard
5253 eaa728ee bellard
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5254 eaa728ee bellard
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5255 eaa728ee bellard
5256 eaa728ee bellard
    /* other setups */
5257 eaa728ee bellard
    cpu_x86_set_cpl(env, 0);
5258 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5259 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5260 eaa728ee bellard
5261 960540b4 bellard
    env->hflags2 &= ~HF2_GIF_MASK;
5262 eaa728ee bellard
    /* FIXME: Resets the current ASID register to zero (host ASID). */
5263 eaa728ee bellard
5264 eaa728ee bellard
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5265 eaa728ee bellard
5266 eaa728ee bellard
    /* Clears the TSC_OFFSET inside the processor. */
5267 eaa728ee bellard
5268 eaa728ee bellard
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5269 eaa728ee bellard
       from the page table indicated the host's CR3. If the PDPEs contain
5270 eaa728ee bellard
       illegal state, the processor causes a shutdown. */
5271 eaa728ee bellard
5272 eaa728ee bellard
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5273 eaa728ee bellard
    env->cr[0] |= CR0_PE_MASK;
5274 eaa728ee bellard
    env->eflags &= ~VM_MASK;
5275 eaa728ee bellard
5276 eaa728ee bellard
    /* Disables all breakpoints in the host DR7 register. */
5277 eaa728ee bellard
5278 eaa728ee bellard
    /* Checks the reloaded host state for consistency. */
5279 eaa728ee bellard
5280 eaa728ee bellard
    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5281 eaa728ee bellard
       host's code segment or non-canonical (in the case of long mode), a
5282 eaa728ee bellard
       #GP fault is delivered inside the host.) */
5283 eaa728ee bellard
5284 eaa728ee bellard
    /* remove any pending exception */
5285 eaa728ee bellard
    env->exception_index = -1;
5286 eaa728ee bellard
    env->error_code = 0;
5287 eaa728ee bellard
    env->old_exception = -1;
5288 eaa728ee bellard
5289 eaa728ee bellard
    cpu_loop_exit();
5290 eaa728ee bellard
}
5291 eaa728ee bellard
5292 eaa728ee bellard
#endif
5293 eaa728ee bellard
5294 eaa728ee bellard
/* MMX/SSE */
5295 eaa728ee bellard
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5296 eaa728ee bellard
void helper_enter_mmx(void)
5297 eaa728ee bellard
{
5298 eaa728ee bellard
    env->fpstt = 0;
5299 eaa728ee bellard
    *(uint32_t *)(env->fptags) = 0;
5300 eaa728ee bellard
    *(uint32_t *)(env->fptags + 4) = 0;
5301 eaa728ee bellard
}
5302 eaa728ee bellard
5303 eaa728ee bellard
void helper_emms(void)
5304 eaa728ee bellard
{
5305 eaa728ee bellard
    /* set to empty state */
5306 eaa728ee bellard
    *(uint32_t *)(env->fptags) = 0x01010101;
5307 eaa728ee bellard
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5308 eaa728ee bellard
}
5309 eaa728ee bellard
5310 eaa728ee bellard
/* XXX: suppress */
5311 a7812ae4 pbrook
void helper_movq(void *d, void *s)
5312 eaa728ee bellard
{
5313 a7812ae4 pbrook
    *(uint64_t *)d = *(uint64_t *)s;
5314 eaa728ee bellard
}
5315 eaa728ee bellard
5316 eaa728ee bellard
#define SHIFT 0
5317 eaa728ee bellard
#include "ops_sse.h"
5318 eaa728ee bellard
5319 eaa728ee bellard
#define SHIFT 1
5320 eaa728ee bellard
#include "ops_sse.h"
5321 eaa728ee bellard
5322 eaa728ee bellard
#define SHIFT 0
5323 eaa728ee bellard
#include "helper_template.h"
5324 eaa728ee bellard
#undef SHIFT
5325 eaa728ee bellard
5326 eaa728ee bellard
#define SHIFT 1
5327 eaa728ee bellard
#include "helper_template.h"
5328 eaa728ee bellard
#undef SHIFT
5329 eaa728ee bellard
5330 eaa728ee bellard
#define SHIFT 2
5331 eaa728ee bellard
#include "helper_template.h"
5332 eaa728ee bellard
#undef SHIFT
5333 eaa728ee bellard
5334 eaa728ee bellard
#ifdef TARGET_X86_64
5335 eaa728ee bellard
5336 eaa728ee bellard
#define SHIFT 3
5337 eaa728ee bellard
#include "helper_template.h"
5338 eaa728ee bellard
#undef SHIFT
5339 eaa728ee bellard
5340 eaa728ee bellard
#endif
5341 eaa728ee bellard
5342 eaa728ee bellard
/* bit operations */
5343 eaa728ee bellard
target_ulong helper_bsf(target_ulong t0)
5344 eaa728ee bellard
{
5345 eaa728ee bellard
    int count;
5346 eaa728ee bellard
    target_ulong res;
5347 eaa728ee bellard
5348 eaa728ee bellard
    res = t0;
5349 eaa728ee bellard
    count = 0;
5350 eaa728ee bellard
    while ((res & 1) == 0) {
5351 eaa728ee bellard
        count++;
5352 eaa728ee bellard
        res >>= 1;
5353 eaa728ee bellard
    }
5354 eaa728ee bellard
    return count;
5355 eaa728ee bellard
}
5356 eaa728ee bellard
5357 eaa728ee bellard
target_ulong helper_bsr(target_ulong t0)
5358 eaa728ee bellard
{
5359 eaa728ee bellard
    int count;
5360 eaa728ee bellard
    target_ulong res, mask;
5361 eaa728ee bellard
    
5362 eaa728ee bellard
    res = t0;
5363 eaa728ee bellard
    count = TARGET_LONG_BITS - 1;
5364 eaa728ee bellard
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5365 eaa728ee bellard
    while ((res & mask) == 0) {
5366 eaa728ee bellard
        count--;
5367 eaa728ee bellard
        res <<= 1;
5368 eaa728ee bellard
    }
5369 eaa728ee bellard
    return count;
5370 eaa728ee bellard
}
5371 eaa728ee bellard
5372 eaa728ee bellard
5373 eaa728ee bellard
static int compute_all_eflags(void)
5374 eaa728ee bellard
{
5375 eaa728ee bellard
    return CC_SRC;
5376 eaa728ee bellard
}
5377 eaa728ee bellard
5378 eaa728ee bellard
static int compute_c_eflags(void)
5379 eaa728ee bellard
{
5380 eaa728ee bellard
    return CC_SRC & CC_C;
5381 eaa728ee bellard
}
5382 eaa728ee bellard
5383 a7812ae4 pbrook
uint32_t helper_cc_compute_all(int op)
5384 a7812ae4 pbrook
{
5385 a7812ae4 pbrook
    switch (op) {
5386 a7812ae4 pbrook
    default: /* should never happen */ return 0;
5387 eaa728ee bellard
5388 a7812ae4 pbrook
    case CC_OP_EFLAGS: return compute_all_eflags();
5389 eaa728ee bellard
5390 a7812ae4 pbrook
    case CC_OP_MULB: return compute_all_mulb();
5391 a7812ae4 pbrook
    case CC_OP_MULW: return compute_all_mulw();
5392 a7812ae4 pbrook
    case CC_OP_MULL: return compute_all_mull();
5393 eaa728ee bellard
5394 a7812ae4 pbrook
    case CC_OP_ADDB: return compute_all_addb();
5395 a7812ae4 pbrook
    case CC_OP_ADDW: return compute_all_addw();
5396 a7812ae4 pbrook
    case CC_OP_ADDL: return compute_all_addl();
5397 eaa728ee bellard
5398 a7812ae4 pbrook
    case CC_OP_ADCB: return compute_all_adcb();
5399 a7812ae4 pbrook
    case CC_OP_ADCW: return compute_all_adcw();
5400 a7812ae4 pbrook
    case CC_OP_ADCL: return compute_all_adcl();
5401 eaa728ee bellard
5402 a7812ae4 pbrook
    case CC_OP_SUBB: return compute_all_subb();
5403 a7812ae4 pbrook
    case CC_OP_SUBW: return compute_all_subw();
5404 a7812ae4 pbrook
    case CC_OP_SUBL: return compute_all_subl();
5405 eaa728ee bellard
5406 a7812ae4 pbrook
    case CC_OP_SBBB: return compute_all_sbbb();
5407 a7812ae4 pbrook
    case CC_OP_SBBW: return compute_all_sbbw();
5408 a7812ae4 pbrook
    case CC_OP_SBBL: return compute_all_sbbl();
5409 eaa728ee bellard
5410 a7812ae4 pbrook
    case CC_OP_LOGICB: return compute_all_logicb();
5411 a7812ae4 pbrook
    case CC_OP_LOGICW: return compute_all_logicw();
5412 a7812ae4 pbrook
    case CC_OP_LOGICL: return compute_all_logicl();
5413 eaa728ee bellard
5414 a7812ae4 pbrook
    case CC_OP_INCB: return compute_all_incb();
5415 a7812ae4 pbrook
    case CC_OP_INCW: return compute_all_incw();
5416 a7812ae4 pbrook
    case CC_OP_INCL: return compute_all_incl();
5417 eaa728ee bellard
5418 a7812ae4 pbrook
    case CC_OP_DECB: return compute_all_decb();
5419 a7812ae4 pbrook
    case CC_OP_DECW: return compute_all_decw();
5420 a7812ae4 pbrook
    case CC_OP_DECL: return compute_all_decl();
5421 eaa728ee bellard
5422 a7812ae4 pbrook
    case CC_OP_SHLB: return compute_all_shlb();
5423 a7812ae4 pbrook
    case CC_OP_SHLW: return compute_all_shlw();
5424 a7812ae4 pbrook
    case CC_OP_SHLL: return compute_all_shll();
5425 eaa728ee bellard
5426 a7812ae4 pbrook
    case CC_OP_SARB: return compute_all_sarb();
5427 a7812ae4 pbrook
    case CC_OP_SARW: return compute_all_sarw();
5428 a7812ae4 pbrook
    case CC_OP_SARL: return compute_all_sarl();
5429 eaa728ee bellard
5430 eaa728ee bellard
#ifdef TARGET_X86_64
5431 a7812ae4 pbrook
    case CC_OP_MULQ: return compute_all_mulq();
5432 eaa728ee bellard
5433 a7812ae4 pbrook
    case CC_OP_ADDQ: return compute_all_addq();
5434 eaa728ee bellard
5435 a7812ae4 pbrook
    case CC_OP_ADCQ: return compute_all_adcq();
5436 eaa728ee bellard
5437 a7812ae4 pbrook
    case CC_OP_SUBQ: return compute_all_subq();
5438 eaa728ee bellard
5439 a7812ae4 pbrook
    case CC_OP_SBBQ: return compute_all_sbbq();
5440 eaa728ee bellard
5441 a7812ae4 pbrook
    case CC_OP_LOGICQ: return compute_all_logicq();
5442 eaa728ee bellard
5443 a7812ae4 pbrook
    case CC_OP_INCQ: return compute_all_incq();
5444 eaa728ee bellard
5445 a7812ae4 pbrook
    case CC_OP_DECQ: return compute_all_decq();
5446 eaa728ee bellard
5447 a7812ae4 pbrook
    case CC_OP_SHLQ: return compute_all_shlq();
5448 eaa728ee bellard
5449 a7812ae4 pbrook
    case CC_OP_SARQ: return compute_all_sarq();
5450 eaa728ee bellard
#endif
5451 a7812ae4 pbrook
    }
5452 a7812ae4 pbrook
}
5453 a7812ae4 pbrook
5454 a7812ae4 pbrook
uint32_t helper_cc_compute_c(int op)
5455 a7812ae4 pbrook
{
5456 a7812ae4 pbrook
    switch (op) {
5457 a7812ae4 pbrook
    default: /* should never happen */ return 0;
5458 a7812ae4 pbrook
5459 a7812ae4 pbrook
    case CC_OP_EFLAGS: return compute_c_eflags();
5460 a7812ae4 pbrook
5461 a7812ae4 pbrook
    case CC_OP_MULB: return compute_c_mull();
5462 a7812ae4 pbrook
    case CC_OP_MULW: return compute_c_mull();
5463 a7812ae4 pbrook
    case CC_OP_MULL: return compute_c_mull();
5464 a7812ae4 pbrook
5465 a7812ae4 pbrook
    case CC_OP_ADDB: return compute_c_addb();
5466 a7812ae4 pbrook
    case CC_OP_ADDW: return compute_c_addw();
5467 a7812ae4 pbrook
    case CC_OP_ADDL: return compute_c_addl();
5468 a7812ae4 pbrook
5469 a7812ae4 pbrook
    case CC_OP_ADCB: return compute_c_adcb();
5470 a7812ae4 pbrook
    case CC_OP_ADCW: return compute_c_adcw();
5471 a7812ae4 pbrook
    case CC_OP_ADCL: return compute_c_adcl();
5472 a7812ae4 pbrook
5473 a7812ae4 pbrook
    case CC_OP_SUBB: return compute_c_subb();
5474 a7812ae4 pbrook
    case CC_OP_SUBW: return compute_c_subw();
5475 a7812ae4 pbrook
    case CC_OP_SUBL: return compute_c_subl();
5476 a7812ae4 pbrook
5477 a7812ae4 pbrook
    case CC_OP_SBBB: return compute_c_sbbb();
5478 a7812ae4 pbrook
    case CC_OP_SBBW: return compute_c_sbbw();
5479 a7812ae4 pbrook
    case CC_OP_SBBL: return compute_c_sbbl();
5480 a7812ae4 pbrook
5481 a7812ae4 pbrook
    case CC_OP_LOGICB: return compute_c_logicb();
5482 a7812ae4 pbrook
    case CC_OP_LOGICW: return compute_c_logicw();
5483 a7812ae4 pbrook
    case CC_OP_LOGICL: return compute_c_logicl();
5484 a7812ae4 pbrook
5485 a7812ae4 pbrook
    case CC_OP_INCB: return compute_c_incl();
5486 a7812ae4 pbrook
    case CC_OP_INCW: return compute_c_incl();
5487 a7812ae4 pbrook
    case CC_OP_INCL: return compute_c_incl();
5488 a7812ae4 pbrook
5489 a7812ae4 pbrook
    case CC_OP_DECB: return compute_c_incl();
5490 a7812ae4 pbrook
    case CC_OP_DECW: return compute_c_incl();
5491 a7812ae4 pbrook
    case CC_OP_DECL: return compute_c_incl();
5492 eaa728ee bellard
5493 a7812ae4 pbrook
    case CC_OP_SHLB: return compute_c_shlb();
5494 a7812ae4 pbrook
    case CC_OP_SHLW: return compute_c_shlw();
5495 a7812ae4 pbrook
    case CC_OP_SHLL: return compute_c_shll();
5496 a7812ae4 pbrook
5497 a7812ae4 pbrook
    case CC_OP_SARB: return compute_c_sarl();
5498 a7812ae4 pbrook
    case CC_OP_SARW: return compute_c_sarl();
5499 a7812ae4 pbrook
    case CC_OP_SARL: return compute_c_sarl();
5500 a7812ae4 pbrook
5501 a7812ae4 pbrook
#ifdef TARGET_X86_64
5502 a7812ae4 pbrook
    case CC_OP_MULQ: return compute_c_mull();
5503 a7812ae4 pbrook
5504 a7812ae4 pbrook
    case CC_OP_ADDQ: return compute_c_addq();
5505 a7812ae4 pbrook
5506 a7812ae4 pbrook
    case CC_OP_ADCQ: return compute_c_adcq();
5507 a7812ae4 pbrook
5508 a7812ae4 pbrook
    case CC_OP_SUBQ: return compute_c_subq();
5509 a7812ae4 pbrook
5510 a7812ae4 pbrook
    case CC_OP_SBBQ: return compute_c_sbbq();
5511 a7812ae4 pbrook
5512 a7812ae4 pbrook
    case CC_OP_LOGICQ: return compute_c_logicq();
5513 a7812ae4 pbrook
5514 a7812ae4 pbrook
    case CC_OP_INCQ: return compute_c_incl();
5515 a7812ae4 pbrook
5516 a7812ae4 pbrook
    case CC_OP_DECQ: return compute_c_incl();
5517 a7812ae4 pbrook
5518 a7812ae4 pbrook
    case CC_OP_SHLQ: return compute_c_shlq();
5519 a7812ae4 pbrook
5520 a7812ae4 pbrook
    case CC_OP_SARQ: return compute_c_sarl();
5521 a7812ae4 pbrook
#endif
5522 a7812ae4 pbrook
    }
5523 a7812ae4 pbrook
}