Statistics
| Branch: | Revision:

root / target-i386 / op_helper.c @ 7e680753

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

4942 eaa728ee bellard
void helper_sti_vm(void)
4943 eaa728ee bellard
{
4944 eaa728ee bellard
    env->eflags |= VIF_MASK;
4945 eaa728ee bellard
    if (env->eflags & VIP_MASK) {
4946 eaa728ee bellard
        raise_exception(EXCP0D_GPF);
4947 eaa728ee bellard
    }
4948 eaa728ee bellard
}
4949 eaa728ee bellard
#endif
4950 eaa728ee bellard
4951 eaa728ee bellard
void helper_set_inhibit_irq(void)
4952 eaa728ee bellard
{
4953 eaa728ee bellard
    env->hflags |= HF_INHIBIT_IRQ_MASK;
4954 eaa728ee bellard
}
4955 eaa728ee bellard
4956 eaa728ee bellard
void helper_reset_inhibit_irq(void)
4957 eaa728ee bellard
{
4958 eaa728ee bellard
    env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4959 eaa728ee bellard
}
4960 eaa728ee bellard
4961 eaa728ee bellard
void helper_boundw(target_ulong a0, int v)
4962 eaa728ee bellard
{
4963 eaa728ee bellard
    int low, high;
4964 eaa728ee bellard
    low = ldsw(a0);
4965 eaa728ee bellard
    high = ldsw(a0 + 2);
4966 eaa728ee bellard
    v = (int16_t)v;
4967 eaa728ee bellard
    if (v < low || v > high) {
4968 eaa728ee bellard
        raise_exception(EXCP05_BOUND);
4969 eaa728ee bellard
    }
4970 eaa728ee bellard
}
4971 eaa728ee bellard
4972 eaa728ee bellard
void helper_boundl(target_ulong a0, int v)
4973 eaa728ee bellard
{
4974 eaa728ee bellard
    int low, high;
4975 eaa728ee bellard
    low = ldl(a0);
4976 eaa728ee bellard
    high = ldl(a0 + 4);
4977 eaa728ee bellard
    if (v < low || v > high) {
4978 eaa728ee bellard
        raise_exception(EXCP05_BOUND);
4979 eaa728ee bellard
    }
4980 eaa728ee bellard
}
4981 eaa728ee bellard
4982 eaa728ee bellard
#if !defined(CONFIG_USER_ONLY)
4983 eaa728ee bellard
4984 eaa728ee bellard
#define MMUSUFFIX _mmu
4985 eaa728ee bellard
4986 eaa728ee bellard
#define SHIFT 0
4987 eaa728ee bellard
#include "softmmu_template.h"
4988 eaa728ee bellard
4989 eaa728ee bellard
#define SHIFT 1
4990 eaa728ee bellard
#include "softmmu_template.h"
4991 eaa728ee bellard
4992 eaa728ee bellard
#define SHIFT 2
4993 eaa728ee bellard
#include "softmmu_template.h"
4994 eaa728ee bellard
4995 eaa728ee bellard
#define SHIFT 3
4996 eaa728ee bellard
#include "softmmu_template.h"
4997 eaa728ee bellard
4998 eaa728ee bellard
#endif
4999 eaa728ee bellard
5000 d9957a8b blueswir1
#if !defined(CONFIG_USER_ONLY)
5001 eaa728ee bellard
/* try to fill the TLB and return an exception if error. If retaddr is
5002 eaa728ee bellard
   NULL, it means that the function was called in C code (i.e. not
5003 eaa728ee bellard
   from generated code or from helper.c) */
5004 eaa728ee bellard
/* XXX: fix it to restore all registers */
5005 bccd9ec5 Blue Swirl
void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
5006 bccd9ec5 Blue Swirl
              void *retaddr)
5007 eaa728ee bellard
{
5008 eaa728ee bellard
    TranslationBlock *tb;
5009 eaa728ee bellard
    int ret;
5010 eaa728ee bellard
    unsigned long pc;
5011 eaa728ee bellard
    CPUX86State *saved_env;
5012 eaa728ee bellard
5013 eaa728ee bellard
    saved_env = env;
5014 bccd9ec5 Blue Swirl
    env = env1;
5015 eaa728ee bellard
5016 97b348e7 Blue Swirl
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx);
5017 eaa728ee bellard
    if (ret) {
5018 eaa728ee bellard
        if (retaddr) {
5019 eaa728ee bellard
            /* now we have a real cpu fault */
5020 eaa728ee bellard
            pc = (unsigned long)retaddr;
5021 eaa728ee bellard
            tb = tb_find_pc(pc);
5022 eaa728ee bellard
            if (tb) {
5023 eaa728ee bellard
                /* the PC is inside the translated code. It means that we have
5024 eaa728ee bellard
                   a virtual CPU fault */
5025 618ba8e6 Stefan Weil
                cpu_restore_state(tb, env, pc);
5026 eaa728ee bellard
            }
5027 eaa728ee bellard
        }
5028 872929aa bellard
        raise_exception_err(env->exception_index, env->error_code);
5029 eaa728ee bellard
    }
5030 eaa728ee bellard
    env = saved_env;
5031 eaa728ee bellard
}
5032 d9957a8b blueswir1
#endif
5033 eaa728ee bellard
5034 eaa728ee bellard
/* Secure Virtual Machine helpers */
5035 eaa728ee bellard
5036 eaa728ee bellard
#if defined(CONFIG_USER_ONLY)
5037 eaa728ee bellard
5038 db620f46 bellard
void helper_vmrun(int aflag, int next_eip_addend)
5039 eaa728ee bellard
{ 
5040 eaa728ee bellard
}
5041 eaa728ee bellard
void helper_vmmcall(void) 
5042 eaa728ee bellard
{ 
5043 eaa728ee bellard
}
5044 914178d3 bellard
void helper_vmload(int aflag)
5045 eaa728ee bellard
{ 
5046 eaa728ee bellard
}
5047 914178d3 bellard
void helper_vmsave(int aflag)
5048 eaa728ee bellard
{ 
5049 eaa728ee bellard
}
5050 872929aa bellard
void helper_stgi(void)
5051 872929aa bellard
{
5052 872929aa bellard
}
5053 872929aa bellard
void helper_clgi(void)
5054 872929aa bellard
{
5055 872929aa bellard
}
5056 eaa728ee bellard
void helper_skinit(void) 
5057 eaa728ee bellard
{ 
5058 eaa728ee bellard
}
5059 914178d3 bellard
void helper_invlpga(int aflag)
5060 eaa728ee bellard
{ 
5061 eaa728ee bellard
}
5062 eaa728ee bellard
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
5063 eaa728ee bellard
{ 
5064 eaa728ee bellard
}
5065 eaa728ee bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5066 eaa728ee bellard
{
5067 eaa728ee bellard
}
5068 eaa728ee bellard
5069 e694d4e2 Blue Swirl
void svm_check_intercept(CPUState *env1, uint32_t type)
5070 e694d4e2 Blue Swirl
{
5071 e694d4e2 Blue Swirl
}
5072 e694d4e2 Blue Swirl
5073 eaa728ee bellard
void helper_svm_check_io(uint32_t port, uint32_t param, 
5074 eaa728ee bellard
                         uint32_t next_eip_addend)
