Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 9c22a623

History | View | Annotate | Download (158 kB)

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

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