Statistics
| Branch: | Revision:

root / target-i386 / helper.c @ 07be379f

History | View | Annotate | Download (148.2 kB)

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

4557 b5b38f61 bellard
void helper_sti_vm(void)
4558 b5b38f61 bellard
{
4559 b5b38f61 bellard
    env->eflags |= VIF_MASK;
4560 b5b38f61 bellard
    if (env->eflags & VIP_MASK) {
4561 b5b38f61 bellard
        raise_exception(EXCP0D_GPF);
4562 7a0e1f41 bellard
    }
4563 b5b38f61 bellard
}
4564 4d6b6c0a bellard
#endif
4565 b5b38f61 bellard
4566 b5b38f61 bellard
void helper_set_inhibit_irq(void)
4567 b5b38f61 bellard
{
4568 b5b38f61 bellard
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4569 b5b38f61 bellard
}
4570 b5b38f61 bellard
4571 b5b38f61 bellard
void helper_reset_inhibit_irq(void)
4572 b5b38f61 bellard
{
4573 b5b38f61 bellard
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4574 b5b38f61 bellard
}
4575 b5b38f61 bellard
4576 b8b6a50b bellard
void helper_boundw(target_ulong a0, int v)
4577 b5b38f61 bellard
{
4578 b8b6a50b bellard
    int low, high;
4579 b8b6a50b bellard
    low = ldsw(a0);
4580 b8b6a50b bellard
    high = ldsw(a0 + 2);
4581 b8b6a50b bellard
    v = (int16_t)v;
4582 b5b38f61 bellard
    if (v < low || v > high) {
4583 b5b38f61 bellard
        raise_exception(EXCP05_BOUND);
4584 b5b38f61 bellard
    }
4585 b5b38f61 bellard
    FORCE_RET();
4586 b5b38f61 bellard
}
4587 b5b38f61 bellard
4588 b8b6a50b bellard
void helper_boundl(target_ulong a0, int v)
4589 b5b38f61 bellard
{
4590 b8b6a50b bellard
    int low, high;
4591 b8b6a50b bellard
    low = ldl(a0);
4592 b8b6a50b bellard
    high = ldl(a0 + 4);
4593 b5b38f61 bellard
    if (v < low || v > high) {
4594 b5b38f61 bellard
        raise_exception(EXCP05_BOUND);
4595 b5b38f61 bellard
    }
4596 b5b38f61 bellard
    FORCE_RET();
4597 b5b38f61 bellard
}
4598 b5b38f61 bellard
4599 b5b38f61 bellard
static float approx_rsqrt(float a)
4600 b5b38f61 bellard
{
4601 b5b38f61 bellard
    return 1.0 / sqrt(a);
4602 b5b38f61 bellard
}
4603 b5b38f61 bellard
4604 b5b38f61 bellard
static float approx_rcp(float a)
4605 b5b38f61 bellard
{
4606 b5b38f61 bellard
    return 1.0 / a;
4607 7a0e1f41 bellard
}
4608 664e0f19 bellard
4609 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
4610 61382a50 bellard
4611 61382a50 bellard
#define MMUSUFFIX _mmu
4612 273af660 ths
#ifdef __s390__
4613 273af660 ths
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
4614 273af660 ths
#else
4615 273af660 ths
# define GETPC() (__builtin_return_address(0))
4616 273af660 ths
#endif
4617 61382a50 bellard
4618 2c0262af bellard
#define SHIFT 0
4619 2c0262af bellard
#include "softmmu_template.h"
4620 2c0262af bellard
4621 2c0262af bellard
#define SHIFT 1
4622 2c0262af bellard
#include "softmmu_template.h"
4623 2c0262af bellard
4624 2c0262af bellard
#define SHIFT 2
4625 2c0262af bellard
#include "softmmu_template.h"
4626 2c0262af bellard
4627 2c0262af bellard
#define SHIFT 3
4628 2c0262af bellard
#include "softmmu_template.h"
4629 2c0262af bellard
4630 61382a50 bellard
#endif
4631 61382a50 bellard
4632 61382a50 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
4633 61382a50 bellard
   NULL, it means that the function was called in C code (i.e. not
4634 61382a50 bellard
   from generated code or from helper.c) */
