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