5075 eaa728ee bellard
{
5076 eaa728ee bellard
}
5077 eaa728ee bellard
#else
5078 eaa728ee bellard
5079 c227f099 Anthony Liguori
static inline void svm_save_seg(target_phys_addr_t addr,
5080 872929aa bellard
                                const SegmentCache *sc)
5081 eaa728ee bellard
{
5082 872929aa bellard
    stw_phys(addr + offsetof(struct vmcb_seg, selector), 
5083 872929aa bellard
             sc->selector);
5084 872929aa bellard
    stq_phys(addr + offsetof(struct vmcb_seg, base), 
5085 872929aa bellard
             sc->base);
5086 872929aa bellard
    stl_phys(addr + offsetof(struct vmcb_seg, limit), 
5087 872929aa bellard
             sc->limit);
5088 872929aa bellard
    stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
5089 e72210e1 bellard
             ((sc->flags >> 8) & 0xff) | ((sc->flags >> 12) & 0x0f00));
5090 872929aa bellard
}
5091 872929aa bellard
                                
5092 c227f099 Anthony Liguori
static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
5093 872929aa bellard
{
5094 872929aa bellard
    unsigned int flags;
5095 872929aa bellard
5096 872929aa bellard
    sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
5097 872929aa bellard
    sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
5098 872929aa bellard
    sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
5099 872929aa bellard
    flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
5100 872929aa bellard
    sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
5101 eaa728ee bellard
}
5102 eaa728ee bellard
5103 c227f099 Anthony Liguori
static inline void svm_load_seg_cache(target_phys_addr_t addr, 
5104 872929aa bellard
                                      CPUState *env, int seg_reg)
5105 eaa728ee bellard
{
5106 872929aa bellard
    SegmentCache sc1, *sc = &sc1;
5107 872929aa bellard
    svm_load_seg(addr, sc);
5108 872929aa bellard
    cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
5109 872929aa bellard
                           sc->base, sc->limit, sc->flags);
5110 eaa728ee bellard
}
5111 eaa728ee bellard
5112 db620f46 bellard
void helper_vmrun(int aflag, int next_eip_addend)
5113 eaa728ee bellard
{
5114 eaa728ee bellard
    target_ulong addr;
5115 eaa728ee bellard
    uint32_t event_inj;
5116 eaa728ee bellard
    uint32_t int_ctl;
5117 eaa728ee bellard
5118 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
5119 872929aa 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, "vmrun! " TARGET_FMT_lx "\n", addr);
5126 eaa728ee bellard
5127 eaa728ee bellard
    env->vm_vmcb = addr;
5128 eaa728ee bellard
5129 eaa728ee bellard
    /* save the current CPU state in the hsave page */
5130 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5131 eaa728ee bellard
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5132 eaa728ee bellard
5133 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5134 eaa728ee bellard
    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5135 eaa728ee bellard
5136 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
5137 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
5138 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
5139 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
5140 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
5141 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
5142 eaa728ee bellard
5143 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
5144 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
5145 eaa728ee bellard
5146 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
5147 872929aa bellard
                  &env->segs[R_ES]);
5148 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
5149 872929aa bellard
                 &env->segs[R_CS]);
5150 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
5151 872929aa bellard
                 &env->segs[R_SS]);
5152 872929aa bellard
    svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
5153 872929aa bellard
                 &env->segs[R_DS]);
5154 eaa728ee bellard
5155 db620f46 bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip),
5156 db620f46 bellard
             EIP + next_eip_addend);
5157 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
5158 eaa728ee bellard
    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
5159 eaa728ee bellard
5160 eaa728ee bellard
    /* load the interception bitmaps so we do not need to access the
5161 eaa728ee bellard
       vmcb in svm mode */
5162 872929aa bellard
    env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
5163 eaa728ee bellard
    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
5164 eaa728ee bellard
    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
5165 eaa728ee bellard
    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
5166 eaa728ee bellard
    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
5167 eaa728ee bellard
    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
5168 eaa728ee bellard
5169 872929aa bellard
    /* enable intercepts */
5170 872929aa bellard
    env->hflags |= HF_SVMI_MASK;
5171 872929aa bellard
5172 33c263df bellard
    env->tsc_offset = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.tsc_offset));
5173 33c263df bellard
5174 eaa728ee bellard
    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
5175 eaa728ee bellard
    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
5176 eaa728ee bellard
5177 eaa728ee bellard
    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
5178 eaa728ee bellard
    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
5179 eaa728ee bellard
5180 eaa728ee bellard
    /* clear exit_info_2 so we behave like the real hardware */
5181 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
5182 eaa728ee bellard
5183 eaa728ee bellard
    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
5184 eaa728ee bellard
    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
5185 eaa728ee bellard
    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
5186 eaa728ee bellard
    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
5187 eaa728ee bellard
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5188 db620f46 bellard
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5189 eaa728ee bellard
    if (int_ctl & V_INTR_MASKING_MASK) {
5190 db620f46 bellard
        env->v_tpr = int_ctl & V_TPR_MASK;
5191 db620f46 bellard
        env->hflags2 |= HF2_VINTR_MASK;
5192 eaa728ee bellard
        if (env->eflags & IF_MASK)
5193 db620f46 bellard
            env->hflags2 |= HF2_HIF_MASK;
5194 eaa728ee bellard
    }
5195 eaa728ee bellard
5196 5efc27bb bellard
    cpu_load_efer(env, 
5197 5efc27bb bellard
                  ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
5198 eaa728ee bellard
    env->eflags = 0;
5199 eaa728ee bellard
    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
5200 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5201 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
5202 eaa728ee bellard
5203 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
5204 872929aa bellard
                       env, R_ES);
5205 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
5206 872929aa bellard
                       env, R_CS);
5207 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
5208 872929aa bellard
                       env, R_SS);
5209 872929aa bellard
    svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
5210 872929aa bellard
                       env, R_DS);
5211 eaa728ee bellard
5212 eaa728ee bellard
    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
5213 eaa728ee bellard
    env->eip = EIP;