4635 61382a50 bellard
/* XXX: fix it to restore all registers */
4636 6ebbf390 j_mayer
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4637 2c0262af bellard
{
4638 2c0262af bellard
    TranslationBlock *tb;
4639 2c0262af bellard
    int ret;
4640 2c0262af bellard
    unsigned long pc;
4641 61382a50 bellard
    CPUX86State *saved_env;
4642 61382a50 bellard
4643 61382a50 bellard
    /* XXX: hack to restore env in all cases, even if not called from
4644 61382a50 bellard
       generated code */
4645 61382a50 bellard
    saved_env = env;
4646 61382a50 bellard
    env = cpu_single_env;
4647 61382a50 bellard
4648 6ebbf390 j_mayer
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4649 2c0262af bellard
    if (ret) {
4650 61382a50 bellard
        if (retaddr) {
4651 61382a50 bellard
            /* now we have a real cpu fault */
4652 61382a50 bellard
            pc = (unsigned long)retaddr;
4653 61382a50 bellard
            tb = tb_find_pc(pc);
4654 61382a50 bellard
            if (tb) {
4655 61382a50 bellard
                /* the PC is inside the translated code. It means that we have
4656 61382a50 bellard
                   a virtual CPU fault */
4657 58fe2f10 bellard
                cpu_restore_state(tb, env, pc, NULL);
4658 61382a50 bellard
            }
4659 2c0262af bellard
        }
4660 0d1a29f9 bellard
        if (retaddr)
4661 54ca9095 bellard
            raise_exception_err(env->exception_index, env->error_code);
4662 0d1a29f9 bellard
        else
4663 54ca9095 bellard
            raise_exception_err_norestore(env->exception_index, env->error_code);
4664 2c0262af bellard
    }
4665 61382a50 bellard
    env = saved_env;
4666 2c0262af bellard
}
4667 0573fbfc ths
4668 0573fbfc ths
4669 0573fbfc ths
/* Secure Virtual Machine helpers */
4670 0573fbfc ths
4671 0573fbfc ths
void helper_stgi(void)
4672 0573fbfc ths
{
4673 0573fbfc ths
    env->hflags |= HF_GIF_MASK;
4674 0573fbfc ths
}
4675 0573fbfc ths
4676 0573fbfc ths
void helper_clgi(void)
4677 0573fbfc ths
{
4678 0573fbfc ths
    env->hflags &= ~HF_GIF_MASK;
4679 0573fbfc ths
}
4680 0573fbfc ths
4681 0573fbfc ths
#if defined(CONFIG_USER_ONLY)
4682 0573fbfc ths
4683 b8b6a50b bellard
void helper_vmrun(void) 
4684 b8b6a50b bellard
{ 
4685 b8b6a50b bellard
}
4686 b8b6a50b bellard
void helper_vmmcall(void) 
4687 b8b6a50b bellard
{ 
4688 b8b6a50b bellard
}
4689 b8b6a50b bellard
void helper_vmload(void) 
4690 b8b6a50b bellard
{ 
4691 b8b6a50b bellard
}
4692 b8b6a50b bellard
void helper_vmsave(void) 
4693 b8b6a50b bellard
{ 
4694 b8b6a50b bellard
}
4695 b8b6a50b bellard
void helper_skinit(void) 
4696 b8b6a50b bellard
{ 
4697 b8b6a50b bellard
}
4698 b8b6a50b bellard
void helper_invlpga(void) 
4699 b8b6a50b bellard
{ 
4700 b8b6a50b bellard
}
4701 b8b6a50b bellard
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4702 b8b6a50b bellard
{ 
4703 b8b6a50b bellard
}
4704 b8b6a50b bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4705 0573fbfc ths
{
4706 0573fbfc ths
}
4707 0573fbfc ths
4708 b8b6a50b bellard
void helper_svm_check_io(uint32_t port, uint32_t param, 
4709 b8b6a50b bellard
                         uint32_t next_eip_addend)
4710 b8b6a50b bellard
{
4711 b8b6a50b bellard
}
4712 0573fbfc ths
#else
4713 0573fbfc ths
4714 0573fbfc ths
static inline uint32_t
4715 0573fbfc ths
vmcb2cpu_attrib(uint16_t vmcb_attrib, uint32_t vmcb_base, uint32_t vmcb_limit)
4716 0573fbfc ths
{
4717 0573fbfc ths
    return    ((vmcb_attrib & 0x00ff) << 8)          /* Type, S, DPL, P */
4718 0573fbfc ths
            | ((vmcb_attrib & 0x0f00) << 12)         /* AVL, L, DB, G */
4719 0573fbfc ths
            | ((vmcb_base >> 16) & 0xff)             /* Base 23-16 */
4720 0573fbfc ths
            | (vmcb_base & 0xff000000)               /* Base 31-24 */
4721 0573fbfc ths
            | (vmcb_limit & 0xf0000);                /* Limit 19-16 */
4722 0573fbfc ths
}
4723 0573fbfc ths
4724 0573fbfc ths
static inline uint16_t cpu2vmcb_attrib(uint32_t cpu_attrib)
4725 0573fbfc ths
{
4726 0573fbfc ths
    return    ((cpu_attrib >> 8) & 0xff)             /* Type, S, DPL, P */
4727 0573fbfc ths
            | ((cpu_attrib & 0xf00000) >> 12);       /* AVL, L, DB, G */
4728 0573fbfc ths
}
4729 0573fbfc ths
4730 b5b38f61 bellard
void helper_vmrun(void)
4731 0573fbfc ths
{
4732 b5b38f61 bellard
    target_ulong addr;
4733 0573fbfc ths
    uint32_t event_inj;
4734 0573fbfc ths
    uint32_t int_ctl;
4735 0573fbfc ths
4736 b5b38f61 bellard
    addr = EAX;
4737 0573fbfc ths
    if (loglevel & CPU_LOG_TB_IN_ASM)
4738 0573fbfc ths
        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4739 0573fbfc ths
4740 0573fbfc ths
    env->vm_vmcb = addr;
4741 0573fbfc ths
4742 0573fbfc ths
    /* save the current CPU state in the hsave page */
4743 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4744 0573fbfc ths
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4745 0573fbfc ths
4746 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4747 0573fbfc ths
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4748 0573fbfc ths
4749 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4750 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4751 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4752 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4753 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8), env->cr[8]);
4754 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4755 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4756 0573fbfc ths
4757 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4758 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4759 0573fbfc ths
4760 0573fbfc ths
    SVM_SAVE_SEG(env->vm_hsave, segs[R_ES], es);
