Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 99036865

History | View | Annotate | Download (159.3 kB)

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

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