op_helper.c revision 4c7e0dceb5826f3f292069287d4093f438bf966f
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * i386 helpers
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * Copyright (c) 2003 Fabrice Bellard
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * This library is free software; you can redistribute it and/or
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * modify it under the terms of the GNU Lesser General Public
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * License as published by the Free Software Foundation; either
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * version 2 of the License, or (at your option) any later version.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * This library is distributed in the hope that it will be useful,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * but WITHOUT ANY WARRANTY; without even the implied warranty of
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * Lesser General Public License for more details.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * You should have received a copy of the GNU Lesser General Public
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * a choice of LGPL license versions is made available with the language indicating
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * that LGPLv2 or any later version may be used, or where a choice of which version
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * of the LGPL is applied is otherwise unspecified.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy#endif /* VBOX */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy//#define DEBUG_PCALL
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy# define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy# define LOG_PCALL(...) do { } while (0)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy qemu_log("raise_exception line=%d\n", __LINE__);\
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy/* modulo 17 table */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy/* modulo 9 table */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy 0.00000000000000000000L,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy 1.00000000000000000000L,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy/* broken thread support */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roystatic spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Royvoid helper_write_eflags(target_ulong t0, uint32_t update_mask)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* if virtual interrupt pending and (virtual) interrupts will be enabled -> #GP */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* if TF will be set -> #GP */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if ( ((new_eflags & IF_MASK) && (env->eflags & VIP_MASK))
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* According to AMD manual, should be read with IOPL == 3 */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* We only use helper_read_eflags_vme() in 16-bits mode */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy LogRel(("CS:EIP=%08x:%08x, FLAGS=%08x\n", env->segs[R_CS].base, env->eip, env->eflags));
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy LogRel(("EAX=%08x\tECX=%08x\tEDX=%08x\tEBX=%08x\n",
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy (uint32_t)env->regs[R_EDX], (uint32_t)env->regs[R_EBX]));
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy LogRel(("ESP=%08x\tEBP=%08x\tESI=%08x\tEDI=%08x\n",
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy (uint32_t)env->regs[R_ESP], (uint32_t)env->regs[R_EBP],
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy (uint32_t)env->regs[R_ESI], (uint32_t)env->regs[R_EDI]));
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * Updates e2 with the DESC_A_MASK, writes it to the descriptor table, and
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * returns the updated e2.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * @returns e2 with A set.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * @param e2 The 2nd selector DWORD.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roystatic uint32_t set_segment_accessed(int selector, uint32_t e2)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy SegmentCache *dt = selector & X86_SEL_LDT ? &env->ldt : &env->gdt;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy target_ulong ptr = dt->base + (selector & X86_SEL_MASK);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy#endif /* VBOX */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy/* return non zero if error */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roystatic inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* Trying to load a selector with CPL=1? */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /** @todo this is a hack to correct the incorrect checking order for pending interrupts in the patm iret replacement code (corrected in the ring-1 version) */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /** @todo in theory the iret could fault and we'd still need this. */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if ((env->hflags & HF_CPL_MASK) == 0 && (selector & 3) == 1 && (env->state & CPU_RAW_RING0) && !EMIsRawRing1Enabled(env->pVM))
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy Log(("RPL 1 -> sel %04X -> %04X\n", selector, selector & 0xfffc));
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy#endif /* VBOX */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roystatic inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy unsigned int limit;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roystatic inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roystatic inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy/* init the segment cache in vm86 mode. */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roystatic inline void load_seg_vm(int seg, int selector)
#ifdef VBOX
#ifndef VBOX
if (shift == 0) {
#ifdef VBOX
e2);
#ifdef VBOX
#define SWITCH_TSS_JMP 0
#ifndef VBOX
int index;
unsigned int index;
new_cr3 = 0;
new_trap = 0;
#ifdef VBOX
#ifdef VBOX
#ifdef VBOX
#ifdef VBOX
#ifndef CONFIG_USER_ONLY
#ifndef VBOX
unsigned int io_offset;
goto fail;
goto fail;
fail:
#ifdef VBOX
void helper_check_external_event()
#ifndef VBOX
#ifndef VBOX
#ifndef VBOX
#ifndef VBOX
#ifndef VBOX
#ifndef VBOX
switch(intno) {
#ifdef TARGET_X86_64
#ifdef VBOX
has_error_code = 0;
if (is_int)
#ifndef VBOX
switch(type) {
#ifdef VBOX
if (has_error_code) {
int type;
if (shift)
new_stack = 0;
if (new_stack) {
if (has_error_code) {
if (new_stack) {
if (has_error_code) {
if (new_stack) {
e2);
#ifndef VBOX
#ifdef VBOX
goto fail;
/* Make sure the io bitmap offset is valid; anything less than sizeof(VBOXTSS) means there's none. */
goto fail;
fail:
int selector;
#ifdef TARGET_X86_64
int index;
#ifdef VBOX
has_error_code = 0;
if (is_int)
switch(type) {
if (ist != 0)
ss = 0;
new_stack = 0;
if (ist != 0)
if (has_error_code) {
if (new_stack) {
#ifndef VBOX
e2);
#ifndef VBOX
#ifdef TARGET_X86_64
#if defined(CONFIG_USER_ONLY)
int selector;
int code64;
if (code64)
#ifdef TARGET_X86_64
#ifdef VBOX
void helper_external_event(void)
# ifdef RT_ARCH_AMD64
void helper_record_call()
unsigned int next_eip)
int selector;
#ifndef VBOX
if (is_int)
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
#ifdef VBOX
#ifdef VBOX
#ifdef VBOX
#ifdef VBOX
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 VBOX
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
#ifdef VBOX
#ifndef VBOX
unsigned int index;
#ifdef VBOX
#ifdef VBOX
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
#ifdef VBOX
#ifndef VBOX
int index;
unsigned int index;
#ifdef VBOX
#ifndef 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);
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
if (is_iret)
#ifdef VBOX
e2);
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
# ifndef VBOX
#ifdef VBOX
ss_e2);
e2);
#ifdef TARGET_X86_64
if (is_iret) {
if (cpl == 0)
#ifdef VBOX
if (shift == 0)
#ifdef VBOX
#ifdef TARGET_X86_64
void helper_sysenter(void)
#ifdef TARGET_X86_64
int cpl;
#ifdef TARGET_X86_64
#if defined(CONFIG_USER_ONLY)
switch(reg) {
#ifndef VBOX
return val;
switch(reg) {
#ifndef VBOX
# ifndef VBOX
# ifndef VBOX
void helper_clts(void)
void helper_rdtsc(void)
void helper_rdtscp(void)
helper_rdtsc();
#ifndef VBOX
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:
case MSR_TSC_AUX:
# 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:
#ifndef VBOX
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:
# ifndef VBOX
case MSR_TSC_AUX:
# 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;
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) {
#ifdef USE_X86LDOUBLE
return tmp.d;
#ifdef USE_X86LDOUBLE
tmp.d = f;
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;
return wordsize;
count--;
if (wordsize > 0) {
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