Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ a1d8db07

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

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