Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ f55761a0

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

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