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