4761 0573fbfc ths
    SVM_SAVE_SEG(env->vm_hsave, segs[R_CS], cs);
4762 0573fbfc ths
    SVM_SAVE_SEG(env->vm_hsave, segs[R_SS], ss);
4763 0573fbfc ths
    SVM_SAVE_SEG(env->vm_hsave, segs[R_DS], ds);
4764 0573fbfc ths
4765 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP);
4766 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4767 0573fbfc ths
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4768 0573fbfc ths
4769 0573fbfc ths
    /* load the interception bitmaps so we do not need to access the
4770 0573fbfc ths
       vmcb in svm mode */
4771 0573fbfc ths
    /* We shift all the intercept bits so we can OR them with the TB
4772 0573fbfc ths
       flags later on */
4773 0573fbfc ths
    env->intercept            = (ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept)) << INTERCEPT_INTR) | INTERCEPT_SVM_MASK;
4774 0573fbfc ths
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4775 0573fbfc ths
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4776 0573fbfc ths
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4777 0573fbfc ths
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4778 0573fbfc ths
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4779 0573fbfc ths
4780 0573fbfc ths
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4781 0573fbfc ths
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4782 0573fbfc ths
4783 0573fbfc ths
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4784 0573fbfc ths
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4785 0573fbfc ths
4786 0573fbfc ths
    /* clear exit_info_2 so we behave like the real hardware */
4787 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
4788 0573fbfc ths
4789 0573fbfc ths
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4790 0573fbfc ths
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4791 0573fbfc ths
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4792 0573fbfc ths
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4793 0573fbfc ths
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4794 0573fbfc ths
    if (int_ctl & V_INTR_MASKING_MASK) {
4795 0573fbfc ths
        env->cr[8] = int_ctl & V_TPR_MASK;
4796 3d575329 balrog
        cpu_set_apic_tpr(env, env->cr[8]);
4797 0573fbfc ths
        if (env->eflags & IF_MASK)
4798 0573fbfc ths
            env->hflags |= HF_HIF_MASK;
4799 0573fbfc ths
    }
4800 0573fbfc ths
4801 0573fbfc ths
#ifdef TARGET_X86_64
4802 0573fbfc ths
    env->efer = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer));
4803 0573fbfc ths
    env->hflags &= ~HF_LMA_MASK;
4804 0573fbfc ths
    if (env->efer & MSR_EFER_LMA)
4805 0573fbfc ths
       env->hflags |= HF_LMA_MASK;
4806 0573fbfc ths
#endif
4807 0573fbfc ths
    env->eflags = 0;
4808 0573fbfc ths
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4809 0573fbfc ths
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4810 0573fbfc ths
    CC_OP = CC_OP_EFLAGS;
4811 0573fbfc ths
    CC_DST = 0xffffffff;
4812 0573fbfc ths
4813 0573fbfc ths
    SVM_LOAD_SEG(env->vm_vmcb, ES, es);
4814 0573fbfc ths
    SVM_LOAD_SEG(env->vm_vmcb, CS, cs);
4815 0573fbfc ths
    SVM_LOAD_SEG(env->vm_vmcb, SS, ss);
4816 0573fbfc ths
    SVM_LOAD_SEG(env->vm_vmcb, DS, ds);
4817 0573fbfc ths
4818 0573fbfc ths
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4819 0573fbfc ths
    env->eip = EIP;
4820 0573fbfc ths
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4821 0573fbfc ths
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4822 0573fbfc ths
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4823 0573fbfc ths
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4824 0573fbfc ths
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4825 0573fbfc ths
4826 0573fbfc ths
    /* FIXME: guest state consistency checks */
4827 0573fbfc ths
4828 0573fbfc ths
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4829 0573fbfc ths
        case TLB_CONTROL_DO_NOTHING:
4830 0573fbfc ths
            break;
4831 0573fbfc ths
        case TLB_CONTROL_FLUSH_ALL_ASID:
4832 0573fbfc ths
            /* FIXME: this is not 100% correct but should work for now */
4833 0573fbfc ths
            tlb_flush(env, 1);
4834 0573fbfc ths
        break;
4835 0573fbfc ths
    }
