op_helper.c revision cba019356f30967782b9bc21e38c4b8913148e8c
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * i386 helpers
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Copyright (c) 2003 Fabrice Bellard
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * This library is free software; you can redistribute it and/or
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * modify it under the terms of the GNU Lesser General Public
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * License as published by the Free Software Foundation; either
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * version 2 of the License, or (at your option) any later version.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * This library is distributed in the hope that it will be useful,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Lesser General Public License for more details.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * You should have received a copy of the GNU Lesser General Public
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * License along with this library; if not, see <http://www.gnu.org/licenses/>.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * a choice of LGPL license versions is made available with the language indicating
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * of the LGPL is applied is otherwise unspecified.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync//#define DEBUG_PCALL
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync# define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync# define LOG_PCALL(...) do { } while (0)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* modulo 17 table */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* modulo 9 table */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync 0.00000000000000000000L,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync 1.00000000000000000000L,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* broken thread support */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncvoid helper_write_eflags(target_ulong t0, uint32_t update_mask)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* if virtual interrupt pending and (virtual) interrupts will be enabled -> #GP */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* if TF will be set -> #GP */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ( ((new_eflags & IF_MASK) && (env->eflags & VIP_MASK))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* According to AMD manual, should be read with IOPL == 3 */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* We only use helper_read_eflags_vme() in 16-bits mode */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync LogRel(("CS:EIP=%08x:%08x, FLAGS=%08x\n", env->segs[R_CS].base, env->eip, env->eflags));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync LogRel(("EAX=%08x\tECX=%08x\tEDX=%08x\tEBX=%08x\n",
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (uint32_t)env->regs[R_EDX], (uint32_t)env->regs[R_EBX]));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync LogRel(("ESP=%08x\tEBP=%08x\tESI=%08x\tEDI=%08x\n",
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (uint32_t)env->regs[R_ESP], (uint32_t)env->regs[R_EBP],
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync (uint32_t)env->regs[R_ESI], (uint32_t)env->regs[R_EDI]));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* return non zero if error */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Trying to load a selector with CPL=1? */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((env->hflags & HF_CPL_MASK) == 0 && (selector & 3) == 1 && (env->state & CPU_RAW_RING0))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Log(("RPL 1 -> sel %04X -> %04X\n", selector, selector & 0xfffc));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync unsigned int limit;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* init the segment cache in vm86 mode. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline void load_seg_vm(int seg, int selector)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* flags must be 0xf3; expand-up read/write accessed data segment with DPL=3. (VT-x) */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync unsigned flags = DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#else /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* XXX: merge with load_seg() */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync /* Trying to load a selector with CPL=1? */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (cpl == 0 && (selector & 3) == 1 && (env->state & CPU_RAW_RING0))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync Log(("RPL 1 -> sel %04X -> %04X\n", selector, selector & 0xfffc));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX: is it correct ? */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* SS must be writable data */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* not readable code */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* if data or non conforming code, checks the rights */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /** @todo: now we ignore loading 0 selectors, need to check what is correct once */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* XXX: restore CPU state in registers (PowerPC case) */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync unsigned int index;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync LOG_PCALL("switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* if task gate, we read the TSS segment and we load it */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* read all the registers from the new TSS */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* 32 bit */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 8; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 6; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* 16 bit */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 8; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 4; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* NOTE: we must avoid memory exceptions during the task switch,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync so we make dummy accesses before */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX: it can still fail in some cases, so a bigger hack is
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync necessary to valid the TLB after having done the accesses */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* clear busy bit (it is restartable) */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync /* save the current state in the old TSS */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync /* 32 bit */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 6; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Must store the ldt as it gets reloaded and might have been changed. */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync stw_kernel(env->tr.base + 0x60, env->ldt.selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync printf("Saving CS=%08X\n", env->segs[R_CS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* 16 bit */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 4; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Must store the ldt as it gets reloaded and might have been changed. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stw_kernel(env->tr.base + 0x2a, env->ldt.selector);
dbabcd810984fc0731edff08eb281f0907dc867avboxsync /* now if an exception occurs, it will occurs in the next task
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync /* set busy bit */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* set the new CPU state */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* from this point, any exception which occurs can give problems */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* load all registers without an exception, then reload them with
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync possible exception */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX: what to do in 16 bit case ? */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 6; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* in vm86, CPL is always 3 */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* CPL is set the RPL of CS */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* first just selectors as the rest may trigger exceptions */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for(i = 0; i < 6; i++)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* load the LDT */
dbabcd810984fc0731edff08eb281f0907dc867avboxsync if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* load the segments */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* check that EIP is in the CS segment limits */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX: different exception if CALL ? */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* reset local breakpoints */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync for (i = 0; i < 4; i++) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* check if Port I/O is allowed in TSS */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync unsigned int io_offset;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* TSS must be a valid 32 bit one */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Note: the check needs two bytes */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* all bits must be zero to allow the I/O */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* Keep in sync with gen_check_external_event() */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ( (env->interrupt_request & ( CPU_INTERRUPT_EXTERNAL_EXIT
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync || ( (env->interrupt_request & CPU_INTERRUPT_EXTERNAL_HARD)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline unsigned int get_sp_mask(unsigned int e2)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return 0xffffffff;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return 0xffff;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* in 64-bit machines, this can overflow. So this segment addition macro
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * can be used to trim the value to 32-bit whenever needed */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#define SEG_ADDL(ssp, sp, sp_mask) ((uint32_t)((ssp) + (sp & (sp_mask))))
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* XXX: add a is_user flag to have proper security support */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync stl_kernel(SEG_ADDL(ssp, sp, sp_mask), (uint32_t)(val));\
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync val = (uint32_t)ldl_kernel(SEG_ADDL(ssp, sp, sp_mask));\
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* protected mode interrupt */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void do_interrupt_protected(int intno, int is_int, int error_code,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (remR3NotifyTrap(env, intno, error_code, next_eip) != VINF_SUCCESS)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* check gate type */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* must do that check here to return the correct error code */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* push the error code */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* check privilege if software int */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* check valid bit */
dbabcd810984fc0731edff08eb281f0907dc867avboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* to inner privilege */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync printf("new stack %04X:%08X gate dpl=%d\n", ss, esp, dpl);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* to same privilege */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX: check that enough room is available */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync push_size = 6 + (new_stack << 2) + (has_error_code << 1);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
dbabcd810984fc0731edff08eb281f0907dc867avboxsync PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
dbabcd810984fc0731edff08eb281f0907dc867avboxsync PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
dbabcd810984fc0731edff08eb281f0907dc867avboxsync PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
dbabcd810984fc0731edff08eb281f0907dc867avboxsync /* interrupt gate clear IF mask */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * We must clear VIP/VIF too on interrupt entry, as otherwise FreeBSD
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * gets confused by seemingly changed EFLAGS. See #3491 and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * public bug #2341.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK | VIF_MASK | VIP_MASK);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* check if VME interrupt redirection is enabled in TSS */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* TSS must be a valid 32 bit one */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* Make sure the io bitmap offset is valid; anything less than sizeof(VBOXTSS) means there's none. */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* the virtual interrupt redirection bitmap is located below the io bitmap */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* bit set means no redirection. */
dbabcd810984fc0731edff08eb281f0907dc867avboxsync return false;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync return true;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* V86 mode software interrupt with CR4.VME=1 */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void do_soft_interrupt_vme(int intno, int error_code, unsigned int next_eip)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync do_interrupt_protected(intno, 1, error_code, next_eip, 0);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* virtual mode idt is at linear address 0 */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* copy VIF into IF and set IOPL to 3 */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* XXX: use SS segment size ? */
dbabcd810984fc0731edff08eb281f0907dc867avboxsync /* update processor state */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic inline target_ulong get_rsp_from_tss(int level)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync/* 64 bit interrupt */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsyncstatic void do_interrupt64(int intno, int is_int, int error_code,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (remR3NotifyTrap(env, intno, error_code, next_eip) != VINF_SUCCESS)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* check gate type */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* check privilege if software int */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* check valid bit */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* to inner privilege */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* to same privilege */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync /* interrupt gate clear IF mask */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#else /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * We must clear VIP/VIF too on interrupt entry, as otherwise FreeBSD
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * gets confused by seemingly changed EFLAGS. See #3491 and
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * public bug #2341.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK | VIF_MASK | VIP_MASK);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync#endif /* VBOX */
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync env->exception_next_eip = env->eip + next_eip_addend;
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync 0, 0xffffffff,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync 0, 0xffffffff,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync 0, 0xffffffff,
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync 0, 0xffffffff,
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync 0, 0xffffffff,
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync 0, 0xffffffff,
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync 0, 0xffffffff,
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
9864317785d3ad19e5f4fd6d328858d71c9d474cvboxsync IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync 0, 0xffffffff,
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync 0, 0xffffffff,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Checks and processes external VMM events.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync * Called by op_check_external_event() when any of the flags is set and can be serviced.
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync __asm__ __volatile__("movq %%rsp, %0" : "=r" (uSP));
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync __asm__ __volatile__("movl %%esp, %0" : "=r" (uSP));
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync /* Keep in sync with flags checked by gen_check_external_event() */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync if (env->interrupt_request & CPU_INTERRUPT_EXTERNAL_HARD)
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (env->interrupt_request & CPU_INTERRUPT_EXTERNAL_EXIT)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (env->interrupt_request & CPU_INTERRUPT_EXTERNAL_DMA)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync if (env->interrupt_request & CPU_INTERRUPT_EXTERNAL_TIMER)
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request,
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync/* helper for recording call instruction addresses for later scanning */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync#endif /* VBOX */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync/* real mode interrupt */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsyncstatic void do_interrupt_real(int intno, int is_int, int error_code,
febf3f1de573e25fb134b8453a22b0732b4c52e2vboxsync unsigned int next_eip)
9f867ca76156f061619e4cffb76451a40c8ad2a3vboxsync /* real mode (simpler !) */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync /* XXX: use SS segment size ? */
051203e46846205a982bcf5ab198a8b5f6f8e6e0vboxsync /* update processor state */
if (is_int)
#if !defined(CONFIG_USER_ONLY)
int type;
if (is_int)
static int count;
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,
count++;
#ifdef VBOX
if (is_int) {
#if !defined(CONFIG_USER_ONLY)
#ifdef TARGET_X86_64
#ifdef VBOX
&& is_int
&& !is_hw
#if !defined(CONFIG_USER_ONLY)
#if !defined(CONFIG_USER_ONLY)
/* This should come from sysemu.h - if we could include it here... */
void qemu_system_reset_request(void);
#if !defined(CONFIG_USER_ONLY)
# ifndef VBOX
return EXCP_HLT;
*error_code = 0;
return intno;
int next_eip_addend)
Log2(("raise_interrupt: %x %x %x %RGv\n", intno, is_int, error_code, (RTGCPTR)env->eip + next_eip_addend));
if (!is_int) {
#if defined(CONFIG_USER_ONLY)
void do_smm_enter(void)
void helper_rsm(void)
#ifdef TARGET_X86_64
void do_smm_enter(void)
int i, offset;
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
void helper_rsm(void)
#ifdef VBOX
int i, offset;
#ifdef TARGET_X86_64
if (den == 0) {
if (den == 0) {
if (q != (int8_t)q)
if (den == 0) {
if (den == 0) {
if (q != (int16_t)q)
unsigned int den, r;
if (den == 0) {
int den, r;
if (den == 0) {
if (q != (int32_t)q)
void helper_aaa(void)
int icarry;
int eflags;
void helper_aas(void)
int icarry;
int eflags;
void helper_daa(void)
int eflags;
eflags = 0;
void helper_das(void)
int eflags;
eflags = 0;
int eflags;
uint64_t d;
int eflags;
#ifdef TARGET_X86_64
int eflags;
void helper_single_step(void)
#ifndef CONFIG_USER_ONLY
void helper_cpuid(void)
if (data32) {
while (--level) {
while (--level) {
#ifdef TARGET_X86_64
if (data64) {
while (--level) {
while (--level) {
#ifndef VBOX
#ifdef VBOX
(RTSEL)env->ldt.selector, (RTGCPTR)env->ldt.base, (RTGCPTR)env->ldt.limit, (RTSEL)(selector & 0xffff)));
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
#ifdef VBOX
#ifndef VBOX
unsigned int index;
#ifdef VBOX
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
#ifdef VBOX
#ifndef VBOX
int index;
unsigned int index;
#ifdef VBOX
#ifdef TARGET_X86_64
e2);
int next_eip_addend)
switch(type) {
int new_eip;
if (shift) {
int new_stack, i;
#ifdef TARGET_X86_64
if (shift) {
switch(type) {
if (shift) {
new_stack = 0;
if (shift) {
if (new_stack) {
ssp,
ss_e2);
e2);
#ifdef CONFIG_KQEMU
int eflags_mask;
#ifdef VBOX
bool fVME = false;
#ifdef VBOX
fVME = true;
#ifdef VBOX
if (fVME)
if (shift == 0)
#ifdef VBOX
if (fVME)
int dpl;
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
if (is_iret) {
if (is_iret) {
goto return_to_vm86;
#ifdef VBOX
#ifdef DEBUG
if (is_iret)
e2);
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
ss_e2);
e2);
#ifdef TARGET_X86_64
if (is_iret) {
if (cpl == 0)
#ifdef VBOX
if (shift == 0)
#ifdef VBOX
#ifdef TARGET_X86_64
#ifdef CONFIG_KQEMU
#ifdef CONFIG_KQEMU
void helper_sysenter(void)
#ifdef TARGET_X86_64
int cpl;
#ifdef TARGET_X86_64
#ifdef CONFIG_KQEMU
#if defined(CONFIG_USER_ONLY)
switch(reg) {
return val;
switch(reg) {
void helper_clts(void)
void helper_rdtsc(void)
#ifdef VBOX
void helper_rdtscp(void)
ECX = 0;
void helper_rdpmc(void)
#ifdef VBOX
/* Just return zero here; rather tricky to properly emulate this, especially as the specs are a mess. */
EAX = 0;
EDX = 0;
#if defined(CONFIG_USER_ONLY)
void helper_wrmsr(void)
void helper_rdmsr(void)
void helper_wrmsr(void)
case MSR_IA32_SYSENTER_CS:
case MSR_IA32_SYSENTER_ESP:
case MSR_IA32_SYSENTER_EIP:
case MSR_IA32_APICBASE:
case MSR_EFER:
update_mask = 0;
case MSR_STAR:
case MSR_PAT:
case MSR_VM_HSAVE_PA:
#ifdef TARGET_X86_64
case MSR_LSTAR:
case MSR_CSTAR:
case MSR_FMASK:
case MSR_FSBASE:
case MSR_GSBASE:
case MSR_KERNELGSBASE:
# ifndef VBOX
case MSR_MTRRphysBase(0):
case MSR_MTRRphysMask(0):
case MSR_MTRRfix64K_00000:
case MSR_MTRRfix16K_80000:
case MSR_MTRRfix16K_A0000:
case MSR_MTRRfix4K_C0000:
case MSR_MTRRfix4K_C8000:
case MSR_MTRRfix4K_D0000:
case MSR_MTRRfix4K_D8000:
case MSR_MTRRfix4K_E0000:
case MSR_MTRRfix4K_E8000:
case MSR_MTRRfix4K_F0000:
case MSR_MTRRfix4K_F8000:
case MSR_MTRRdefType:
case MSR_MCG_STATUS:
case MSR_MCG_CTL:
# ifndef VBOX
# ifdef VBOX
void helper_rdmsr(void)
case MSR_IA32_SYSENTER_CS:
case MSR_IA32_SYSENTER_ESP:
case MSR_IA32_SYSENTER_EIP:
case MSR_IA32_APICBASE:
case MSR_EFER:
case MSR_STAR:
case MSR_PAT:
case MSR_VM_HSAVE_PA:
case MSR_IA32_PERF_STATUS:
#ifdef TARGET_X86_64
case MSR_LSTAR:
case MSR_CSTAR:
case MSR_FMASK:
case MSR_FSBASE:
case MSR_GSBASE:
case MSR_KERNELGSBASE:
#ifdef CONFIG_KQEMU
case MSR_QPI_COMMBASE:
val = 0;
# ifndef VBOX
case MSR_MTRRphysBase(0):
case MSR_MTRRphysMask(0):
case MSR_MTRRfix64K_00000:
case MSR_MTRRfix16K_80000:
case MSR_MTRRfix16K_A0000:
case MSR_MTRRfix4K_C0000:
case MSR_MTRRfix4K_C8000:
case MSR_MTRRfix4K_D0000:
case MSR_MTRRfix4K_D8000:
case MSR_MTRRfix4K_E0000:
case MSR_MTRRfix4K_E8000:
case MSR_MTRRfix4K_F0000:
case MSR_MTRRfix4K_F8000:
case MSR_MTRRdefType:
case MSR_MTRRcap:
val = 0;
case MSR_MCG_CAP:
case MSR_MCG_CTL:
val = 0;
case MSR_MCG_STATUS:
# ifndef VBOX
val = 0;
val = 0;
# ifdef VBOX_STRICT
val = 0;
AssertMsg(val == RT_MAKE_U64(EAX, EDX), ("idMsr=%#x val=%#llx eax:edx=%#llx\n", (uint32_t)ECX, val, RT_MAKE_U64(EAX, EDX)));
unsigned int limit;
goto fail;
goto fail;
goto fail;
switch(type) {
goto fail;
fail:
return limit;
goto fail;
goto fail;
goto fail;
switch(type) {
goto fail;
fail:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
fail:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
fail:
static void fpu_raise_exception(void)
#if !defined(CONFIG_USER_ONLY)
float32 f;
uint32_t i;
u.i = val;
float64 f;
uint64_t i;
u.i = val;
int new_fpstt;
float32 f;
uint32_t i;
u.i = val;
int new_fpstt;
float64 f;
uint64_t i;
u.i = val;
int new_fpstt;
int new_fpstt;
#ifndef VBOX
float32 f;
uint32_t i;
float64 f;
uint64_t i;
#ifndef VBOX
return val;
#ifndef VBOX
return val;
return val;
#ifndef VBOX
return val;
#ifndef VBOX
return val;
return val;
int new_fpstt;
void helper_fpush(void)
fpush();
void helper_fpop(void)
fpop();
void helper_fdecstp(void)
void helper_fincstp(void)
void helper_fmov_ST0_FT0(void)
void helper_fcom_ST0_FT0(void)
int ret;
void helper_fucom_ST0_FT0(void)
int ret;
void helper_fcomi_ST0_FT0(void)
int eflags;
int ret;
void helper_fucomi_ST0_FT0(void)
int eflags;
int ret;
void helper_fadd_ST0_FT0(void)
void helper_fmul_ST0_FT0(void)
void helper_fsub_ST0_FT0(void)
void helper_fsubr_ST0_FT0(void)
void helper_fdiv_ST0_FT0(void)
void helper_fdivr_ST0_FT0(void)
CPU86_LDouble *p;
*p = ST0 - *p;
CPU86_LDouble *p;
CPU86_LDouble *p;
void helper_fchs_ST0(void)
void helper_fabs_ST0(void)
void helper_fld1_ST0(void)
void helper_fldl2t_ST0(void)
void helper_fldl2e_ST0(void)
void helper_fldpi_ST0(void)
void helper_fldlg2_ST0(void)
void helper_fldln2_ST0(void)
void helper_fldz_ST0(void)
void helper_fldz_FT0(void)
#ifndef VBOX
#ifndef VBOX
static void update_fp_status(void)
int rnd_type;
case RC_NEAR:
case RC_DOWN:
case RC_UP:
case RC_CHOP:
#ifdef FLOATX80
void helper_fclex(void)
void helper_fwait(void)
void helper_fninit(void)
val = 0;
fpush();
if (val < 0) {
if (val == 0)
void helper_f2xm1(void)
void helper_fyl2x(void)
fpop();
void helper_fptan(void)
fpush();
void helper_fpatan(void)
fpop();
void helper_fxtract(void)
unsigned int expdif;
fpush();
void helper_fprem1(void)
int expdif;
if (expdif < 0) {
q = (signed long long int)(-dblq);
q = (signed long long int)dblq;
void helper_fprem(void)
int expdif;
if (expdif < 0) {
q = (signed long long int)(-dblq);
q = (signed long long int)dblq;
void helper_fyl2xp1(void)
fpop();
void helper_fsqrt(void)
void helper_fsincos(void)
fpush();
void helper_frndint(void)
void helper_fscale(void)
void helper_fsin(void)
void helper_fcos(void)
void helper_fxam_ST0(void)
int expdif;
#ifdef USE_X86LDOUBLE
} else if (expdif == 0) {
fptag = 0;
#ifdef USE_X86LDOUBLE
if (data32) {
if (data32) {
fptag = 0;
#ifdef TARGET_X86_64
if (data64) {
for(i = 0; i < nb_xmm_regs; i++) {
for(i = 0; i < nb_xmm_regs; i++) {
#else /* VBOX + __GNUC__ >= 4: gcc 4.x compiler bug - it runs out of registers for the 64-bit value. */
#ifndef USE_X86LDOUBLE
temp.d = f;
*pexp = e;
#ifdef __arm__
return temp.d;
temp.d = f;
return temp.d;
#ifdef TARGET_X86_64
*plow += a;
if (*plow < a)
(*phigh)++;
*phigh += b;
if (a1 == 0) {
q = a0 / b;
r = a0 % b;
*plow = q;
*phigh = r;
if (a1 >= b)
a1 -= b;
qb = 0;
#if defined(DEBUG_MULDIV)
printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
if (sa)
sb = (b < 0);
if (sb)
if (sa)
return r0;
if (t0 == 0) {
if (t0 == 0) {
static void do_hlt(void)
do_hlt();
#ifdef VBOX
#ifdef VBOX
do_hlt();
void helper_debug(void)
void helper_reset_rf(void)
void helper_cli(void)
void helper_sti(void)
#ifdef VBOX
void helper_cli_vme(void)
void helper_sti_vme(void)
void helper_cli_vm(void)
void helper_sti_vm(void)
void helper_set_inhibit_irq(void)
void helper_reset_inhibit_irq(void)
v = (int16_t)v;
static float approx_rsqrt(float a)
static float approx_rcp(float a)
#if !defined(CONFIG_USER_ONLY)
#define SHIFT 0
#include "softmmu_template.h"
#include "softmmu_template.h"
#include "softmmu_template.h"
#include "softmmu_template.h"
#if !defined(CONFIG_USER_ONLY)
from generated code or from helper.c) */
int ret;
unsigned long pc;
if (ret) {
if (retaddr) {
if (tb) {
#ifdef VBOX
return efl;
return u8;
return u16;
return u32;
#ifdef FORCE_SEGMENT_SYNC
#ifdef FORCE_SEGMENT_SYNC
e2);
env1->segs[seg_reg].selector = selector; /* hidden values are now incorrect, but will be resynced when this register is accessed. */
#ifdef FORCE_SEGMENT_SYNC
int flags;
* eip remains the same for repeated instructions; no idea why qemu doesn't do a jump inside the generated code
int fake_ret;
Log(("REM: Emulating next instruction due to instruction fusing (HF_INHIBIT_IRQ_MASK) at %RGv\n", env->eip));
#ifdef VBOX_STRICT
//raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
if (shift == 0) {
fptag = 0;
for(i = 0; i < nb_xmm_regs; i++) {
#else /* VBOX + __GNUC__ >= 4: gcc 4.x compiler bug - it runs out of registers for the 64-bit value. */
int fptag;
fptag = 0;
int data64 = !!(env->hflags & HF_LMA_MASK); /* don't use HF_CS64_MASK here as cs hasn't been synced when this function is called. */
for(i = 0; i < nb_xmm_regs; i++) {
/* this is a workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35135 */
int fptag, j;
#if defined(CONFIG_USER_ONLY)
void helper_vmmcall(void)
void helper_stgi(void)
void helper_clgi(void)
void helper_skinit(void)
unsigned int flags;
env->intercept_cr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
env->intercept_cr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
env->intercept_dr_read = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
env->intercept_dr_write = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
case TLB_CONTROL_DO_NOTHING:
case SVM_EVTINJ_TYPE_INTR:
case SVM_EVTINJ_TYPE_NMI:
case SVM_EVTINJ_TYPE_EXEPT:
case SVM_EVTINJ_TYPE_SOFT:
void helper_vmmcall(void)
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
#ifdef TARGET_X86_64
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
#ifdef TARGET_X86_64
void helper_stgi(void)
void helper_clgi(void)
void helper_skinit(void)
#ifndef VBOX
switch(type) {
case SVM_EXIT_MSR:
t0 = 0;
t1 = 0;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
EIP);
void helper_enter_mmx(void)
void helper_emms(void)
void helper_movq(void *d, void *s)
#define SHIFT 0
#include "ops_sse.h"
#include "ops_sse.h"
#define SHIFT 0
#include "helper_template.h"
#include "helper_template.h"
#include "helper_template.h"
#ifdef TARGET_X86_64
#include "helper_template.h"
int count;
count = 0;
count++;
return count;
int count;
count--;
return count;
static int compute_all_eflags(void)
return CC_SRC;
static int compute_c_eflags(void)
switch (op) {
#ifdef TARGET_X86_64
switch (op) {
#ifdef TARGET_X86_64