Statistics
| Branch: | Revision:

root / target-i386 / helper.c @ d6205959

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

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