4836 0573fbfc ths
4837 0573fbfc ths
    helper_stgi();
4838 0573fbfc ths
4839 0573fbfc ths
    /* maybe we need to inject an event */
4840 0573fbfc ths
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4841 0573fbfc ths
    if (event_inj & SVM_EVTINJ_VALID) {
4842 0573fbfc ths
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4843 0573fbfc ths
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4844 0573fbfc ths
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4845 0573fbfc ths
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4846 0573fbfc ths
4847 0573fbfc ths
        if (loglevel & CPU_LOG_TB_IN_ASM)
4848 0573fbfc ths
            fprintf(logfile, "Injecting(%#hx): ", valid_err);
4849 0573fbfc ths
        /* FIXME: need to implement valid_err */
4850 0573fbfc ths
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4851 0573fbfc ths
        case SVM_EVTINJ_TYPE_INTR:
4852 0573fbfc ths
                env->exception_index = vector;
4853 0573fbfc ths
                env->error_code = event_inj_err;
4854 7241f532 balrog
                env->exception_is_int = 0;
4855 0573fbfc ths
                env->exception_next_eip = -1;
4856 0573fbfc ths
                if (loglevel & CPU_LOG_TB_IN_ASM)
4857 0573fbfc ths
                    fprintf(logfile, "INTR");
4858 0573fbfc ths
                break;
4859 0573fbfc ths
        case SVM_EVTINJ_TYPE_NMI:
4860 0573fbfc ths
                env->exception_index = vector;
4861 0573fbfc ths
                env->error_code = event_inj_err;
4862 7241f532 balrog
                env->exception_is_int = 0;
4863 0573fbfc ths
                env->exception_next_eip = EIP;
4864 0573fbfc ths
                if (loglevel & CPU_LOG_TB_IN_ASM)
4865 0573fbfc ths
                    fprintf(logfile, "NMI");
4866 0573fbfc ths
                break;
4867 0573fbfc ths
        case SVM_EVTINJ_TYPE_EXEPT:
4868 0573fbfc ths
                env->exception_index = vector;
4869 0573fbfc ths
                env->error_code = event_inj_err;
4870 0573fbfc ths
                env->exception_is_int = 0;
4871 0573fbfc ths
                env->exception_next_eip = -1;
4872 0573fbfc ths
                if (loglevel & CPU_LOG_TB_IN_ASM)
4873 0573fbfc ths
                    fprintf(logfile, "EXEPT");
4874 0573fbfc ths
                break;
4875 0573fbfc ths
        case SVM_EVTINJ_TYPE_SOFT:
4876 0573fbfc ths
                env->exception_index = vector;
4877 0573fbfc ths
                env->error_code = event_inj_err;
4878 0573fbfc ths
                env->exception_is_int = 1;
4879 0573fbfc ths
                env->exception_next_eip = EIP;
4880 0573fbfc ths
                if (loglevel & CPU_LOG_TB_IN_ASM)
4881 0573fbfc ths
                    fprintf(logfile, "SOFT");
4882 0573fbfc ths
                break;
4883 0573fbfc ths
        }
4884 0573fbfc ths
        if (loglevel & CPU_LOG_TB_IN_ASM)
4885 0573fbfc ths
            fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
4886 0573fbfc ths
    }
4887 52621688 ths
    if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) {
4888 0573fbfc ths
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4889 52621688 ths
    }
4890 0573fbfc ths
4891 0573fbfc ths
    cpu_loop_exit();
4892 0573fbfc ths
}
4893 0573fbfc ths
4894 0573fbfc ths
void helper_vmmcall(void)
4895 0573fbfc ths
{
4896 0573fbfc ths
    if (loglevel & CPU_LOG_TB_IN_ASM)
4897 0573fbfc ths
        fprintf(logfile,"vmmcall!\n");
4898 0573fbfc ths
}
4899 0573fbfc ths
4900 b5b38f61 bellard
void helper_vmload(void)
4901 0573fbfc ths
{
4902 b5b38f61 bellard
    target_ulong addr;
4903 b5b38f61 bellard
    addr = EAX;
4904 0573fbfc ths
    if (loglevel & CPU_LOG_TB_IN_ASM)
4905 0573fbfc ths
        fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4906 0573fbfc ths
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4907 0573fbfc ths
                env->segs[R_FS].base);
4908 0573fbfc ths
4909 0573fbfc ths
    SVM_LOAD_SEG2(addr, segs[R_FS], fs);
4910 0573fbfc ths
    SVM_LOAD_SEG2(addr, segs[R_GS], gs);
4911 0573fbfc ths
    SVM_LOAD_SEG2(addr, tr, tr);
4912 0573fbfc ths
    SVM_LOAD_SEG2(addr, ldt, ldtr);
