Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ d5e49a81

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

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