Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 66fcf8ff

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

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