4913 0573fbfc ths
4914 0573fbfc ths
#ifdef TARGET_X86_64
4915 0573fbfc ths
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
4916 0573fbfc ths
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
4917 0573fbfc ths
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
4918 0573fbfc ths
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
4919 0573fbfc ths
#endif
4920 0573fbfc ths
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
4921 0573fbfc ths
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
4922 0573fbfc ths
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
4923 0573fbfc ths
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
4924 0573fbfc ths
}
4925 0573fbfc ths
4926 b5b38f61 bellard
void helper_vmsave(void)
4927 0573fbfc ths
{
4928 b5b38f61 bellard
    target_ulong addr;
4929 b5b38f61 bellard
    addr = EAX;
4930 0573fbfc ths
    if (loglevel & CPU_LOG_TB_IN_ASM)
4931 0573fbfc ths
        fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4932 0573fbfc ths
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4933 0573fbfc ths
                env->segs[R_FS].base);
4934 0573fbfc ths
4935 0573fbfc ths
    SVM_SAVE_SEG(addr, segs[R_FS], fs);
4936 0573fbfc ths
    SVM_SAVE_SEG(addr, segs[R_GS], gs);
4937 0573fbfc ths
    SVM_SAVE_SEG(addr, tr, tr);
4938 0573fbfc ths
    SVM_SAVE_SEG(addr, ldt, ldtr);
4939 0573fbfc ths
4940 0573fbfc ths
#ifdef TARGET_X86_64
4941 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
4942 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
4943 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
4944 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
4945 0573fbfc ths
#endif
4946 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
4947 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
4948 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
4949 0573fbfc ths
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
4950 0573fbfc ths
}
4951 0573fbfc ths
4952 0573fbfc ths
void helper_skinit(void)
4953 0573fbfc ths
{
4954 0573fbfc ths
    if (loglevel & CPU_LOG_TB_IN_ASM)
4955 0573fbfc ths
        fprintf(logfile,"skinit!\n");
4956 0573fbfc ths
}
4957 0573fbfc ths
4958 0573fbfc ths
void helper_invlpga(void)
4959 0573fbfc ths
{
4960 0573fbfc ths
    tlb_flush(env, 0);
4961 0573fbfc ths
}
4962 0573fbfc ths
4963 b8b6a50b bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4964 0573fbfc ths
{
4965 0573fbfc ths
    switch(type) {
4966 0573fbfc ths
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
4967 0573fbfc ths
        if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) {
4968 b8b6a50b bellard
            helper_vmexit(type, param);
4969 0573fbfc ths
        }
4970 0573fbfc ths
        break;
4971 0573fbfc ths
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8:
4972 0573fbfc ths
        if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) {
4973 b8b6a50b bellard
            helper_vmexit(type, param);
4974 0573fbfc ths
        }
4975 0573fbfc ths
        break;
4976 0573fbfc ths
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
4977 0573fbfc ths
        if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) {
4978 b8b6a50b bellard
            helper_vmexit(type, param);
4979 0573fbfc ths
        }
4980 0573fbfc ths
        break;
4981 0573fbfc ths
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8:
4982 0573fbfc ths
        if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) {
4983 b8b6a50b bellard
            helper_vmexit(type, param);
4984 0573fbfc ths
        }
4985 0573fbfc ths
        break;
4986 0573fbfc ths
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16:
4987 0573fbfc ths
        if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) {
4988 b8b6a50b bellard
            helper_vmexit(type, param);
4989 0573fbfc ths
        }
4990 0573fbfc ths
        break;
4991 0573fbfc ths
    case SVM_EXIT_IOIO:
4992 0573fbfc ths
        break;
4993 0573fbfc ths
4994 0573fbfc ths
    case SVM_EXIT_MSR:
4995 0573fbfc ths
        if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) {
4996 0573fbfc ths
            /* FIXME: this should be read in at vmrun (faster this way?) */
4997 0573fbfc ths
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
4998 b8b6a50b bellard
            uint32_t t0, t1;
4999 0573fbfc ths
            switch((uint32_t)ECX) {
5000 0573fbfc ths
            case 0 ... 0x1fff:
5001 b8b6a50b bellard
                t0 = (ECX * 2) % 8;
5002 b8b6a50b bellard
                t1 = ECX / 8;
5003 0573fbfc ths
                break;
5004 0573fbfc ths
            case 0xc0000000 ... 0xc0001fff:
5005 b8b6a50b bellard
                t0 = (8192 + ECX - 0xc0000000) * 2;
5006 b8b6a50b bellard
                t1 = (t0 / 8);
5007 b8b6a50b bellard
                t0 %= 8;
5008 0573fbfc ths
                break;
5009 0573fbfc ths
            case 0xc0010000 ... 0xc0011fff:
5010 b8b6a50b bellard
                t0 = (16384 + ECX - 0xc0010000) * 2;
5011 b8b6a50b bellard
                t1 = (t0 / 8);
5012 b8b6a50b bellard
                t0 %= 8;
5013 0573fbfc ths
                break;
5014 0573fbfc ths
            default:
5015 b8b6a50b bellard
                helper_vmexit(type, param);
5016 b8b6a50b bellard
                t0 = 0;
5017 b8b6a50b bellard
                t1 = 0;
5018 b8b6a50b bellard
                break;
5019 0573fbfc ths
            }
5020 b8b6a50b bellard
            if (ldub_phys(addr + t1) & ((1 << param) << t0))
5021 b8b6a50b bellard
                helper_vmexit(type, param);
5022 0573fbfc ths
        }
