Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 6fb6d245

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

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