5214 eaa728ee bellard
    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
5215 eaa728ee bellard
    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
5216 eaa728ee bellard
    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
5217 eaa728ee bellard
    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
5218 eaa728ee bellard
    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
5219 eaa728ee bellard
5220 eaa728ee bellard
    /* FIXME: guest state consistency checks */
5221 eaa728ee bellard
5222 eaa728ee bellard
    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
5223 eaa728ee bellard
        case TLB_CONTROL_DO_NOTHING:
5224 eaa728ee bellard
            break;
5225 eaa728ee bellard
        case TLB_CONTROL_FLUSH_ALL_ASID:
5226 eaa728ee bellard
            /* FIXME: this is not 100% correct but should work for now */
5227 eaa728ee bellard
            tlb_flush(env, 1);
5228 eaa728ee bellard
        break;
5229 eaa728ee bellard
    }
5230 eaa728ee bellard
5231 960540b4 bellard
    env->hflags2 |= HF2_GIF_MASK;
5232 eaa728ee bellard
5233 db620f46 bellard
    if (int_ctl & V_IRQ_MASK) {
5234 db620f46 bellard
        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
5235 db620f46 bellard
    }
5236 db620f46 bellard
5237 eaa728ee bellard
    /* maybe we need to inject an event */
5238 eaa728ee bellard
    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
5239 eaa728ee bellard
    if (event_inj & SVM_EVTINJ_VALID) {
5240 eaa728ee bellard
        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
5241 eaa728ee bellard
        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
5242 eaa728ee bellard
        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
5243 eaa728ee bellard
5244 93fcfe39 aliguori
        qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
5245 eaa728ee bellard
        /* FIXME: need to implement valid_err */
5246 eaa728ee bellard
        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
5247 eaa728ee bellard
        case SVM_EVTINJ_TYPE_INTR:
5248 eaa728ee bellard
                env->exception_index = vector;
5249 eaa728ee bellard
                env->error_code = event_inj_err;
5250 eaa728ee bellard
                env->exception_is_int = 0;
5251 eaa728ee bellard
                env->exception_next_eip = -1;
5252 93fcfe39 aliguori
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
5253 db620f46 bellard
                /* XXX: is it always correct ? */
5254 e694d4e2 Blue Swirl
                do_interrupt_all(vector, 0, 0, 0, 1);
5255 eaa728ee bellard
                break;
5256 eaa728ee bellard
        case SVM_EVTINJ_TYPE_NMI:
5257 db620f46 bellard
                env->exception_index = EXCP02_NMI;
5258 eaa728ee bellard
                env->error_code = event_inj_err;
5259 eaa728ee bellard
                env->exception_is_int = 0;
5260 eaa728ee bellard
                env->exception_next_eip = EIP;
5261 93fcfe39 aliguori
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
5262 1162c041 Blue Swirl
                cpu_loop_exit(env);
5263 eaa728ee bellard
                break;
5264 eaa728ee bellard
        case SVM_EVTINJ_TYPE_EXEPT:
5265 eaa728ee bellard
                env->exception_index = vector;
5266 eaa728ee bellard
                env->error_code = event_inj_err;
5267 eaa728ee bellard
                env->exception_is_int = 0;
5268 eaa728ee bellard
                env->exception_next_eip = -1;
5269 93fcfe39 aliguori
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
5270 1162c041 Blue Swirl
                cpu_loop_exit(env);
5271 eaa728ee bellard
                break;
5272 eaa728ee bellard
        case SVM_EVTINJ_TYPE_SOFT:
5273 eaa728ee bellard
                env->exception_index = vector;
5274 eaa728ee bellard
                env->error_code = event_inj_err;
5275 eaa728ee bellard
                env->exception_is_int = 1;
5276 eaa728ee bellard
                env->exception_next_eip = EIP;
5277 93fcfe39 aliguori
                qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
5278 1162c041 Blue Swirl
                cpu_loop_exit(env);
5279 eaa728ee bellard
                break;
5280 eaa728ee bellard
        }
5281 93fcfe39 aliguori
        qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index, env->error_code);
5282 eaa728ee bellard
    }
5283 eaa728ee bellard
}
5284 eaa728ee bellard
5285 eaa728ee bellard
void helper_vmmcall(void)
5286 eaa728ee bellard
{
5287 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
5288 872929aa bellard
    raise_exception(EXCP06_ILLOP);
5289 eaa728ee bellard
}
5290 eaa728ee bellard
5291 914178d3 bellard
void helper_vmload(int aflag)
5292 eaa728ee bellard
{
5293 eaa728ee bellard
    target_ulong addr;
5294 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
5295 872929aa bellard
5296 914178d3 bellard
    if (aflag == 2)
5297 914178d3 bellard
        addr = EAX;
5298 914178d3 bellard
    else
5299 914178d3 bellard
        addr = (uint32_t)EAX;
5300 914178d3 bellard
5301 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5302 eaa728ee bellard
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5303 eaa728ee bellard
                env->segs[R_FS].base);
5304 eaa728ee bellard
5305 872929aa bellard
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
5306 872929aa bellard
                       env, R_FS);
5307 872929aa bellard
    svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
5308 872929aa bellard
                       env, R_GS);
5309 872929aa bellard
    svm_load_seg(addr + offsetof(struct vmcb, save.tr),
5310 872929aa bellard
                 &env->tr);
5311 872929aa bellard
    svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
5312 872929aa bellard
                 &env->ldt);
5313 eaa728ee bellard
5314 eaa728ee bellard
#ifdef TARGET_X86_64
5315 eaa728ee bellard
    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
5316 eaa728ee bellard
    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
5317 eaa728ee bellard
    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
5318 eaa728ee bellard
    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
5319 eaa728ee bellard
#endif
5320 eaa728ee bellard
    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
5321 eaa728ee bellard
    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
5322 eaa728ee bellard
    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
5323 eaa728ee bellard
    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
5324 eaa728ee bellard
}
5325 eaa728ee bellard
5326 914178d3 bellard
void helper_vmsave(int aflag)
5327 eaa728ee bellard
{
5328 eaa728ee bellard
    target_ulong addr;
5329 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5330 914178d3 bellard
5331 914178d3 bellard
    if (aflag == 2)
5332 914178d3 bellard
        addr = EAX;
5333 914178d3 bellard
    else
5334 914178d3 bellard
        addr = (uint32_t)EAX;
5335 914178d3 bellard
5336 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5337 eaa728ee bellard
                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5338 eaa728ee bellard
                env->segs[R_FS].base);
5339 eaa728ee bellard
5340 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5341 872929aa bellard
                 &env->segs[R_FS]);