5023 0573fbfc ths
        break;
5024 0573fbfc ths
    default:
5025 0573fbfc ths
        if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) {
5026 b8b6a50b bellard
            helper_vmexit(type, param);
5027 0573fbfc ths
        }
5028 0573fbfc ths
        break;
5029 0573fbfc ths
    }
5030 0573fbfc ths
}
5031 0573fbfc ths
5032 b8b6a50b bellard
void helper_svm_check_io(uint32_t port, uint32_t param, 
5033 b8b6a50b bellard
                         uint32_t next_eip_addend)
5034 b8b6a50b bellard
{
5035 b8b6a50b bellard
    if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) {
5036 b8b6a50b bellard
        /* FIXME: this should be read in at vmrun (faster this way?) */
5037 b8b6a50b bellard
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5038 b8b6a50b bellard
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5039 b8b6a50b bellard
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5040 b8b6a50b bellard
            /* next EIP */
5041 b8b6a50b bellard
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5042 b8b6a50b bellard
                     env->eip + next_eip_addend);
5043 b8b6a50b bellard
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5044 b8b6a50b bellard
        }
5045 b8b6a50b bellard
    }
5046 b8b6a50b bellard
}
5047 b8b6a50b bellard
5048 b8b6a50b bellard
/* Note: currently only 32 bits of exit_code are used */
5049 b8b6a50b bellard
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5050 0573fbfc ths
{
5051 0573fbfc ths
    uint32_t int_ctl;
5052 0573fbfc ths
5053 0573fbfc ths
    if (loglevel & CPU_LOG_TB_IN_ASM)
5054 b8b6a50b bellard
        fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5055 0573fbfc ths
                exit_code, exit_info_1,
5056 0573fbfc ths
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5057 0573fbfc ths
                EIP);
5058 0573fbfc ths
5059 52621688 ths
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5060 52621688 ths
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5061 52621688 ths
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5062 52621688 ths
    } else {
5063 52621688 ths
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5064 52621688 ths
    }
5065 52621688 ths
5066 0573fbfc ths
    /* Save the VM state in the vmcb */
5067 0573fbfc ths
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es);
5068 0573fbfc ths
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs);
5069 0573fbfc ths
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_SS], ss);
5070 0573fbfc ths
    SVM_SAVE_SEG(env->vm_vmcb, segs[R_DS], ds);
5071 0573fbfc ths
5072 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5073 0573fbfc ths
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5074 0573fbfc ths
5075 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5076 0573fbfc ths
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5077 0573fbfc ths
5078 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5079 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5080 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5081 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5082 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5083 0573fbfc ths
5084 0573fbfc ths
    if ((int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl))) & V_INTR_MASKING_MASK) {
5085 0573fbfc ths
        int_ctl &= ~V_TPR_MASK;
5086 0573fbfc ths
        int_ctl |= env->cr[8] & V_TPR_MASK;
5087 0573fbfc ths
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5088 0573fbfc ths
    }
5089 0573fbfc ths
5090 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5091 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5092 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5093 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5094 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5095 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5096 0573fbfc ths
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5097 0573fbfc ths
5098 0573fbfc ths
    /* Reload the host state from vm_hsave */
5099 0573fbfc ths
    env->hflags &= ~HF_HIF_MASK;
5100 0573fbfc ths
    env->intercept = 0;
5101 0573fbfc ths
    env->intercept_exceptions = 0;
5102 0573fbfc ths
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5103 0573fbfc ths
5104 0573fbfc ths
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5105 0573fbfc ths
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5106 0573fbfc ths
5107 0573fbfc ths
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5108 0573fbfc ths
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5109 0573fbfc ths
5110 0573fbfc ths
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5111 0573fbfc ths
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5112 0573fbfc ths
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5113 3d575329 balrog
    if (int_ctl & V_INTR_MASKING_MASK) {
5114 0573fbfc ths
        env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8));
5115 3d575329 balrog
        cpu_set_apic_tpr(env, env->cr[8]);
5116 3d575329 balrog
    }
5117 0573fbfc ths
    /* we need to set the efer after the crs so the hidden flags get set properly */
5118 0573fbfc ths
#ifdef TARGET_X86_64
5119 0573fbfc ths
    env->efer  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer));
5120 0573fbfc ths
    env->hflags &= ~HF_LMA_MASK;
5121 0573fbfc ths
    if (env->efer & MSR_EFER_LMA)
5122 0573fbfc ths
       env->hflags |= HF_LMA_MASK;
5123 0573fbfc ths
#endif
5124 0573fbfc ths
5125 0573fbfc ths
    env->eflags = 0;
