helper.c revision cca8c8c55206ccd60f1b32843a67ce737447ac60
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * i386 helpers
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Copyright (c) 2003 Fabrice Bellard
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * This library is free software; you can redistribute it and/or
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * modify it under the terms of the GNU Lesser General Public
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * License as published by the Free Software Foundation; either
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * version 2 of the License, or (at your option) any later version.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * This library is distributed in the hope that it will be useful,
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Lesser General Public License for more details.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * You should have received a copy of the GNU Lesser General Public
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * License along with this library; if not, write to the Free Software
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * other than GPL or LGPL is available it will apply instead, Sun elects to use only
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * a choice of LGPL license versions is made available with the language indicating
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync * of the LGPL is applied is otherwise unspecified.
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync//#define DEBUG_PCALL
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* modulo 17 table */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* modulo 9 table */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync 0.00000000000000000000L,
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync 1.00000000000000000000L,
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* thread support */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* NOTE: the register at this point must be saved by hand because
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync longjmp restore them */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* return non zero if error */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsyncstatic inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsyncstatic inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync unsigned int limit;
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsyncstatic inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsyncstatic inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
cf5af7fccfec4bef83f4ec21662d6a6e6cbe3835vboxsync/* init the segment cache in vm86 mode. */
cf5af7fccfec4bef83f4ec21662d6a6e6cbe3835vboxsyncstatic inline void load_seg_vm(int seg, int selector)
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync unsigned flags = DESC_P_MASK | DESC_S_MASK | DESC_W_MASK;
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsyncstatic inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* XXX: merge with load_seg() */
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync /* XXX: is it correct ? */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* SS must be writable data */
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync /* not readable code */
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
c6adb272ec43d5eaadb1493cb2bf45f2f8adf588vboxsync /* if data or non conforming code, checks the rights */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync/* XXX: restore CPU state in registers (PowerPC case) */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync printf("switch_tss %x %x %x %d %08x\n", tss_selector, e1, e2, source, next_eip);
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync /* if task gate, we read the TSS segment and we load it */
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
f5ab5688c35373443d953e2a9fa8a054defdece8vboxsync old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* read all the registers from the new TSS */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* 32 bit */
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync for(i = 0; i < 8; i++)
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
aca7a56d52c58d8b388343450503c22822fd6620vboxsync for(i = 0; i < 6; i++)
aca7a56d52c58d8b388343450503c22822fd6620vboxsync new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
aca7a56d52c58d8b388343450503c22822fd6620vboxsync /* 16 bit */
aca7a56d52c58d8b388343450503c22822fd6620vboxsync for(i = 0; i < 8; i++)
aca7a56d52c58d8b388343450503c22822fd6620vboxsync new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
aca7a56d52c58d8b388343450503c22822fd6620vboxsync for(i = 0; i < 4; i++)
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync /* NOTE: we must avoid memory exceptions during the task switch,
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync so we make dummy accesses before */
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync /* XXX: it can still fail in some cases, so a bigger hack is
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync necessary to valid the TLB after having done the accesses */
cf5af7fccfec4bef83f4ec21662d6a6e6cbe3835vboxsync v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* clear busy bit (it is restartable) */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* save the current state in the old TSS */
7eaaa8a4480370b82ef3735994f986f338fb4df2vboxsync /* 32 bit */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync for(i = 0; i < 6; i++)
0c587d7af645db20acefebcfc15b6f46c440ba4avboxsync stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync printf("Saving CS=%08X\n", env->segs[R_CS].selector);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* 16 bit */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync for(i = 0; i < 4; i++)
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* now if an exception occurs, it will occurs in the next task
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync /* set busy bit */
5f9dfb422a6ed57822f9c0cb94fa7df8d24acc9bvboxsync if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
goto fail;
goto fail;
fail:
void check_iob_T0(void)
void check_iow_T0(void)
void check_iol_T0(void)
void check_iob_DX(void)
void check_iow_DX(void)
void check_iol_DX(void)
#ifdef TARGET_X86_64
#ifdef VBOX
# ifdef VBOX_WITH_VMI
has_error_code = 0;
switch(intno) {
if (is_int)
switch(type) {
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);
#ifdef VBOX
goto fail;
goto fail;
fail:
int selector;
#ifdef TARGET_X86_64
int index;
#ifdef VBOX
has_error_code = 0;
switch(intno) {
if (is_int)
switch(type) {
if (ist != 0)
ss = 0;
new_stack = 0;
if (ist != 0)
if (has_error_code) {
if (new_stack) {
e2);
int selector;
#ifdef TARGET_X86_64
int code64;
if (code64)
#ifdef TARGET_X86_64
#ifdef USE_KQEMU
#ifdef VBOX
void helper_external_event(void)
void helper_record_call()
unsigned int next_eip)
int selector;
if (is_int)
if (is_int)
static int count;
fprintf(logfile, "%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 TARGET_X86_64
#ifdef VBOX
&& is_int
&& !is_hw
int next_eip_addend)
NOT_DMIK(Log2(("raise_interrupt: %x %x %x %RGv\n", intno, is_int, error_code, env->eip + next_eip_addend)));
#if defined(CONFIG_USER_ONLY)
void do_smm_enter(void)
void helper_rsm(void)
#ifdef TARGET_X86_64
void do_smm_enter(void)
#ifdef VBOX
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 BUGGY_GCC_DIV64
void helper_divl_EAX_T0(void)
unsigned int den, r;
if (den == 0) {
#ifdef BUGGY_GCC_DIV64
void helper_idivl_EAX_T0(void)
int den, r;
if (den == 0) {
#ifdef BUGGY_GCC_DIV64
if (q != (int32_t)q)
void helper_cmpxchg8b(void)
uint64_t d;
int eflags;
void helper_single_step()
void helper_cpuid(void)
#ifndef VBOX
switch(index) {
EBX = 0;
ECX = 0;
EDX = 0;
EBX = 0;
ECX = 0;
EAX = 0;
EDX = 0;
EBX = 0;
ECX = 0;
EDX = 0;
EAX = 0;
EBX = 0;
ECX = 0;
EDX = 0;
if (data32) {
while (--level) {
while (--level) {
#ifdef TARGET_X86_64
if (data64) {
while (--level) {
while (--level) {
void helper_lldt_T0(void)
int selector;
#ifdef VBOX
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
#ifdef VBOX
void helper_ltr_T0(void)
int selector;
#ifdef VBOX
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
#ifdef VBOX
int index;
#ifdef VBOX
#ifdef TARGET_X86_64
e2);
switch(type) {
if (shift) {
#ifdef DEBUG_PCALL
#ifdef DEBUG_PCALL
#ifdef TARGET_X86_64
if (shift) {
switch(type) {
#ifdef DEBUG_PCALL
if (shift) {
new_stack = 0;
if (shift) {
if (new_stack) {
ssp,
ss_e2);
e2);
#ifdef USE_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)
#ifdef DEBUG_PCALL
e2);
#ifdef TARGET_X86_64
#ifdef DEBUG_PCALL
#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 USE_KQEMU
#ifdef USE_KQEMU
void helper_sysenter(void)
void helper_sysexit(void)
int cpl;
#ifdef USE_KQEMU
#if !defined(CONFIG_USER_ONLY)
switch(reg) {
void helper_rdtsc(void)
#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:
#ifdef TARGET_X86_64
case MSR_LSTAR:
case MSR_CSTAR:
case MSR_FMASK:
case MSR_FSBASE:
case MSR_GSBASE:
case MSR_KERNELGSBASE:
#ifndef 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:
#ifdef TARGET_X86_64
case MSR_LSTAR:
case MSR_CSTAR:
case MSR_FMASK:
case MSR_FSBASE:
case MSR_GSBASE:
case MSR_KERNELGSBASE:
#ifndef VBOX
val = 0;
void helper_lsl(void)
goto fail;
goto fail;
switch(type) {
goto fail;
fail:
void helper_lar(void)
unsigned int selector;
goto fail;
goto fail;
goto fail;
switch(type) {
goto fail;
fail:
void helper_verr(void)
unsigned int selector;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
fail:
void helper_verw(void)
unsigned int selector;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
fail:
void helper_fldt_ST0_A0(void)
int new_fpstt;
void helper_fstt_ST0_A0(void)
void fpu_raise_exception(void)
#if !defined(CONFIG_USER_ONLY)
void helper_fbld_ST0_A0(void)
val = 0;
fpush();
void helper_fbst_ST0_A0(void)
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;
void helper_fprem(void)
int expdif;
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;
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;
uint64_t v;
a0 = a;
b0 = b;
*plow = v;
*phigh = 0;
*phigh += v;
#ifdef DEBUG_MULDIV
sa = (a < 0);
if (sa)
sb = (b < 0);
if (sb)
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)
void helper_mulq_EAX_T0(void)
void helper_imulq_EAX_T0(void)
void helper_imulq_T0_T1(void)
void helper_divq_EAX_T0(void)
if (T0 == 0) {
void helper_idivq_EAX_T0(void)
if (T0 == 0) {
void helper_bswapq_T0(void)
void helper_hlt(void)
void helper_monitor(void)
void helper_mwait(void)
#ifdef VBOX
helper_hlt();
helper_hlt();
float approx_rsqrt(float a)
float approx_rcp(float a)
void update_fp_status(void)
int rnd_type;
case RC_NEAR:
case RC_DOWN:
case RC_UP:
case RC_CHOP:
#ifdef FLOATX80
#if !defined(CONFIG_USER_ONLY)
#define SHIFT 0
#include "softmmu_template.h"
#include "softmmu_template.h"
#include "softmmu_template.h"
#include "softmmu_template.h"
from generated code or from helper.c) */
int ret;
unsigned long pc;
if (ret) {
if (retaddr) {
if (tb) {
if (retaddr)
#ifdef VBOX
return efl;
return u8;
return u16;
return u32;
e2);
env1->segs[seg_reg].selector = selector; /* hidden values are now incorrect, but will be resynced when this register is accessed. */
#ifdef VBOX_STRICT
goto l_failure;
#ifdef TARGET_X86_64
goto l_failure;
goto l_failure;
goto l_failure;
#ifdef TARGET_X86_64
int csize;
void (*gen_func)(void);
if (!tb)
AssertFailed();
#ifdef DEBUG
AssertFailed();
AssertFailed();
// eip remains the same for repeated instructions; no idea why qemu doesn't do a jump inside the generated code
gen_func();
Log(("REM: Emulating next instruction due to instruction fusing (HF_INHIBIT_IRQ_MASK) at %RGv\n", env->eip));
//raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
if (shift == 0) {
#define data64 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;
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;