5342 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5343 872929aa bellard
                 &env->segs[R_GS]);
5344 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5345 872929aa bellard
                 &env->tr);
5346 872929aa bellard
    svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5347 872929aa bellard
                 &env->ldt);
5348 eaa728ee bellard
5349 eaa728ee bellard
#ifdef TARGET_X86_64
5350 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
5351 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
5352 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
5353 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
5354 eaa728ee bellard
#endif
5355 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
5356 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
5357 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
5358 eaa728ee bellard
    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
5359 eaa728ee bellard
}
5360 eaa728ee bellard
5361 872929aa bellard
void helper_stgi(void)
5362 872929aa bellard
{
5363 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5364 db620f46 bellard
    env->hflags2 |= HF2_GIF_MASK;
5365 872929aa bellard
}
5366 872929aa bellard
5367 872929aa bellard
void helper_clgi(void)
5368 872929aa bellard
{
5369 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5370 db620f46 bellard
    env->hflags2 &= ~HF2_GIF_MASK;
5371 872929aa bellard
}
5372 872929aa bellard
5373 eaa728ee bellard
void helper_skinit(void)
5374 eaa728ee bellard
{
5375 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5376 872929aa bellard
    /* XXX: not implemented */
5377 872929aa bellard
    raise_exception(EXCP06_ILLOP);
5378 eaa728ee bellard
}
5379 eaa728ee bellard
5380 914178d3 bellard
void helper_invlpga(int aflag)
5381 eaa728ee bellard
{
5382 914178d3 bellard
    target_ulong addr;
5383 872929aa bellard
    helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5384 914178d3 bellard
    
5385 914178d3 bellard
    if (aflag == 2)
5386 914178d3 bellard
        addr = EAX;
5387 914178d3 bellard
    else
5388 914178d3 bellard
        addr = (uint32_t)EAX;
5389 914178d3 bellard
5390 914178d3 bellard
    /* XXX: could use the ASID to see if it is needed to do the
5391 914178d3 bellard
       flush */
5392 914178d3 bellard
    tlb_flush_page(env, addr);
5393 eaa728ee bellard
}
5394 eaa728ee bellard
5395 eaa728ee bellard
void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5396 eaa728ee bellard
{
5397 872929aa bellard
    if (likely(!(env->hflags & HF_SVMI_MASK)))
5398 872929aa bellard
        return;
5399 eaa728ee bellard
    switch(type) {
5400 eaa728ee bellard
    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5401 872929aa bellard
        if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5402 eaa728ee bellard
            helper_vmexit(type, param);
5403 eaa728ee bellard
        }
5404 eaa728ee bellard
        break;
5405 872929aa bellard
    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5406 872929aa bellard
        if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
5407 eaa728ee bellard
            helper_vmexit(type, param);
5408 eaa728ee bellard
        }
5409 eaa728ee bellard
        break;
5410 872929aa bellard
    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
5411 872929aa bellard
        if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
5412 eaa728ee bellard
            helper_vmexit(type, param);
5413 eaa728ee bellard
        }
5414 eaa728ee bellard
        break;
5415 872929aa bellard
    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
5416 872929aa bellard
        if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
5417 eaa728ee bellard
            helper_vmexit(type, param);
5418 eaa728ee bellard
        }
5419 eaa728ee bellard
        break;
5420 872929aa bellard
    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
5421 872929aa bellard
        if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
5422 eaa728ee bellard
            helper_vmexit(type, param);
5423 eaa728ee bellard
        }
5424 eaa728ee bellard
        break;
5425 eaa728ee bellard
    case SVM_EXIT_MSR:
5426 872929aa bellard
        if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5427 eaa728ee bellard
            /* FIXME: this should be read in at vmrun (faster this way?) */
5428 eaa728ee bellard
            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5429 eaa728ee bellard
            uint32_t t0, t1;
5430 eaa728ee bellard
            switch((uint32_t)ECX) {
5431 eaa728ee bellard
            case 0 ... 0x1fff:
5432 eaa728ee bellard
                t0 = (ECX * 2) % 8;
5433 583cd3cb Adam Lackorzynski
                t1 = (ECX * 2) / 8;
5434 eaa728ee bellard
                break;
5435 eaa728ee bellard
            case 0xc0000000 ... 0xc0001fff:
5436 eaa728ee bellard
                t0 = (8192 + ECX - 0xc0000000) * 2;
5437 eaa728ee bellard
                t1 = (t0 / 8);
5438 eaa728ee bellard
                t0 %= 8;
5439 eaa728ee bellard
                break;
5440 eaa728ee bellard
            case 0xc0010000 ... 0xc0011fff:
5441 eaa728ee bellard
                t0 = (16384 + ECX - 0xc0010000) * 2;
5442 eaa728ee bellard
                t1 = (t0 / 8);
5443 eaa728ee bellard
                t0 %= 8;
5444 eaa728ee bellard
                break;
5445 eaa728ee bellard
            default:
5446 eaa728ee bellard
                helper_vmexit(type, param);
5447 eaa728ee bellard
                t0 = 0;
5448 eaa728ee bellard
                t1 = 0;
5449 eaa728ee bellard
                break;
5450 eaa728ee bellard
            }
5451 eaa728ee bellard
            if (ldub_phys(addr + t1) & ((1 << param) << t0))
5452 eaa728ee bellard
                helper_vmexit(type, param);
5453 eaa728ee bellard
        }
5454 eaa728ee bellard
        break;
5455 eaa728ee bellard
    default:
5456 872929aa bellard
        if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5457 eaa728ee bellard
            helper_vmexit(type, param);
5458 eaa728ee bellard
        }
5459 eaa728ee bellard
        break;
5460 eaa728ee bellard
    }
5461 eaa728ee bellard
}
5462 eaa728ee bellard
5463 e694d4e2 Blue Swirl
void svm_check_intercept(CPUState *env1, uint32_t type)
5464 e694d4e2 Blue Swirl
{
5465 e694d4e2 Blue Swirl
    CPUState *saved_env;
5466 e694d4e2 Blue Swirl
5467 e694d4e2 Blue Swirl
    saved_env = env;
5468 e694d4e2 Blue Swirl
    env = env1;
5469 e694d4e2 Blue Swirl
    helper_svm_check_intercept_param(type, 0);
5470 e694d4e2 Blue Swirl
    env = saved_env;
5471 e694d4e2 Blue Swirl
}
5472 e694d4e2 Blue Swirl
5473 eaa728ee bellard
void helper_svm_check_io(uint32_t port, uint32_t param, 
5474 eaa728ee bellard
                         uint32_t next_eip_addend)