5126 0573fbfc ths
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5127 0573fbfc ths
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5128 0573fbfc ths
    CC_OP = CC_OP_EFLAGS;
5129 0573fbfc ths
5130 0573fbfc ths
    SVM_LOAD_SEG(env->vm_hsave, ES, es);
5131 0573fbfc ths
    SVM_LOAD_SEG(env->vm_hsave, CS, cs);
5132 0573fbfc ths
    SVM_LOAD_SEG(env->vm_hsave, SS, ss);
5133 0573fbfc ths
    SVM_LOAD_SEG(env->vm_hsave, DS, ds);
5134 0573fbfc ths
5135 0573fbfc ths
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5136 0573fbfc ths
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5137 0573fbfc ths
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5138 0573fbfc ths
5139 0573fbfc ths
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5140 0573fbfc ths
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5141 0573fbfc ths
5142 0573fbfc ths
    /* other setups */
5143 0573fbfc ths
    cpu_x86_set_cpl(env, 0);
5144 b8b6a50b bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5145 0573fbfc ths
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5146 0573fbfc ths
5147 0573fbfc ths
    helper_clgi();
5148 0573fbfc ths
    /* FIXME: Resets the current ASID register to zero (host ASID). */
5149 0573fbfc ths
5150 0573fbfc ths
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5151 0573fbfc ths
5152 0573fbfc ths
    /* Clears the TSC_OFFSET inside the processor. */
5153 0573fbfc ths
5154 0573fbfc ths
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5155 0573fbfc ths
       from the page table indicated the host's CR3. If the PDPEs contain
5156 0573fbfc ths
       illegal state, the processor causes a shutdown. */
5157 0573fbfc ths
5158 0573fbfc ths
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5159 0573fbfc ths
    env->cr[0] |= CR0_PE_MASK;
5160 0573fbfc ths
    env->eflags &= ~VM_MASK;
5161 0573fbfc ths
5162 0573fbfc ths
    /* Disables all breakpoints in the host DR7 register. */
5163 0573fbfc ths
5164 0573fbfc ths
    /* Checks the reloaded host state for consistency. */
5165 0573fbfc ths
5166 0573fbfc ths
    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5167 0573fbfc ths
       host's code segment or non-canonical (in the case of long mode), a
5168 0573fbfc ths
       #GP fault is delivered inside the host.) */
5169 0573fbfc ths
5170 0573fbfc ths
    /* remove any pending exception */
5171 0573fbfc ths
    env->exception_index = -1;
5172 0573fbfc ths
    env->error_code = 0;
5173 0573fbfc ths
    env->old_exception = -1;
5174 0573fbfc ths
5175 0573fbfc ths
    cpu_loop_exit();