5475 eaa728ee bellard
{
5476 872929aa bellard
    if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5477 eaa728ee bellard
        /* FIXME: this should be read in at vmrun (faster this way?) */
5478 eaa728ee bellard
        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5479 eaa728ee bellard
        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5480 eaa728ee bellard
        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5481 eaa728ee bellard
            /* next EIP */
5482 eaa728ee bellard
            stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5483 eaa728ee bellard
                     env->eip + next_eip_addend);
5484 eaa728ee bellard
            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5485 eaa728ee bellard
        }
5486 eaa728ee bellard
    }
5487 eaa728ee bellard
}
5488 eaa728ee bellard
5489 eaa728ee bellard
/* Note: currently only 32 bits of exit_code are used */
5490 eaa728ee bellard
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5491 eaa728ee bellard
{
5492 eaa728ee bellard
    uint32_t int_ctl;
5493 eaa728ee bellard
5494 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5495 eaa728ee bellard
                exit_code, exit_info_1,
5496 eaa728ee bellard
                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5497 eaa728ee bellard
                EIP);
5498 eaa728ee bellard
5499 eaa728ee bellard
    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5500 eaa728ee bellard
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5501 eaa728ee bellard
        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5502 eaa728ee bellard
    } else {
5503 eaa728ee bellard
        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5504 eaa728ee bellard
    }
5505 eaa728ee bellard
5506 eaa728ee bellard
    /* Save the VM state in the vmcb */
5507 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5508 872929aa bellard
                 &env->segs[R_ES]);
5509 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5510 872929aa bellard
                 &env->segs[R_CS]);
5511 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5512 872929aa bellard
                 &env->segs[R_SS]);
5513 872929aa bellard
    svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5514 872929aa bellard
                 &env->segs[R_DS]);
5515 eaa728ee bellard
5516 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5517 eaa728ee bellard
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5518 eaa728ee bellard
5519 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5520 eaa728ee bellard
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5521 eaa728ee bellard
5522 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5523 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5524 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5525 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5526 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5527 eaa728ee bellard
5528 db620f46 bellard
    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
5529 db620f46 bellard
    int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
5530 db620f46 bellard
    int_ctl |= env->v_tpr & V_TPR_MASK;
5531 db620f46 bellard
    if (env->interrupt_request & CPU_INTERRUPT_VIRQ)
5532 db620f46 bellard
        int_ctl |= V_IRQ_MASK;
5533 db620f46 bellard
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5534 eaa728ee bellard
5535 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5536 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5537 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5538 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5539 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5540 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5541 eaa728ee bellard
    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5542 eaa728ee bellard
5543 eaa728ee bellard
    /* Reload the host state from vm_hsave */
5544 db620f46 bellard
    env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK);
5545 872929aa bellard
    env->hflags &= ~HF_SVMI_MASK;
5546 eaa728ee bellard
    env->intercept = 0;
5547 eaa728ee bellard
    env->intercept_exceptions = 0;
5548 eaa728ee bellard
    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5549 33c263df bellard
    env->tsc_offset = 0;
5550 eaa728ee bellard
5551 eaa728ee bellard
    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5552 eaa728ee bellard
    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5553 eaa728ee bellard
5554 eaa728ee bellard
    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5555 eaa728ee bellard
    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5556 eaa728ee bellard
5557 eaa728ee bellard
    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5558 eaa728ee bellard
    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5559 eaa728ee bellard
    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5560 5efc27bb bellard
    /* we need to set the efer after the crs so the hidden flags get
5561 5efc27bb bellard
       set properly */
5562 5efc27bb bellard
    cpu_load_efer(env, 
5563 5efc27bb bellard
                  ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
5564 eaa728ee bellard
    env->eflags = 0;
5565 eaa728ee bellard
    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5566 eaa728ee bellard
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5567 eaa728ee bellard
    CC_OP = CC_OP_EFLAGS;
5568 eaa728ee bellard
5569 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5570 872929aa bellard
                       env, R_ES);
5571 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5572 872929aa bellard
                       env, R_CS);
5573 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5574 872929aa bellard
                       env, R_SS);
5575 872929aa bellard
    svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5576 872929aa bellard
                       env, R_DS);
5577 eaa728ee bellard
5578 eaa728ee bellard
    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5579 eaa728ee bellard
    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5580 eaa728ee bellard
    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5581 eaa728ee bellard
5582 eaa728ee bellard
    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5583 eaa728ee bellard
    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5584 eaa728ee bellard
5585 eaa728ee bellard
    /* other setups */
5586 eaa728ee bellard
    cpu_x86_set_cpl(env, 0);
5587 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5588 eaa728ee bellard
    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5589 eaa728ee bellard
5590 2ed51f5b aliguori
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info),
5591 2ed51f5b aliguori
             ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)));
5592 2ed51f5b aliguori
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err),
5593 2ed51f5b aliguori
             ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err)));
5594 ab5ea558 Jan Kiszka
    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 0);
5595 2ed51f5b aliguori
5596 960540b4 bellard
    env->hflags2 &= ~HF2_GIF_MASK;
5597 eaa728ee bellard
    /* FIXME: Resets the current ASID register to zero (host ASID). */
5598 eaa728ee bellard
5599 eaa728ee bellard
    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5600 eaa728ee bellard
5601 eaa728ee bellard
    /* Clears the TSC_OFFSET inside the processor. */
5602 eaa728ee bellard
5603 eaa728ee bellard
    /* If the host is in PAE mode, the processor reloads the host's PDPEs
5604 eaa728ee bellard
       from the page table indicated the host's CR3. If the PDPEs contain
5605 eaa728ee bellard
       illegal state, the processor causes a shutdown. */
5606 eaa728ee bellard
5607 eaa728ee bellard
    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5608 eaa728ee bellard
    env->cr[0] |= CR0_PE_MASK;
5609 eaa728ee bellard
    env->eflags &= ~VM_MASK;
5610 eaa728ee bellard
5611 eaa728ee bellard
    /* Disables all breakpoints in the host DR7 register. */
5612 eaa728ee bellard
5613 eaa728ee bellard
    /* Checks the reloaded host state for consistency. */
5614 eaa728ee bellard
5615 eaa728ee bellard
    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5616 eaa728ee bellard
       host's code segment or non-canonical (in the case of long mode), a
5617 eaa728ee bellard
       #GP fault is delivered inside the host.) */
5618 eaa728ee bellard
5619 eaa728ee bellard
    /* remove any pending exception */
5620 eaa728ee bellard
    env->exception_index = -1;
5621 eaa728ee bellard
    env->error_code = 0;
5622 eaa728ee bellard
    env->old_exception = -1;
5623 eaa728ee bellard
5624 1162c041 Blue Swirl
    cpu_loop_exit(env);
5625 eaa728ee bellard
}
5626 eaa728ee bellard
5627 eaa728ee bellard
#endif
5628 eaa728ee bellard
5629 eaa728ee bellard
/* MMX/SSE */
5630 eaa728ee bellard
/* XXX: optimize by storing fptt and fptags in the static cpu state */
5631 2355c16e Aurelien Jarno
5632 2355c16e Aurelien Jarno
#define SSE_DAZ             0x0040
5633 2355c16e Aurelien Jarno
#define SSE_RC_MASK         0x6000
5634 2355c16e Aurelien Jarno
#define SSE_RC_NEAR         0x0000
5635 2355c16e Aurelien Jarno
#define SSE_RC_DOWN         0x2000
5636 2355c16e Aurelien Jarno
#define SSE_RC_UP           0x4000
5637 2355c16e Aurelien Jarno
#define SSE_RC_CHOP         0x6000
5638 2355c16e Aurelien Jarno
#define SSE_FZ              0x8000
5639 2355c16e Aurelien Jarno
5640 2355c16e Aurelien Jarno
static void update_sse_status(void)
5641 2355c16e Aurelien Jarno
{
5642 2355c16e Aurelien Jarno
    int rnd_type;
5643 2355c16e Aurelien Jarno
5644 2355c16e Aurelien Jarno
    /* set rounding mode */
5645 2355c16e Aurelien Jarno
    switch(env->mxcsr & SSE_RC_MASK) {
5646 2355c16e Aurelien Jarno
    default:
5647 2355c16e Aurelien Jarno
    case SSE_RC_NEAR:
5648 2355c16e Aurelien Jarno
        rnd_type = float_round_nearest_even;
5649 2355c16e Aurelien Jarno
        break;
5650 2355c16e Aurelien Jarno
    case SSE_RC_DOWN:
5651 2355c16e Aurelien Jarno
        rnd_type = float_round_down;
5652 2355c16e Aurelien Jarno
        break;
5653 2355c16e Aurelien Jarno
    case SSE_RC_UP:
5654 2355c16e Aurelien Jarno
        rnd_type = float_round_up;
5655 2355c16e Aurelien Jarno
        break;
5656 2355c16e Aurelien Jarno
    case SSE_RC_CHOP:
5657 2355c16e Aurelien Jarno
        rnd_type = float_round_to_zero;
5658 2355c16e Aurelien Jarno
        break;
5659 2355c16e Aurelien Jarno
    }
5660 2355c16e Aurelien Jarno
    set_float_rounding_mode(rnd_type, &env->sse_status);
5661 2355c16e Aurelien Jarno
5662 2355c16e Aurelien Jarno
    /* set denormals are zero */
5663 2355c16e Aurelien Jarno
    set_flush_inputs_to_zero((env->mxcsr & SSE_DAZ) ? 1 : 0, &env->sse_status);
5664 2355c16e Aurelien Jarno
5665 2355c16e Aurelien Jarno
    /* set flush to zero */
5666 2355c16e Aurelien Jarno
    set_flush_to_zero((env->mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
5667 2355c16e Aurelien Jarno
}
5668 2355c16e Aurelien Jarno
5669 2355c16e Aurelien Jarno
void helper_ldmxcsr(uint32_t val)
5670 2355c16e Aurelien Jarno
{
5671 2355c16e Aurelien Jarno
    env->mxcsr = val;
5672 2355c16e Aurelien Jarno
    update_sse_status();
5673 2355c16e Aurelien Jarno
}
5674 2355c16e Aurelien Jarno
5675 eaa728ee bellard
void helper_enter_mmx(void)
5676 eaa728ee bellard
{
5677 eaa728ee bellard
    env->fpstt = 0;
5678 eaa728ee bellard
    *(uint32_t *)(env->fptags) = 0;
5679 eaa728ee bellard
    *(uint32_t *)(env->fptags + 4) = 0;
5680 eaa728ee bellard
}
5681 eaa728ee bellard
5682 eaa728ee bellard
void helper_emms(void)
5683 eaa728ee bellard
{
5684 eaa728ee bellard
    /* set to empty state */
5685 eaa728ee bellard
    *(uint32_t *)(env->fptags) = 0x01010101;
5686 eaa728ee bellard
    *(uint32_t *)(env->fptags + 4) = 0x01010101;
5687 eaa728ee bellard
}
5688 eaa728ee bellard
5689 eaa728ee bellard
/* XXX: suppress */
5690 a7812ae4 pbrook
void helper_movq(void *d, void *s)
5691 eaa728ee bellard
{
5692 a7812ae4 pbrook
    *(uint64_t *)d = *(uint64_t *)s;
5693 eaa728ee bellard
}
5694 eaa728ee bellard
5695 eaa728ee bellard
#define SHIFT 0
5696 eaa728ee bellard
#include "ops_sse.h"
5697 eaa728ee bellard
5698 eaa728ee bellard
#define SHIFT 1
5699 eaa728ee bellard
#include "ops_sse.h"
5700 eaa728ee bellard
5701 eaa728ee bellard
#define SHIFT 0
5702 eaa728ee bellard
#include "helper_template.h"
5703 eaa728ee bellard
#undef SHIFT
5704 eaa728ee bellard
5705 eaa728ee bellard
#define SHIFT 1
5706 eaa728ee bellard
#include "helper_template.h"
5707 eaa728ee bellard
#undef SHIFT
5708 eaa728ee bellard
5709 eaa728ee bellard
#define SHIFT 2
5710 eaa728ee bellard
#include "helper_template.h"
5711 eaa728ee bellard
#undef SHIFT
5712 eaa728ee bellard
5713 eaa728ee bellard
#ifdef TARGET_X86_64
5714 eaa728ee bellard
5715 eaa728ee bellard
#define SHIFT 3
5716 eaa728ee bellard
#include "helper_template.h"
5717 eaa728ee bellard
#undef SHIFT
5718 eaa728ee bellard
5719 eaa728ee bellard
#endif
5720 eaa728ee bellard
5721 eaa728ee bellard
/* bit operations */
5722 eaa728ee bellard
target_ulong helper_bsf(target_ulong t0)
5723 eaa728ee bellard
{
5724 eaa728ee bellard
    int count;
5725 eaa728ee bellard
    target_ulong res;
5726 eaa728ee bellard
5727 eaa728ee bellard
    res = t0;
5728 eaa728ee bellard
    count = 0;
5729 eaa728ee bellard
    while ((res & 1) == 0) {
5730 eaa728ee bellard
        count++;
5731 eaa728ee bellard
        res >>= 1;
5732 eaa728ee bellard
    }
5733 eaa728ee bellard
    return count;
5734 eaa728ee bellard
}
5735 eaa728ee bellard
5736 31501a71 Andre Przywara
target_ulong helper_lzcnt(target_ulong t0, int wordsize)
5737 eaa728ee bellard
{
5738 eaa728ee bellard
    int count;
5739 eaa728ee bellard
    target_ulong res, mask;
5740 31501a71 Andre Przywara
5741 31501a71 Andre Przywara
    if (wordsize > 0 && t0 == 0) {
5742 31501a71 Andre Przywara
        return wordsize;
5743 31501a71 Andre Przywara
    }
5744 eaa728ee bellard
    res = t0;
5745 eaa728ee bellard
    count = TARGET_LONG_BITS - 1;
5746 eaa728ee bellard
    mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5747 eaa728ee bellard
    while ((res & mask) == 0) {
5748 eaa728ee bellard
        count--;
5749 eaa728ee bellard
        res <<= 1;
5750 eaa728ee bellard
    }
5751 31501a71 Andre Przywara
    if (wordsize > 0) {
5752 31501a71 Andre Przywara
        return wordsize - 1 - count;
5753 31501a71 Andre Przywara
    }
5754 eaa728ee bellard
    return count;
5755 eaa728ee bellard
}
5756 eaa728ee bellard
5757 31501a71 Andre Przywara
target_ulong helper_bsr(target_ulong t0)
5758 31501a71 Andre Przywara
{
5759 31501a71 Andre Przywara
        return helper_lzcnt(t0, 0);
5760 31501a71 Andre Przywara
}
5761 eaa728ee bellard
5762 eaa728ee bellard
static int compute_all_eflags(void)
5763 eaa728ee bellard
{
5764 eaa728ee bellard
    return CC_SRC;
5765 eaa728ee bellard
}
5766 eaa728ee bellard
5767 eaa728ee bellard
static int compute_c_eflags(void)
5768 eaa728ee bellard
{
5769 eaa728ee bellard
    return CC_SRC & CC_C;
5770 eaa728ee bellard
}
5771 eaa728ee bellard
5772 a7812ae4 pbrook
uint32_t helper_cc_compute_all(int op)
5773 a7812ae4 pbrook
{
5774 a7812ae4 pbrook
    switch (op) {
5775 a7812ae4 pbrook
    default: /* should never happen */ return 0;
5776 eaa728ee bellard
5777 a7812ae4 pbrook
    case CC_OP_EFLAGS: return compute_all_eflags();
5778 eaa728ee bellard
5779 a7812ae4 pbrook
    case CC_OP_MULB: return compute_all_mulb();
5780 a7812ae4 pbrook
    case CC_OP_MULW: return compute_all_mulw();
5781 a7812ae4 pbrook
    case CC_OP_MULL: return compute_all_mull();
5782 eaa728ee bellard
5783 a7812ae4 pbrook
    case CC_OP_ADDB: return compute_all_addb();
5784 a7812ae4 pbrook
    case CC_OP_ADDW: return compute_all_addw();
5785 a7812ae4 pbrook
    case CC_OP_ADDL: return compute_all_addl();
5786 eaa728ee bellard
5787 a7812ae4 pbrook
    case CC_OP_ADCB: return compute_all_adcb();
5788 a7812ae4 pbrook
    case CC_OP_ADCW: return compute_all_adcw();
5789 a7812ae4 pbrook
    case CC_OP_ADCL: return compute_all_adcl();
5790 eaa728ee bellard
5791 a7812ae4 pbrook
    case CC_OP_SUBB: return compute_all_subb();
5792 a7812ae4 pbrook
    case CC_OP_SUBW: return compute_all_subw();
5793 a7812ae4 pbrook
    case CC_OP_SUBL: return compute_all_subl();
5794 eaa728ee bellard
5795 a7812ae4 pbrook
    case CC_OP_SBBB: return compute_all_sbbb();
5796 a7812ae4 pbrook
    case CC_OP_SBBW: return compute_all_sbbw();
5797 a7812ae4 pbrook
    case CC_OP_SBBL: return compute_all_sbbl();
5798 eaa728ee bellard
5799 a7812ae4 pbrook
    case CC_OP_LOGICB: return compute_all_logicb();
5800 a7812ae4 pbrook
    case CC_OP_LOGICW: return compute_all_logicw();
5801 a7812ae4 pbrook
    case CC_OP_LOGICL: return compute_all_logicl();
5802 eaa728ee bellard
5803 a7812ae4 pbrook
    case CC_OP_INCB: return compute_all_incb();
5804 a7812ae4 pbrook
    case CC_OP_INCW: return compute_all_incw();
5805 a7812ae4 pbrook
    case CC_OP_INCL: return compute_all_incl();
5806 eaa728ee bellard
5807 a7812ae4 pbrook
    case CC_OP_DECB: return compute_all_decb();
5808 a7812ae4 pbrook
    case CC_OP_DECW: return compute_all_decw();
5809 a7812ae4 pbrook
    case CC_OP_DECL: return compute_all_decl();
5810 eaa728ee bellard
5811 a7812ae4 pbrook
    case CC_OP_SHLB: return compute_all_shlb();
5812 a7812ae4 pbrook
    case CC_OP_SHLW: return compute_all_shlw();
5813 a7812ae4 pbrook
    case CC_OP_SHLL: return compute_all_shll();
5814 eaa728ee bellard
5815 a7812ae4 pbrook
    case CC_OP_SARB: return compute_all_sarb();
5816 a7812ae4 pbrook
    case CC_OP_SARW: return compute_all_sarw();
5817 a7812ae4 pbrook
    case CC_OP_SARL: return compute_all_sarl();
5818 eaa728ee bellard
5819 eaa728ee bellard
#ifdef TARGET_X86_64
5820 a7812ae4 pbrook
    case CC_OP_MULQ: return compute_all_mulq();
5821 eaa728ee bellard
5822 a7812ae4 pbrook
    case CC_OP_ADDQ: return compute_all_addq();
5823 eaa728ee bellard
5824 a7812ae4 pbrook
    case CC_OP_ADCQ: return compute_all_adcq();
5825 eaa728ee bellard
5826 a7812ae4 pbrook
    case CC_OP_SUBQ: return compute_all_subq();
5827 eaa728ee bellard
5828 a7812ae4 pbrook
    case CC_OP_SBBQ: return compute_all_sbbq();
5829 eaa728ee bellard
5830 a7812ae4 pbrook
    case CC_OP_LOGICQ: return compute_all_logicq();
5831 eaa728ee bellard
5832 a7812ae4 pbrook
    case CC_OP_INCQ: return compute_all_incq();
5833 eaa728ee bellard
5834 a7812ae4 pbrook
    case CC_OP_DECQ: return compute_all_decq();
5835 eaa728ee bellard
5836 a7812ae4 pbrook
    case CC_OP_SHLQ: return compute_all_shlq();
5837 eaa728ee bellard
5838 a7812ae4 pbrook
    case CC_OP_SARQ: return compute_all_sarq();
5839 eaa728ee bellard
#endif
5840 a7812ae4 pbrook
    }
5841 a7812ae4 pbrook
}
5842 a7812ae4 pbrook
5843 e694d4e2 Blue Swirl
uint32_t cpu_cc_compute_all(CPUState *env1, int op)
5844 e694d4e2 Blue Swirl
{
5845 e694d4e2 Blue Swirl
    CPUState *saved_env;
5846 e694d4e2 Blue Swirl
    uint32_t ret;
5847 e694d4e2 Blue Swirl
5848 e694d4e2 Blue Swirl
    saved_env = env;
5849 e694d4e2 Blue Swirl
    env = env1;
5850 e694d4e2 Blue Swirl
    ret = helper_cc_compute_all(op);
5851 e694d4e2 Blue Swirl
    env = saved_env;
5852 e694d4e2 Blue Swirl
    return ret;
5853 e694d4e2 Blue Swirl
}
5854 e694d4e2 Blue Swirl
5855 a7812ae4 pbrook
uint32_t helper_cc_compute_c(int op)
5856 a7812ae4 pbrook
{
5857 a7812ae4 pbrook
    switch (op) {
5858 a7812ae4 pbrook
    default: /* should never happen */ return 0;
5859 a7812ae4 pbrook
5860 a7812ae4 pbrook
    case CC_OP_EFLAGS: return compute_c_eflags();
5861 a7812ae4 pbrook
5862 a7812ae4 pbrook
    case CC_OP_MULB: return compute_c_mull();
5863 a7812ae4 pbrook
    case CC_OP_MULW: return compute_c_mull();
5864 a7812ae4 pbrook
    case CC_OP_MULL: return compute_c_mull();
5865 a7812ae4 pbrook
5866 a7812ae4 pbrook
    case CC_OP_ADDB: return compute_c_addb();
5867 a7812ae4 pbrook
    case CC_OP_ADDW: return compute_c_addw();
5868 a7812ae4 pbrook
    case CC_OP_ADDL: return compute_c_addl();
5869 a7812ae4 pbrook
5870 a7812ae4 pbrook
    case CC_OP_ADCB: return compute_c_adcb();
5871 a7812ae4 pbrook
    case CC_OP_ADCW: return compute_c_adcw();
5872 a7812ae4 pbrook
    case CC_OP_ADCL: return compute_c_adcl();
5873 a7812ae4 pbrook
5874 a7812ae4 pbrook
    case CC_OP_SUBB: return compute_c_subb();
5875 a7812ae4 pbrook
    case CC_OP_SUBW: return compute_c_subw();
5876 a7812ae4 pbrook
    case CC_OP_SUBL: return compute_c_subl();
5877 a7812ae4 pbrook
5878 a7812ae4 pbrook
    case CC_OP_SBBB: return compute_c_sbbb();
5879 a7812ae4 pbrook
    case CC_OP_SBBW: return compute_c_sbbw();
5880 a7812ae4 pbrook
    case CC_OP_SBBL: return compute_c_sbbl();
5881 a7812ae4 pbrook
5882 a7812ae4 pbrook
    case CC_OP_LOGICB: return compute_c_logicb();
5883 a7812ae4 pbrook
    case CC_OP_LOGICW: return compute_c_logicw();
5884 a7812ae4 pbrook
    case CC_OP_LOGICL: return compute_c_logicl();
5885 a7812ae4 pbrook
5886 a7812ae4 pbrook
    case CC_OP_INCB: return compute_c_incl();
5887 a7812ae4 pbrook
    case CC_OP_INCW: return compute_c_incl();
5888 a7812ae4 pbrook
    case CC_OP_INCL: return compute_c_incl();
5889 a7812ae4 pbrook
5890 a7812ae4 pbrook
    case CC_OP_DECB: return compute_c_incl();
5891 a7812ae4 pbrook
    case CC_OP_DECW: return compute_c_incl();
5892 a7812ae4 pbrook
    case CC_OP_DECL: return compute_c_incl();
5893 eaa728ee bellard
5894 a7812ae4 pbrook
    case CC_OP_SHLB: return compute_c_shlb();
5895 a7812ae4 pbrook
    case CC_OP_SHLW: return compute_c_shlw();
5896 a7812ae4 pbrook
    case CC_OP_SHLL: return compute_c_shll();
5897 a7812ae4 pbrook
5898 a7812ae4 pbrook
    case CC_OP_SARB: return compute_c_sarl();
5899 a7812ae4 pbrook
    case CC_OP_SARW: return compute_c_sarl();
5900 a7812ae4 pbrook
    case CC_OP_SARL: return compute_c_sarl();
5901 a7812ae4 pbrook
5902 a7812ae4 pbrook
#ifdef TARGET_X86_64
5903 a7812ae4 pbrook
    case CC_OP_MULQ: return compute_c_mull();
5904 a7812ae4 pbrook
5905 a7812ae4 pbrook
    case CC_OP_ADDQ: return compute_c_addq();
5906 a7812ae4 pbrook
5907 a7812ae4 pbrook
    case CC_OP_ADCQ: return compute_c_adcq();
5908 a7812ae4 pbrook
5909 a7812ae4 pbrook
    case CC_OP_SUBQ: return compute_c_subq();
5910 a7812ae4 pbrook
5911 a7812ae4 pbrook
    case CC_OP_SBBQ: return compute_c_sbbq();
5912 a7812ae4 pbrook
5913 a7812ae4 pbrook
    case CC_OP_LOGICQ: return compute_c_logicq();
5914 a7812ae4 pbrook
5915 a7812ae4 pbrook
    case CC_OP_INCQ: return compute_c_incl();
5916 a7812ae4 pbrook
5917 a7812ae4 pbrook
    case CC_OP_DECQ: return compute_c_incl();
5918 a7812ae4 pbrook
5919 a7812ae4 pbrook
    case CC_OP_SHLQ: return compute_c_shlq();
5920 a7812ae4 pbrook
5921 a7812ae4 pbrook
    case CC_OP_SARQ: return compute_c_sarl();
5922 a7812ae4 pbrook
#endif
5923 a7812ae4 pbrook
    }
5924 a7812ae4 pbrook
}