5176 0573fbfc ths
}
5177 0573fbfc ths
5178 0573fbfc ths
#endif
5179 5af45186 bellard
5180 5af45186 bellard
/* MMX/SSE */
5181 5af45186 bellard
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5182 5af45186 bellard
void helper_enter_mmx(void)
5183 5af45186 bellard
{
5184 5af45186 bellard
    env->fpstt = 0;
5185 5af45186 bellard
    *(uint32_t *)(env->fptags) = 0;
5186 5af45186 bellard
    *(uint32_t *)(env->fptags + 4) = 0;
5187 5af45186 bellard
}
5188 5af45186 bellard
5189 5af45186 bellard
void helper_emms(void)
5190 5af45186 bellard
{
5191 5af45186 bellard
    /* set to empty state */
5192 5af45186 bellard
    *(uint32_t *)(env->fptags) = 0x01010101;
5193 5af45186 bellard
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5194 5af45186 bellard
}
5195 5af45186 bellard
5196 5af45186 bellard
/* XXX: suppress */
5197 5af45186 bellard
void helper_movq(uint64_t *d, uint64_t *s)
5198 5af45186 bellard
{
5199 5af45186 bellard
    *d = *s;
5200 5af45186 bellard
}
5201 5af45186 bellard
5202 5af45186 bellard
#define SHIFT 0
5203 5af45186 bellard
#include "ops_sse.h"
5204 5af45186 bellard
5205 5af45186 bellard
#define SHIFT 1
5206 5af45186 bellard
#include "ops_sse.h"
5207 5af45186 bellard
5208 b6abf97d bellard
#define SHIFT 0
5209 b6abf97d bellard
#include "helper_template.h"
5210 b6abf97d bellard
#undef SHIFT
5211 b6abf97d bellard
5212 b6abf97d bellard
#define SHIFT 1
5213 b6abf97d bellard
#include "helper_template.h"
5214 b6abf97d bellard
#undef SHIFT
5215 b6abf97d bellard
5216 b6abf97d bellard
#define SHIFT 2
5217 b6abf97d bellard
#include "helper_template.h"
5218 b6abf97d bellard
#undef SHIFT
5219 b6abf97d bellard
5220 b6abf97d bellard
#ifdef TARGET_X86_64
5221 b6abf97d bellard
5222 b6abf97d bellard
#define SHIFT 3
5223 b6abf97d bellard
#include "helper_template.h"
5224 b6abf97d bellard
#undef SHIFT
5225 b6abf97d bellard
5226 b6abf97d bellard
#endif
5227 07d2c595 bellard
5228 6191b059 bellard
/* bit operations */
5229 6191b059 bellard
target_ulong helper_bsf(target_ulong t0)
5230 6191b059 bellard
{
5231 6191b059 bellard
    int count;
5232 6191b059 bellard
    target_ulong res;
5233 6191b059 bellard
5234 6191b059 bellard
    res = t0;
5235 6191b059 bellard
    count = 0;
5236 6191b059 bellard
    while ((res & 1) == 0) {
5237 6191b059 bellard
        count++;
5238 6191b059 bellard
        res >>= 1;
5239 6191b059 bellard
    }
5240 6191b059 bellard
    return count;
5241 6191b059 bellard
}
5242 6191b059 bellard
5243 6191b059 bellard
target_ulong helper_bsr(target_ulong t0)
5244 6191b059 bellard
{
5245 6191b059 bellard
    int count;
5246 6191b059 bellard
    target_ulong res, mask;
5247 6191b059 bellard
    
5248 6191b059 bellard
    res = t0;
5249 6191b059 bellard
    count = TARGET_LONG_BITS - 1;
5250 6191b059 bellard
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5251 6191b059 bellard
    while ((res & mask) == 0) {
5252 6191b059 bellard
        count--;
5253 6191b059 bellard
        res <<= 1;
5254 6191b059 bellard
    }
5255 6191b059 bellard
    return count;
5256 6191b059 bellard
}
5257 6191b059 bellard
5258 6191b059 bellard
5259 07d2c595 bellard
static int compute_all_eflags(void)
5260 07d2c595 bellard
{
5261 07d2c595 bellard
    return CC_SRC;
5262 07d2c595 bellard
}
5263 07d2c595 bellard
5264 07d2c595 bellard
static int compute_c_eflags(void)
5265 07d2c595 bellard
{
5266 07d2c595 bellard
    return CC_SRC & CC_C;
5267 07d2c595 bellard
}
5268 07d2c595 bellard
5269 07d2c595 bellard
CCTable cc_table[CC_OP_NB] = {
5270 07d2c595 bellard
    [CC_OP_DYNAMIC] = { /* should never happen */ },
5271 07d2c595 bellard
5272 07d2c595 bellard
    [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
5273 07d2c595 bellard
5274 07d2c595 bellard
    [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
5275 07d2c595 bellard
    [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
5276 07d2c595 bellard
    [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
5277 07d2c595 bellard
5278 07d2c595 bellard
    [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
5279 07d2c595 bellard
    [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
5280 07d2c595 bellard
    [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
5281 07d2c595 bellard
5282 07d2c595 bellard
    [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
5283 07d2c595 bellard
    [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
5284 07d2c595 bellard
    [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
5285 07d2c595 bellard
5286 07d2c595 bellard
    [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
5287 07d2c595 bellard
    [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
5288 07d2c595 bellard
    [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
5289 07d2c595 bellard
5290 07d2c595 bellard
    [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
5291 07d2c595 bellard
    [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
5292 07d2c595 bellard
    [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
5293 07d2c595 bellard
5294 07d2c595 bellard
    [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
5295 07d2c595 bellard
    [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
5296 07d2c595 bellard
    [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
5297 07d2c595 bellard
5298 07d2c595 bellard
    [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
5299 07d2c595 bellard
    [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
5300 07d2c595 bellard
    [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
5301 07d2c595 bellard
5302 07d2c595 bellard
    [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
5303 07d2c595 bellard
    [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
5304 07d2c595 bellard
    [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
5305 07d2c595 bellard
5306 07d2c595 bellard
    [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
5307 07d2c595 bellard
    [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
5308 07d2c595 bellard
    [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
5309 07d2c595 bellard
5310 07d2c595 bellard
    [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
5311 07d2c595 bellard
    [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
5312 07d2c595 bellard
    [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
5313 07d2c595 bellard
5314 07d2c595 bellard
#ifdef TARGET_X86_64
5315 07d2c595 bellard
    [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
5316 07d2c595 bellard
5317 07d2c595 bellard
    [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq  },
5318 07d2c595 bellard
5319 07d2c595 bellard
    [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq  },
5320 07d2c595 bellard
5321 07d2c595 bellard
    [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq  },
5322 07d2c595 bellard
5323 07d2c595 bellard
    [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq  },
5324 07d2c595 bellard
5325 07d2c595 bellard
    [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
5326 07d2c595 bellard
5327 07d2c595 bellard
    [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
5328 07d2c595 bellard
5329 07d2c595 bellard
    [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
5330 07d2c595 bellard
5331 07d2c595 bellard
    [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
5332 07d2c595 bellard
5333 07d2c595 bellard
    [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
5334 07d2c595 bellard
#endif
5335 07d2c595 bellard
};