qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [4459] converted more helpers to TCG - fixed some SVM issue


From: Fabrice Bellard
Subject: [Qemu-devel] [4459] converted more helpers to TCG - fixed some SVM issues
Date: Thu, 15 May 2008 16:46:41 +0000

Revision: 4459
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4459
Author:   bellard
Date:     2008-05-15 16:46:30 +0000 (Thu, 15 May 2008)

Log Message:
-----------
converted more helpers to TCG - fixed some SVM issues

Modified Paths:
--------------
    trunk/target-i386/TODO
    trunk/target-i386/exec.h
    trunk/target-i386/helper.c
    trunk/target-i386/helper.h
    trunk/target-i386/op.c
    trunk/target-i386/ops_sse.h
    trunk/target-i386/ops_sse_header.h
    trunk/target-i386/ops_template.h
    trunk/target-i386/svm.h
    trunk/target-i386/translate.c

Modified: trunk/target-i386/TODO
===================================================================
--- trunk/target-i386/TODO      2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/TODO      2008-05-15 16:46:30 UTC (rev 4459)
@@ -3,12 +3,13 @@
 - rework eflags optimization (will be a consequence of TCG port)
 - SVM: rework the implementation: simplify code, move most intercept
   tests as dynamic, correct segment access, verify exception safety,
-  remove most of the added CPU state.
+  cpu save/restore, SMM save/restore. 
 - arpl eflags computation is invalid
 - x86_64: fxsave/fxrestore intel/amd differences
 - x86_64: lcall/ljmp intel/amd differences ?
 - x86_64: cmpxchgl intel/amd differences ?
-- x86_64: cmovl bug intel/amd differences ?
+- x86_64: cmovl intel/amd differences ?
+- cmpxchg16b + cmpxchg8b cpuid test
 - x86: monitor invalid 
 - better code fetch (different exception handling + CS.limit support)
 - user/kernel PUSHL/POPL in helper.c
@@ -19,10 +20,18 @@
 - full support of segment limit/rights 
 - full x87 exception support
 - improve x87 bit exactness (use bochs code ?)
+- DRx register support
+- CR0.AC emulation
+- SSE alignment checks
+- fix SSE min/max with nans
 
 Optimizations/Features:
 
 - finish TCG port
+- add SVM nested paging support
+- add VMX support
+- add AVX support
+- add SSE5 support
 - evaluate x87 stack pointer statically
 - find a way to avoid translating several time the same TB if CR0.TS
   is set or not.

Modified: trunk/target-i386/exec.h
===================================================================
--- trunk/target-i386/exec.h    2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/exec.h    2008-05-15 16:46:30 UTC (rev 4459)
@@ -105,16 +105,6 @@
 
 extern CCTable cc_table[];
 
-void helper_load_seg(int seg_reg, int selector);
-void helper_ljmp_protected_T0_T1(int next_eip);
-void helper_lcall_real_T0_T1(int shift, int next_eip);
-void helper_lcall_protected_T0_T1(int shift, int next_eip);
-void helper_iret_real(int shift);
-void helper_iret_protected(int shift, int next_eip);
-void helper_lret_protected(int shift, int addend);
-void helper_movl_crN_T0(int reg);
-void helper_movl_drN_T0(int reg);
-void helper_invlpg(target_ulong addr);
 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
 void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
@@ -141,18 +131,11 @@
 
 #include "helper.h"
 
-void helper_mulq_EAX_T0(void);
-void helper_imulq_EAX_T0(void);
-void helper_imulq_T0_T1(void);
-void helper_cmpxchg8b(void);
+static inline void svm_check_intercept(uint32_t type)
+{
+    helper_svm_check_intercept_param(type, 0);
+}
 
-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);
-
 #if !defined(CONFIG_USER_ONLY)
 
 #include "softmmu_exec.h"
@@ -363,7 +346,6 @@
 void fpu_raise_exception(void);
 void restore_native_fp_state(CPUState *env);
 void save_native_fp_state(CPUState *env);
-void vmexit(uint64_t exit_code, uint64_t exit_info_1);
 
 extern const uint8_t parity_table[256];
 extern const uint8_t rclw_table[32];

Modified: trunk/target-i386/helper.c
===================================================================
--- trunk/target-i386/helper.c  2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/helper.c  2008-05-15 16:46:30 UTC (rev 4459)
@@ -17,6 +17,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#define CPU_NO_GLOBAL_REGS
 #include "exec.h"
 #include "host-utils.h"
 
@@ -93,16 +94,16 @@
     3.32192809488736234781L,  /*l2t*/
 };
 
-/* thread support */
+/* broken thread support */
 
 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
 
-void cpu_lock(void)
+void helper_lock(void)
 {
     spin_lock(&global_cpu_lock);
 }
 
-void cpu_unlock(void)
+void helper_unlock(void)
 {
     spin_unlock(&global_cpu_lock);
 }
@@ -508,36 +509,51 @@
     }
 }
 
-void check_iob_T0(void)
+void helper_check_iob(uint32_t t0)
 {
-    check_io(T0, 1);
+    check_io(t0, 1);
 }
 
-void check_iow_T0(void)
+void helper_check_iow(uint32_t t0)
 {
-    check_io(T0, 2);
+    check_io(t0, 2);
 }
 
-void check_iol_T0(void)
+void helper_check_iol(uint32_t t0)
 {
-    check_io(T0, 4);
+    check_io(t0, 4);
 }
 
-void check_iob_DX(void)
+void helper_outb(uint32_t port, uint32_t data)
 {
-    check_io(EDX & 0xffff, 1);
+    cpu_outb(env, port, data & 0xff);
 }
 
-void check_iow_DX(void)
+target_ulong helper_inb(uint32_t port)
 {
-    check_io(EDX & 0xffff, 2);
+    return cpu_inb(env, port);
 }
 
-void check_iol_DX(void)
+void helper_outw(uint32_t port, uint32_t data)
 {
-    check_io(EDX & 0xffff, 4);
+    cpu_outw(env, port, data & 0xffff);
 }
 
+target_ulong helper_inw(uint32_t port)
+{
+    return cpu_inw(env, port);
+}
+
+void helper_outl(uint32_t port, uint32_t data)
+{
+    cpu_outl(env, port, data);
+}
+
+target_ulong helper_inl(uint32_t port)
+{
+    return cpu_inl(env, port);
+}
+
 static inline unsigned int get_sp_mask(unsigned int e2)
 {
     if (e2 & DESC_B_MASK)
@@ -1275,7 +1291,7 @@
                      int next_eip_addend)
 {
     if (!is_int) {
-        svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
+        helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, 
error_code);
         intno = check_exception(intno, &error_code);
     }
 
@@ -1857,19 +1873,19 @@
     FORCE_RET();
 }
 
-void helper_cmpxchg8b(void)
+void helper_cmpxchg8b(target_ulong a0)
 {
     uint64_t d;
     int eflags;
 
     eflags = cc_table[CC_OP].compute_all();
-    d = ldq(A0);
+    d = ldq(a0);
     if (d == (((uint64_t)EDX << 32) | EAX)) {
-        stq(A0, ((uint64_t)ECX << 32) | EBX);
+        stq(a0, ((uint64_t)ECX << 32) | EBX);
         eflags |= CC_Z;
     } else {
-        EDX = d >> 32;
-        EAX = d;
+        EDX = (uint32_t)(d >> 32);
+        EAX = (uint32_t)d;
         eflags &= ~CC_Z;
     }
     CC_SRC = eflags;
@@ -1986,7 +2002,7 @@
     }
 }
 
-void helper_enter_level(int level, int data32)
+void helper_enter_level(int level, int data32, target_ulong t1)
 {
     target_ulong ssp;
     uint32_t esp_mask, esp, ebp;
@@ -2004,7 +2020,7 @@
             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
         }
         esp -= 4;
-        stl(ssp + (esp & esp_mask), T1);
+        stl(ssp + (esp & esp_mask), t1);
     } else {
         /* 16 bit */
         esp -= 2;
@@ -2014,12 +2030,12 @@
             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
         }
         esp -= 2;
-        stw(ssp + (esp & esp_mask), T1);
+        stw(ssp + (esp & esp_mask), t1);
     }
 }
 
 #ifdef TARGET_X86_64
-void helper_enter64_level(int level, int data64)
+void helper_enter64_level(int level, int data64, target_ulong t1)
 {
     target_ulong esp, ebp;
     ebp = EBP;
@@ -2034,7 +2050,7 @@
             stq(esp, ldq(ebp));
         }
         esp -= 8;
-        stq(esp, T1);
+        stq(esp, t1);
     } else {
         /* 16 bit */
         esp -= 2;
@@ -2044,7 +2060,7 @@
             stw(esp, lduw(ebp));
         }
         esp -= 2;
-        stw(esp, T1);
+        stw(esp, t1);
     }
 }
 #endif
@@ -2231,14 +2247,13 @@
 }
 
 /* protected mode jump */
-void helper_ljmp_protected_T0_T1(int next_eip_addend)
+void helper_ljmp_protected(int new_cs, target_ulong new_eip,
+                           int next_eip_addend)
 {
-    int new_cs, gate_cs, type;
+    int gate_cs, type;
     uint32_t e1, e2, cpl, dpl, rpl, limit;
-    target_ulong new_eip, next_eip;
+    target_ulong next_eip;
 
-    new_cs = T0;
-    new_eip = T1;
     if ((new_cs & 0xfffc) == 0)
         raise_exception_err(EXCP0D_GPF, 0);
     if (load_segment(&e1, &e2, new_cs) != 0)
@@ -2322,14 +2337,14 @@
 }
 
 /* real mode call */
-void helper_lcall_real_T0_T1(int shift, int next_eip)
+void helper_lcall_real(int new_cs, target_ulong new_eip1,
+                       int shift, int next_eip)
 {
-    int new_cs, new_eip;
+    int new_eip;
     uint32_t esp, esp_mask;
     target_ulong ssp;
 
-    new_cs = T0;
-    new_eip = T1;
+    new_eip = new_eip1;
     esp = ESP;
     esp_mask = get_sp_mask(env->segs[R_SS].flags);
     ssp = env->segs[R_SS].base;
@@ -2348,16 +2363,15 @@
 }
 
 /* protected mode call */
-void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
+void helper_lcall_protected(int new_cs, target_ulong new_eip, 
+                            int shift, int next_eip_addend)
 {
-    int new_cs, new_stack, i;
+    int new_stack, i;
     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
     uint32_t val, limit, old_sp_mask;
-    target_ulong ssp, old_ssp, next_eip, new_eip;
+    target_ulong ssp, old_ssp, next_eip;
 
-    new_cs = T0;
-    new_eip = T1;
     next_eip = env->eip + next_eip_addend;
 #ifdef DEBUG_PCALL
     if (loglevel & CPU_LOG_PCALL) {
@@ -2922,34 +2936,55 @@
 #endif
 }
 
-void helper_movl_crN_T0(int reg)
+void helper_movl_crN_T0(int reg, target_ulong t0)
 {
 #if !defined(CONFIG_USER_ONLY)
     switch(reg) {
     case 0:
-        cpu_x86_update_cr0(env, T0);
+        cpu_x86_update_cr0(env, t0);
         break;
     case 3:
-        cpu_x86_update_cr3(env, T0);
+        cpu_x86_update_cr3(env, t0);
         break;
     case 4:
-        cpu_x86_update_cr4(env, T0);
+        cpu_x86_update_cr4(env, t0);
         break;
     case 8:
-        cpu_set_apic_tpr(env, T0);
-        env->cr[8] = T0;
+        cpu_set_apic_tpr(env, t0);
+        env->cr[8] = t0;
         break;
     default:
-        env->cr[reg] = T0;
+        env->cr[reg] = t0;
         break;
     }
 #endif
 }
 
+void helper_lmsw(target_ulong t0)
+{
+    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
+       if already set to one. */
+    t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
+    helper_movl_crN_T0(0, t0);
+}
+
+void helper_clts(void)
+{
+    env->cr[0] &= ~CR0_TS_MASK;
+    env->hflags &= ~HF_TS_MASK;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+target_ulong helper_movtl_T0_cr8(void)
+{
+    return cpu_get_apic_tpr(env);
+}
+#endif
+
 /* XXX: do more */
-void helper_movl_drN_T0(int reg)
+void helper_movl_drN_T0(int reg, target_ulong t0)
 {
-    env->dr[reg] = T0;
+    env->dr[reg] = t0;
 }
 
 void helper_invlpg(target_ulong addr)
@@ -2975,10 +3010,10 @@
         raise_exception(EXCP0D_GPF);
     }
 
-    if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) {
-        /* currently unimplemented */
-        raise_exception_err(EXCP06_ILLOP, 0);
-    }
+    helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
+    
+    /* currently unimplemented */
+    raise_exception_err(EXCP06_ILLOP, 0);
 }
 
 #if defined(CONFIG_USER_ONLY)
@@ -3118,7 +3153,7 @@
 }
 #endif
 
-void helper_lsl(uint32_t selector)
+uint32_t helper_lsl(uint32_t selector)
 {
     unsigned int limit;
     uint32_t e1, e2, eflags;
@@ -3153,15 +3188,15 @@
         if (dpl < cpl || dpl < rpl) {
         fail:
             CC_SRC = eflags & ~CC_Z;
-            return;
+            return 0;
         }
     }
     limit = get_seg_limit(e1, e2);
-    T1 = limit;
     CC_SRC = eflags | CC_Z;
+    return limit;
 }
 
-void helper_lar(uint32_t selector)
+uint32_t helper_lar(uint32_t selector)
 {
     uint32_t e1, e2, eflags;
     int rpl, dpl, cpl, type;
@@ -3200,11 +3235,11 @@
         if (dpl < cpl || dpl < rpl) {
         fail:
             CC_SRC = eflags & ~CC_Z;
-            return;
+            return 0;
         }
     }
-    T1 = e2 & 0x00f0ff00;
     CC_SRC = eflags | CC_Z;
+    return e2 & 0x00f0ff00;
 }
 
 void helper_verr(uint32_t selector)
@@ -4412,36 +4447,36 @@
     return 0;
 }
 
-void helper_mulq_EAX_T0(void)
+void helper_mulq_EAX_T0(target_ulong t0)
 {
     uint64_t r0, r1;
 
-    mulu64(&r0, &r1, EAX, T0);
+    mulu64(&r0, &r1, EAX, t0);
     EAX = r0;
     EDX = r1;
     CC_DST = r0;
     CC_SRC = r1;
 }
 
-void helper_imulq_EAX_T0(void)
+void helper_imulq_EAX_T0(target_ulong t0)
 {
     uint64_t r0, r1;
 
-    muls64(&r0, &r1, EAX, T0);
+    muls64(&r0, &r1, EAX, t0);
     EAX = r0;
     EDX = r1;
     CC_DST = r0;
     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
 }
 
-void helper_imulq_T0_T1(void)
+target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
 {
     uint64_t r0, r1;
 
-    muls64(&r0, &r1, T0, T1);
-    T0 = r0;
+    muls64(&r0, &r1, t0, t1);
     CC_DST = r0;
     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
+    return r0;
 }
 
 void helper_divq_EAX(target_ulong t0)
@@ -4553,24 +4588,23 @@
     env->hflags &= ~HF_INHIBIT_IRQ_MASK;
 }
 
-void helper_boundw(void)
+void helper_boundw(target_ulong a0, int v)
 {
-    int low, high, v;
-    low = ldsw(A0);
-    high = ldsw(A0 + 2);
-    v = (int16_t)T0;
+    int low, high;
+    low = ldsw(a0);
+    high = ldsw(a0 + 2);
+    v = (int16_t)v;
     if (v < low || v > high) {
         raise_exception(EXCP05_BOUND);
     }
     FORCE_RET();
 }
 
-void helper_boundl(void)
+void helper_boundl(target_ulong a0, int v)
 {
-    int low, high, v;
-    low = ldl(A0);
-    high = ldl(A0 + 4);
-    v = T0;
+    int low, high;
+    low = ldl(a0);
+    high = ldl(a0 + 4);
     if (v < low || v > high) {
         raise_exception(EXCP05_BOUND);
     }
@@ -4661,18 +4695,35 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void helper_vmrun(void) { }
-void helper_vmmcall(void) { }
-void helper_vmload(void) { }
-void helper_vmsave(void) { }
-void helper_skinit(void) { }
-void helper_invlpga(void) { }
-void vmexit(uint64_t exit_code, uint64_t exit_info_1) { }
-int svm_check_intercept_param(uint32_t type, uint64_t param)
+void helper_vmrun(void) 
+{ 
+}
+void helper_vmmcall(void) 
+{ 
+}
+void helper_vmload(void) 
+{ 
+}
+void helper_vmsave(void) 
+{ 
+}
+void helper_skinit(void) 
+{ 
+}
+void helper_invlpga(void) 
+{ 
+}
+void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
+{ 
+}
+void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
 {
-    return 0;
 }
 
+void helper_svm_check_io(uint32_t port, uint32_t param, 
+                         uint32_t next_eip_addend)
+{
+}
 #else
 
 static inline uint32_t
@@ -4702,7 +4753,6 @@
         fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
 
     env->vm_vmcb = addr;
-    regs_to_env();
 
     /* save the current CPU state in the hsave page */
     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), 
env->gdt.base);
@@ -4801,8 +4851,6 @@
 
     helper_stgi();
 
-    regs_to_env();
-
     /* maybe we need to inject an event */
     event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.event_inj));
     if (event_inj & SVM_EVTINJ_VALID) {
@@ -4927,95 +4975,98 @@
     tlb_flush(env, 0);
 }
 
-int svm_check_intercept_param(uint32_t type, uint64_t param)
+void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
 {
     switch(type) {
     case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
         if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) {
-            vmexit(type, param);
-            return 1;
+            helper_vmexit(type, param);
         }
         break;
     case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8:
         if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) {
-            vmexit(type, param);
-            return 1;
+            helper_vmexit(type, param);
         }
         break;
     case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
         if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) {
-            vmexit(type, param);
-            return 1;
+            helper_vmexit(type, param);
         }
         break;
     case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8:
         if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) {
-            vmexit(type, param);
-            return 1;
+            helper_vmexit(type, param);
         }
         break;
     case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16:
         if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) {
-            vmexit(type, param);
-            return 1;
+            helper_vmexit(type, param);
         }
         break;
     case SVM_EXIT_IOIO:
-        if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) {
-            /* FIXME: this should be read in at vmrun (faster this way?) */
-            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.iopm_base_pa));
-            uint16_t port = (uint16_t) (param >> 16);
-
-            uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
-            if(lduw_phys(addr + port / 8) & (mask << (port & 7)))
-                vmexit(type, param);
-        }
         break;
 
     case SVM_EXIT_MSR:
         if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) {
             /* FIXME: this should be read in at vmrun (faster this way?) */
             uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.msrpm_base_pa));
+            uint32_t t0, t1;
             switch((uint32_t)ECX) {
             case 0 ... 0x1fff:
-                T0 = (ECX * 2) % 8;
-                T1 = ECX / 8;
+                t0 = (ECX * 2) % 8;
+                t1 = ECX / 8;
                 break;
             case 0xc0000000 ... 0xc0001fff:
-                T0 = (8192 + ECX - 0xc0000000) * 2;
-                T1 = (T0 / 8);
-                T0 %= 8;
+                t0 = (8192 + ECX - 0xc0000000) * 2;
+                t1 = (t0 / 8);
+                t0 %= 8;
                 break;
             case 0xc0010000 ... 0xc0011fff:
-                T0 = (16384 + ECX - 0xc0010000) * 2;
-                T1 = (T0 / 8);
-                T0 %= 8;
+                t0 = (16384 + ECX - 0xc0010000) * 2;
+                t1 = (t0 / 8);
+                t0 %= 8;
                 break;
             default:
-                vmexit(type, param);
-                return 1;
+                helper_vmexit(type, param);
+                t0 = 0;
+                t1 = 0;
+                break;
             }
-            if (ldub_phys(addr + T1) & ((1 << param) << T0))
-                vmexit(type, param);
-            return 1;
+            if (ldub_phys(addr + t1) & ((1 << param) << t0))
+                helper_vmexit(type, param);
         }
         break;
     default:
         if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) {
-            vmexit(type, param);
-            return 1;
+            helper_vmexit(type, param);
         }
         break;
     }
-    return 0;
 }
 
-void vmexit(uint64_t exit_code, uint64_t exit_info_1)
+void helper_svm_check_io(uint32_t port, uint32_t param, 
+                         uint32_t next_eip_addend)
 {
+    if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) {
+        /* FIXME: this should be read in at vmrun (faster this way?) */
+        uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.iopm_base_pa));
+        uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
+        if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
+            /* next EIP */
+            stq_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.exit_info_2), 
+                     env->eip + next_eip_addend);
+            helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
+        }
+    }
+}
+
+/* Note: currently only 32 bits of exit_code are used */
+void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
+{
     uint32_t int_ctl;
 
     if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile,"vmexit(%016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 
", " TARGET_FMT_lx ")!\n",
+        fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " 
TARGET_FMT_lx ")!\n",
                 exit_code, exit_info_1,
                 ldq_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.exit_info_2)),
                 EIP);
@@ -5105,8 +5156,7 @@
 
     /* other setups */
     cpu_x86_set_cpl(env, 0);
-    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code_hi), 
(uint32_t)(exit_code >> 32));
-    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), 
exit_code);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), 
exit_code);
     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), 
exit_info_1);
 
     helper_clgi();
@@ -5137,7 +5187,6 @@
     env->error_code = 0;
     env->old_exception = -1;
 
-    regs_to_env();
     cpu_loop_exit();
 }
 

Modified: trunk/target-i386/helper.h
===================================================================
--- trunk/target-i386/helper.h  2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/helper.h  2008-05-15 16:46:30 UTC (rev 4459)
@@ -1,5 +1,7 @@
 #define TCG_HELPER_PROTO
 
+void helper_lock(void);
+void helper_unlock(void);
 void helper_divb_AL(target_ulong t0);
 void helper_idivb_AL(target_ulong t0);
 void helper_divw_AX(target_ulong t0);
@@ -7,6 +9,9 @@
 void helper_divl_EAX(target_ulong t0);
 void helper_idivl_EAX(target_ulong t0);
 #ifdef TARGET_X86_64
+void helper_mulq_EAX_T0(target_ulong t0);
+void helper_imulq_EAX_T0(target_ulong t0);
+target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1);
 void helper_divq_EAX(target_ulong t0);
 void helper_idivq_EAX(target_ulong t0);
 #endif
@@ -18,26 +23,34 @@
 void helper_daa(void);
 void helper_das(void);
 
-void helper_lsl(uint32_t selector);
-void helper_lar(uint32_t selector);
+uint32_t helper_lsl(uint32_t selector);
+uint32_t helper_lar(uint32_t selector);
 void helper_verr(uint32_t selector);
 void helper_verw(uint32_t selector);
 void helper_lldt(int selector);
 void helper_ltr(int selector);
 void helper_load_seg(int seg_reg, int selector);
-void helper_ljmp_protected_T0_T1(int next_eip);
-void helper_lcall_real_T0_T1(int shift, int next_eip);
-void helper_lcall_protected_T0_T1(int shift, int next_eip);
+void helper_ljmp_protected(int new_cs, target_ulong new_eip,
+                           int next_eip_addend);
+void helper_lcall_real(int new_cs, target_ulong new_eip1,
+                       int shift, int next_eip);
+void helper_lcall_protected(int new_cs, target_ulong new_eip, 
+                            int shift, int next_eip_addend);
 void helper_iret_real(int shift);
 void helper_iret_protected(int shift, int next_eip);
 void helper_lret_protected(int shift, int addend);
-void helper_movl_crN_T0(int reg);
-void helper_movl_drN_T0(int reg);
+void helper_movl_crN_T0(int reg, target_ulong t0);
+void helper_lmsw(target_ulong t0);
+void helper_clts(void);
+#if !defined(CONFIG_USER_ONLY)
+target_ulong helper_movtl_T0_cr8(void);
+#endif
+void helper_movl_drN_T0(int reg, target_ulong t0);
 void helper_invlpg(target_ulong addr);
 
-void helper_enter_level(int level, int data32);
+void helper_enter_level(int level, int data32, target_ulong t1);
 #ifdef TARGET_X86_64
-void helper_enter64_level(int level, int data64);
+void helper_enter64_level(int level, int data64, target_ulong t1);
 #endif
 void helper_sysenter(void);
 void helper_sysexit(void);
@@ -55,9 +68,10 @@
 void helper_sti(void);
 void helper_set_inhibit_irq(void);
 void helper_reset_inhibit_irq(void);
-void helper_boundw(void);
-void helper_boundl(void);
+void helper_boundw(target_ulong a0, int v);
+void helper_boundl(target_ulong a0, int v);
 void helper_rsm(void);
+void helper_cmpxchg8b(target_ulong a0);
 void helper_single_step(void);
 void helper_cpuid(void);
 void helper_rdtsc(void);
@@ -65,6 +79,20 @@
 void helper_rdmsr(void);
 void helper_wrmsr(void);
 
+void helper_check_iob(uint32_t t0);
+void helper_check_iow(uint32_t t0);
+void helper_check_iol(uint32_t t0);
+void helper_outb(uint32_t port, uint32_t data);
+target_ulong helper_inb(uint32_t port);
+void helper_outw(uint32_t port, uint32_t data);
+target_ulong helper_inw(uint32_t port);
+void helper_outl(uint32_t port, uint32_t data);
+target_ulong helper_inl(uint32_t port);
+
+void helper_svm_check_intercept_param(uint32_t type, uint64_t param);
+void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1);
+void helper_svm_check_io(uint32_t port, uint32_t param, 
+                         uint32_t next_eip_addend);
 void helper_vmrun(void);
 void helper_vmmcall(void);
 void helper_vmload(void);

Modified: trunk/target-i386/op.c
===================================================================
--- trunk/target-i386/op.c      2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/op.c      2008-05-15 16:46:30 UTC (rev 4459)
@@ -276,17 +276,17 @@
 #ifdef TARGET_X86_64
 void OPPROTO op_mulq_EAX_T0(void)
 {
-    helper_mulq_EAX_T0();
+    helper_mulq_EAX_T0(T0);
 }
 
 void OPPROTO op_imulq_EAX_T0(void)
 {
-    helper_imulq_EAX_T0();
+    helper_imulq_EAX_T0(T0);
 }
 
 void OPPROTO op_imulq_T0_T1(void)
 {
-    helper_imulq_T0_T1();
+    T0 = helper_imulq_T0_T1(T0, T1);
 }
 #endif
 
@@ -351,7 +351,7 @@
 
 void OPPROTO op_cmpxchg8b(void)
 {
-    helper_cmpxchg8b();
+    helper_cmpxchg8b(A0);
 }
 
 /* multiple size ops */
@@ -522,12 +522,6 @@
 
 /* segment handling */
 
-/* never use it with R_CS */
-void OPPROTO op_movl_seg_T0(void)
-{
-    helper_load_seg(PARAM1, T0);
-}
-
 /* faster VM86 version */
 void OPPROTO op_movl_seg_T0_vm(void)
 {
@@ -548,12 +542,20 @@
 
 void OPPROTO op_lsl(void)
 {
-    helper_lsl(T0);
+    uint32_t val;
+    val = helper_lsl(T0);
+    if (CC_SRC & CC_Z)
+        T1 = val;
+    FORCE_RET();
 }
 
 void OPPROTO op_lar(void)
 {
-    helper_lar(T0);
+    uint32_t val;
+    val = helper_lar(T0);
+    if (CC_SRC & CC_Z)
+        T1 = val;
+    FORCE_RET();
 }
 
 void OPPROTO op_verr(void)
@@ -585,104 +587,6 @@
     CC_SRC = (eflags & ~CC_Z) | T1;
 }
 
-/* T0: segment, T1:eip */
-void OPPROTO op_ljmp_protected_T0_T1(void)
-{
-    helper_ljmp_protected_T0_T1(PARAM1);
-}
-
-void OPPROTO op_lcall_real_T0_T1(void)
-{
-    helper_lcall_real_T0_T1(PARAM1, PARAM2);
-}
-
-void OPPROTO op_lcall_protected_T0_T1(void)
-{
-    helper_lcall_protected_T0_T1(PARAM1, PARAM2);
-}
-
-void OPPROTO op_iret_real(void)
-{
-    helper_iret_real(PARAM1);
-}
-
-void OPPROTO op_iret_protected(void)
-{
-    helper_iret_protected(PARAM1, PARAM2);
-}
-
-void OPPROTO op_lret_protected(void)
-{
-    helper_lret_protected(PARAM1, PARAM2);
-}
-
-/* CR registers access. */
-void OPPROTO op_movl_crN_T0(void)
-{
-    helper_movl_crN_T0(PARAM1);
-}
-
-/* These pseudo-opcodes check for SVM intercepts. */
-void OPPROTO op_svm_check_intercept(void)
-{
-    A0 = PARAM1 & PARAM2;
-    svm_check_intercept(PARAMQ1);
-}
-
-void OPPROTO op_svm_check_intercept_param(void)
-{
-    A0 = PARAM1 & PARAM2;
-    svm_check_intercept_param(PARAMQ1, T1);
-}
-
-void OPPROTO op_svm_vmexit(void)
-{
-    A0 = PARAM1 & PARAM2;
-    vmexit(PARAMQ1, T1);
-}
-
-void OPPROTO op_geneflags(void)
-{
-    CC_SRC = cc_table[CC_OP].compute_all();
-}
-
-/* This pseudo-opcode checks for IO intercepts. */
-#if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_svm_check_intercept_io(void)
-{
-    A0 = PARAM1 & PARAM2;
-    /* PARAMQ1 = TYPE (0 = OUT, 1 = IN; 4 = STRING; 8 = REP)
-       T0      = PORT
-       T1      = next eip */
-    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), T1);
-    /* ASIZE does not appear on real hw */
-    svm_check_intercept_param(SVM_EXIT_IOIO,
-                              (PARAMQ1 & ~SVM_IOIO_ASIZE_MASK) |
-                              ((T0 & 0xffff) << 16));
-}
-#endif
-
-#if !defined(CONFIG_USER_ONLY)
-void OPPROTO op_movtl_T0_cr8(void)
-{
-    T0 = cpu_get_apic_tpr(env);
-}
-#endif
-
-/* DR registers access */
-void OPPROTO op_movl_drN_T0(void)
-{
-    helper_movl_drN_T0(PARAM1);
-}
-
-void OPPROTO op_lmsw_T0(void)
-{
-    /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
-       if already set to one. */
-    T0 = (env->cr[0] & ~0xe) | (T0 & 0xf);
-    helper_movl_crN_T0(0);
-}
-
 void OPPROTO op_movl_T0_env(void)
 {
     T0 = *(uint32_t *)((char *)env + PARAM1);
@@ -718,12 +622,6 @@
     *(target_ulong *)((char *)env + PARAM1) = T1;
 }
 
-void OPPROTO op_clts(void)
-{
-    env->cr[0] &= ~CR0_TS_MASK;
-    env->hflags &= ~HF_TS_MASK;
-}
-
 /* flags handling */
 
 void OPPROTO op_jmp_label(void)
@@ -1028,17 +926,6 @@
     T0 = 0;
 }
 
-/* threading support */
-void OPPROTO op_lock(void)
-{
-    cpu_lock();
-}
-
-void OPPROTO op_unlock(void)
-{
-    cpu_unlock();
-}
-
 /* SSE support */
 void OPPROTO op_com_dummy(void)
 {

Modified: trunk/target-i386/ops_sse.h
===================================================================
--- trunk/target-i386/ops_sse.h 2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/ops_sse.h 2008-05-15 16:46:30 UTC (rev 4459)
@@ -471,12 +471,12 @@
 #endif
 }
 
-void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s)
+void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s, target_ulong a0)
 {
     int i;
     for(i = 0; i < (8 << SHIFT); i++) {
         if (s->B(i) & 0x80)
-            stb(A0 + i, d->B(i));
+            stb(a0 + i, d->B(i));
     }
     FORCE_RET();
 }

Modified: trunk/target-i386/ops_sse_header.h
===================================================================
--- trunk/target-i386/ops_sse_header.h  2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/ops_sse_header.h  2008-05-15 16:46:30 UTC (rev 4459)
@@ -104,7 +104,7 @@
 void glue(helper_pmaddwd, SUFFIX) (Reg *d, Reg *s);
 
 void glue(helper_psadbw, SUFFIX) (Reg *d, Reg *s);
-void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s);
+void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s, target_ulong a0);
 void glue(helper_movl_mm_T0, SUFFIX) (Reg *d, uint32_t val);
 #ifdef TARGET_X86_64
 void glue(helper_movq_mm_T0, SUFFIX) (Reg *d, uint64_t val);

Modified: trunk/target-i386/ops_template.h
===================================================================
--- trunk/target-i386/ops_template.h    2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/ops_template.h    2008-05-15 16:46:30 UTC (rev 4459)
@@ -554,39 +554,6 @@
     T0 = DF << SHIFT;
 }
 
-/* port I/O */
-#if DATA_BITS <= 32
-void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
-{
-    glue(cpu_out, SUFFIX)(env, T0, T1 & DATA_MASK);
-}
-
-void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
-{
-    T1 = glue(cpu_in, SUFFIX)(env, T0);
-}
-
-void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
-{
-    T0 = glue(cpu_in, SUFFIX)(env, EDX & 0xffff);
-}
-
-void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
-{
-    glue(cpu_out, SUFFIX)(env, EDX & 0xffff, T0);
-}
-
-void OPPROTO glue(glue(op_check_io, SUFFIX), _T0)(void)
-{
-    glue(glue(check_io, SUFFIX), _T0)();
-}
-
-void OPPROTO glue(glue(op_check_io, SUFFIX), _DX)(void)
-{
-    glue(glue(check_io, SUFFIX), _DX)();
-}
-#endif
-
 #undef DATA_BITS
 #undef SHIFT_MASK
 #undef SHIFT1_MASK

Modified: trunk/target-i386/svm.h
===================================================================
--- trunk/target-i386/svm.h     2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/svm.h     2008-05-15 16:46:30 UTC (rev 4459)
@@ -71,8 +71,7 @@
        uint32_t int_vector;
        uint32_t int_state;
        uint8_t reserved_3[4];
-       uint32_t exit_code;
-       uint32_t exit_code_hi;
+       uint64_t exit_code;
        uint64_t exit_info_1;
        uint64_t exit_info_2;
        uint32_t exit_int_info;
@@ -323,14 +322,6 @@
 
 /* function references */
 
-void helper_stgi(void);
-void vmexit(uint64_t exit_code, uint64_t exit_info_1);
-int svm_check_intercept_param(uint32_t type, uint64_t param);
-static inline int svm_check_intercept(unsigned int type) {
-    return svm_check_intercept_param(type, 0);
-}
-
-
 #define INTERCEPTED(mask) (env->intercept & mask)
 #define INTERCEPTEDw(var, mask) (env->intercept ## var & mask)
 #define INTERCEPTEDl(var, mask) (env->intercept ## var & mask)

Modified: trunk/target-i386/translate.c
===================================================================
--- trunk/target-i386/translate.c       2008-05-15 16:17:07 UTC (rev 4458)
+++ trunk/target-i386/translate.c       2008-05-15 16:46:30 UTC (rev 4459)
@@ -60,7 +60,7 @@
 /* global register indexes */
 static TCGv cpu_env, cpu_T[2], cpu_A0;
 /* local register indexes (only used inside old micro ops) */
-static TCGv cpu_tmp0, cpu_tmp1, cpu_tmp2, cpu_ptr0, cpu_ptr1;
+static TCGv cpu_tmp0, cpu_tmp1, cpu_tmp2, cpu_tmp3, cpu_ptr0, cpu_ptr1;
 
 #ifdef TARGET_X86_64
 static int x86_64_hregs;
@@ -903,53 +903,55 @@
     },
 };
 
-static GenOpFunc *gen_op_in_DX_T0[3] = {
-    gen_op_inb_DX_T0,
-    gen_op_inw_DX_T0,
-    gen_op_inl_DX_T0,
+static void *helper_in_func[3] = {
+    helper_inb,
+    helper_inw,
+    helper_inl,
 };
 
-static GenOpFunc *gen_op_out_DX_T0[3] = {
-    gen_op_outb_DX_T0,
-    gen_op_outw_DX_T0,
-    gen_op_outl_DX_T0,
+static void *helper_out_func[3] = {
+    helper_outb,
+    helper_outw,
+    helper_outl,
 };
 
-static GenOpFunc *gen_op_in[3] = {
-    gen_op_inb_T0_T1,
-    gen_op_inw_T0_T1,
-    gen_op_inl_T0_T1,
+static void *gen_check_io_func[3] = {
+    helper_check_iob,
+    helper_check_iow,
+    helper_check_iol,
 };
 
-static GenOpFunc *gen_op_out[3] = {
-    gen_op_outb_T0_T1,
-    gen_op_outw_T0_T1,
-    gen_op_outl_T0_T1,
-};
+static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
+                         uint32_t svm_flags)
+{
+    int state_saved;
+    target_ulong next_eip;
 
-static GenOpFunc *gen_check_io_T0[3] = {
-    gen_op_check_iob_T0,
-    gen_op_check_iow_T0,
-    gen_op_check_iol_T0,
-};
-
-static GenOpFunc *gen_check_io_DX[3] = {
-    gen_op_check_iob_DX,
-    gen_op_check_iow_DX,
-    gen_op_check_iol_DX,
-};
-
-static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong 
cur_eip)
-{
+    state_saved = 0;
     if (s->pe && (s->cpl > s->iopl || s->vm86)) {
         if (s->cc_op != CC_OP_DYNAMIC)
             gen_op_set_cc_op(s->cc_op);
         gen_jmp_im(cur_eip);
-        if (use_dx)
-            gen_check_io_DX[ot]();
-        else
-            gen_check_io_T0[ot]();
+        state_saved = 1;
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+        tcg_gen_helper_0_1(gen_check_io_func[ot],
+                           cpu_tmp2);
     }
+    if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
+        if (!state_saved) {
+            if (s->cc_op != CC_OP_DYNAMIC)
+                gen_op_set_cc_op(s->cc_op);
+            gen_jmp_im(cur_eip);
+            state_saved = 1;
+        }
+        svm_flags |= (1 << (4 + ot));
+        next_eip = s->pc - s->cs_base;
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+        tcg_gen_helper_0_3(helper_svm_check_io,
+                           cpu_tmp2,
+                           tcg_const_i32(svm_flags),
+                           tcg_const_i32(next_eip - cur_eip));
+    }
 }
 
 static inline void gen_movs(DisasContext *s, int ot)
@@ -1080,7 +1082,10 @@
     gen_string_movl_A0_EDI(s);
     gen_op_movl_T0_0();
     gen_op_st_T0_A0(ot + s->mem_index);
-    gen_op_in_DX_T0[ot]();
+    gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
+    tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[1]);
+    tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff);
+    tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[0], cpu_tmp2);
     gen_op_st_T0_A0(ot + s->mem_index);
     gen_op_movl_T0_Dshift[ot]();
 #ifdef TARGET_X86_64
@@ -1099,7 +1104,13 @@
 {
     gen_string_movl_A0_ESI(s);
     gen_op_ld_T0_A0(ot + s->mem_index);
-    gen_op_out_DX_T0[ot]();
+
+    gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
+    tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[1]);
+    tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff);
+    tcg_gen_trunc_tl_i32(cpu_tmp3, cpu_T[0]);
+    tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2, cpu_tmp3);
+
     gen_op_movl_T0_Dshift[ot]();
 #ifdef TARGET_X86_64
     if (s->aflag == 2) {
@@ -1976,7 +1987,8 @@
         if (s->cc_op != CC_OP_DYNAMIC)
             gen_op_set_cc_op(s->cc_op);
         gen_jmp_im(cur_eip);
-        gen_op_movl_seg_T0(seg_reg);
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+        tcg_gen_helper_0_2(helper_load_seg, tcg_const_i32(seg_reg), cpu_tmp2);
         /* abort translation because the addseg value may change or
            because ss32 may change. For R_SS, translation must always
            stop as a special handling must be done to disable hardware
@@ -1990,28 +2002,6 @@
     }
 }
 
-#define SVM_movq_T1_im(x) gen_movtl_T1_im(x)
-
-static inline int
-gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type)
-{
-#if !defined(CONFIG_USER_ONLY)
-    if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
-        if (s->cc_op != CC_OP_DYNAMIC)
-            gen_op_set_cc_op(s->cc_op);
-        SVM_movq_T1_im(s->pc - s->cs_base);
-        gen_jmp_im(pc_start - s->cs_base);
-        gen_op_geneflags();
-        gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type);
-        s->cc_op = CC_OP_DYNAMIC;
-        /* FIXME: maybe we could move the io intercept vector to the TB as well
-                  so we know if this is an EOB or not ... let's assume it's not
-                  for now. */
-    }
-#endif
-    return 0;
-}
-
 static inline int svm_is_rep(int prefixes)
 {
     return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
@@ -2019,7 +2009,7 @@
 
 static inline int
 gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
-                              uint64_t type, uint64_t param)
+                              uint32_t type, uint64_t param)
 {
     if(!(s->flags & (INTERCEPT_SVM_MASK)))
        /* no SVM activated */
@@ -2029,12 +2019,10 @@
         case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1:
             if (s->cc_op != CC_OP_DYNAMIC) {
                 gen_op_set_cc_op(s->cc_op);
-                s->cc_op = CC_OP_DYNAMIC;
             }
             gen_jmp_im(pc_start - s->cs_base);
-            SVM_movq_T1_im(param);
-            gen_op_geneflags();
-            gen_op_svm_check_intercept_param((uint32_t)(type >> 32), 
(uint32_t)type);
+            tcg_gen_helper_0_2(helper_svm_check_intercept_param, 
+                               tcg_const_i32(type), tcg_const_i64(param));
             /* this is a special case as we do not know if the interception 
occurs
                so we assume there was none */
             return 0;
@@ -2042,12 +2030,10 @@
             if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) {
                 if (s->cc_op != CC_OP_DYNAMIC) {
                     gen_op_set_cc_op(s->cc_op);
-                    s->cc_op = CC_OP_DYNAMIC;
                 }
                 gen_jmp_im(pc_start - s->cs_base);
-                SVM_movq_T1_im(param);
-                gen_op_geneflags();
-                gen_op_svm_check_intercept_param((uint32_t)(type >> 32), 
(uint32_t)type);
+                tcg_gen_helper_0_2(helper_svm_check_intercept_param,
+                                   tcg_const_i32(type), tcg_const_i64(param));
                 /* this is a special case as we do not know if the 
interception occurs
                    so we assume there was none */
                 return 0;
@@ -2057,12 +2043,10 @@
             if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) 
{
                 if (s->cc_op != CC_OP_DYNAMIC) {
                     gen_op_set_cc_op(s->cc_op);
-                   s->cc_op = CC_OP_EFLAGS;
                 }
                 gen_jmp_im(pc_start - s->cs_base);
-                SVM_movq_T1_im(param);
-                gen_op_geneflags();
-                gen_op_svm_vmexit(type >> 32, type);
+                tcg_gen_helper_0_2(helper_vmexit,
+                                   tcg_const_i32(type), tcg_const_i64(param));
                 /* we can optimize this one so TBs don't get longer
                    than up to vmexit */
                 gen_eob(s);
@@ -2276,9 +2260,10 @@
         gen_op_st_T0_A0(ot + s->mem_index);
         if (level) {
             /* XXX: must save state */
-            tcg_gen_helper_0_2(helper_enter64_level,
+            tcg_gen_helper_0_3(helper_enter64_level,
                                tcg_const_i32(level),
-                               tcg_const_i32((ot == OT_QUAD)));
+                               tcg_const_i32((ot == OT_QUAD)),
+                               cpu_T[1]);
         }
         gen_op_mov_reg_T1(ot, R_EBP);
         gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
@@ -2301,9 +2286,10 @@
         gen_op_st_T0_A0(ot + s->mem_index);
         if (level) {
             /* XXX: must save state */
-            tcg_gen_helper_0_2(helper_enter_level,
+            tcg_gen_helper_0_3(helper_enter_level,
                                tcg_const_i32(level),
-                               tcg_const_i32(s->dflag));
+                               tcg_const_i32(s->dflag),
+                               cpu_T[1]);
         }
         gen_op_mov_reg_T1(ot, R_EBP);
         gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
@@ -3208,22 +3194,6 @@
     } else {
         /* generic MMX or SSE operation */
         switch(b) {
-        case 0xf7:
-            /* maskmov : we must prepare A0 */
-            if (mod != 3)
-                goto illegal_op;
-#ifdef TARGET_X86_64
-            if (s->aflag == 2) {
-                gen_op_movq_A0_reg(R_EDI);
-            } else
-#endif
-            {
-                gen_op_movl_A0_reg(R_EDI);
-                if (s->aflag == 0)
-                    gen_op_andl_A0_ffff();
-            }
-            gen_add_A0_ds_seg(s);
-            break;
         case 0x70: /* pshufx insn */
         case 0xc6: /* pshufx insn */
         case 0xc2: /* compare insns */
@@ -3295,6 +3265,26 @@
             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
             tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);
             break;
+        case 0xf7:
+            /* maskmov : we must prepare A0 */
+            if (mod != 3)
+                goto illegal_op;
+#ifdef TARGET_X86_64
+            if (s->aflag == 2) {
+                gen_op_movq_A0_reg(R_EDI);
+            } else
+#endif
+            {
+                gen_op_movl_A0_reg(R_EDI);
+                if (s->aflag == 0)
+                    gen_op_andl_A0_ffff();
+            }
+            gen_add_A0_ds_seg(s);
+
+            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
+            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
+            tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, cpu_A0);
+            break;
         default:
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
             tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
@@ -3440,7 +3430,7 @@
 
     /* lock generation */
     if (prefixes & PREFIX_LOCK)
-        gen_op_lock();
+        tcg_gen_helper_0_0(helper_lock);
 
     /* now check op code */
  reswitch:
@@ -3783,9 +3773,17 @@
                 if (s->cc_op != CC_OP_DYNAMIC)
                     gen_op_set_cc_op(s->cc_op);
                 gen_jmp_im(pc_start - s->cs_base);
-                gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
+                tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+                tcg_gen_helper_0_4(helper_lcall_protected,
+                                   cpu_tmp2, cpu_T[1],
+                                   tcg_const_i32(dflag), 
+                                   tcg_const_i32(s->pc - pc_start));
             } else {
-                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
+                tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+                tcg_gen_helper_0_4(helper_lcall_real,
+                                   cpu_tmp2, cpu_T[1],
+                                   tcg_const_i32(dflag), 
+                                   tcg_const_i32(s->pc - s->cs_base));
             }
             gen_eob(s);
             break;
@@ -3804,7 +3802,11 @@
                 if (s->cc_op != CC_OP_DYNAMIC)
                     gen_op_set_cc_op(s->cc_op);
                 gen_jmp_im(pc_start - s->cs_base);
-                gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
+                tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+                tcg_gen_helper_0_3(helper_ljmp_protected,
+                                   cpu_tmp2,
+                                   cpu_T[1],
+                                   tcg_const_i32(s->pc - pc_start));
             } else {
                 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
                 gen_op_movl_T0_T1();
@@ -4355,11 +4357,11 @@
             gen_op_mov_TN_reg(ot, 0, reg);
             /* for xchg, lock is implicit */
             if (!(prefixes & PREFIX_LOCK))
-                gen_op_lock();
+                tcg_gen_helper_0_0(helper_lock);
             gen_op_ld_T1_A0(ot + s->mem_index);
             gen_op_st_T0_A0(ot + s->mem_index);
             if (!(prefixes & PREFIX_LOCK))
-                gen_op_unlock();
+                tcg_gen_helper_0_0(helper_unlock);
             gen_op_mov_reg_T1(ot, reg);
         }
         break;
@@ -5117,13 +5119,10 @@
             ot = OT_BYTE;
         else
             ot = dflag ? OT_LONG : OT_WORD;
-        gen_check_io(s, ot, 1, pc_start - s->cs_base);
         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
         gen_op_andl_T0_ffff();
-        if (gen_svm_check_io(s, pc_start,
-                             SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
-                             svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
-            break;
+        gen_check_io(s, ot, pc_start - s->cs_base, 
+                     SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -5136,13 +5135,10 @@
             ot = OT_BYTE;
         else
             ot = dflag ? OT_LONG : OT_WORD;
-        gen_check_io(s, ot, 1, pc_start - s->cs_base);
         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
         gen_op_andl_T0_ffff();
-        if (gen_svm_check_io(s, pc_start,
-                             (1 << (4+ot)) | svm_is_rep(prefixes) |
-                             4 | (1 << (7+s->aflag))))
-            break;
+        gen_check_io(s, ot, pc_start - s->cs_base,
+                     svm_is_rep(prefixes) | 4);
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -5161,12 +5157,10 @@
             ot = dflag ? OT_LONG : OT_WORD;
         val = ldub_code(s->pc++);
         gen_op_movl_T0_im(val);
-        gen_check_io(s, ot, 0, pc_start - s->cs_base);
-        if (gen_svm_check_io(s, pc_start,
-                             SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
-                             (1 << (4+ot))))
-            break;
-        gen_op_in[ot]();
+        gen_check_io(s, ot, pc_start - s->cs_base,
+                     SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+        tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2);
         gen_op_mov_reg_T1(ot, R_EAX);
         break;
     case 0xe6:
@@ -5177,12 +5171,14 @@
             ot = dflag ? OT_LONG : OT_WORD;
         val = ldub_code(s->pc++);
         gen_op_movl_T0_im(val);
-        gen_check_io(s, ot, 0, pc_start - s->cs_base);
-        if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
-                             (1 << (4+ot))))
-            break;
+        gen_check_io(s, ot, pc_start - s->cs_base,
+                     svm_is_rep(prefixes));
         gen_op_mov_TN_reg(ot, 1, R_EAX);
-        gen_op_out[ot]();
+
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+        tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff);
+        tcg_gen_trunc_tl_i32(cpu_tmp3, cpu_T[1]);
+        tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2, cpu_tmp3);
         break;
     case 0xec:
     case 0xed:
@@ -5192,12 +5188,10 @@
             ot = dflag ? OT_LONG : OT_WORD;
         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
         gen_op_andl_T0_ffff();
-        gen_check_io(s, ot, 0, pc_start - s->cs_base);
-        if (gen_svm_check_io(s, pc_start,
-                             SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
-                             (1 << (4+ot))))
-            break;
-        gen_op_in[ot]();
+        gen_check_io(s, ot, pc_start - s->cs_base,
+                     SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+        tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2);
         gen_op_mov_reg_T1(ot, R_EAX);
         break;
     case 0xee:
@@ -5208,12 +5202,14 @@
             ot = dflag ? OT_LONG : OT_WORD;
         gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
         gen_op_andl_T0_ffff();
-        gen_check_io(s, ot, 0, pc_start - s->cs_base);
-        if (gen_svm_check_io(s, pc_start,
-                             svm_is_rep(prefixes) | (1 << (4+ot))))
-            break;
+        gen_check_io(s, ot, pc_start - s->cs_base,
+                     svm_is_rep(prefixes));
         gen_op_mov_TN_reg(ot, 1, R_EAX);
-        gen_op_out[ot]();
+
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
+        tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff);
+        tcg_gen_trunc_tl_i32(cpu_tmp3, cpu_T[1]);
+        tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2, cpu_tmp3);
         break;
 
         /************************/
@@ -5246,7 +5242,9 @@
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_op_lret_protected(s->dflag, val);
+            tcg_gen_helper_0_2(helper_lret_protected,
+                               tcg_const_i32(s->dflag), 
+                               tcg_const_i32(val));
         } else {
             gen_stack_A0(s);
             /* pop offset */
@@ -5273,20 +5271,22 @@
             break;
         if (!s->pe) {
             /* real mode */
-            gen_op_iret_real(s->dflag);
+            tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag));
             s->cc_op = CC_OP_EFLAGS;
         } else if (s->vm86) {
             if (s->iopl != 3) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
-                gen_op_iret_real(s->dflag);
+                tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag));
                 s->cc_op = CC_OP_EFLAGS;
             }
         } else {
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
+            tcg_gen_helper_0_2(helper_iret_protected,
+                               tcg_const_i32(s->dflag), 
+                               tcg_const_i32(s->pc - s->cs_base));
             s->cc_op = CC_OP_EFLAGS;
         }
         gen_eob(s);
@@ -5723,10 +5723,11 @@
         gen_op_mov_TN_reg(ot, 0, reg);
         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
         gen_jmp_im(pc_start - s->cs_base);
+        tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]);
         if (ot == OT_WORD)
-            tcg_gen_helper_0_0(helper_boundw);
+            tcg_gen_helper_0_2(helper_boundw, cpu_A0, cpu_tmp2);
         else
-            tcg_gen_helper_0_0(helper_boundl);
+            tcg_gen_helper_0_2(helper_boundl, cpu_A0, cpu_tmp2);
         break;
     case 0x1c8 ... 0x1cf: /* bswap reg */
         reg = (b & 7) | REX_B(s);
@@ -6134,7 +6135,7 @@
                 if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
                     break;
                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
-                gen_op_lmsw_T0();
+                tcg_gen_helper_0_1(helper_lmsw, cpu_T[0]);
                 gen_jmp_im(s->pc - s->cs_base);
                 gen_eob(s);
             }
@@ -6223,6 +6224,7 @@
             } else {
                 gen_op_mov_TN_reg(ot, 0, rm);
             }
+            gen_op_mov_TN_reg(ot, 1, reg);
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_op_arpl();
@@ -6299,14 +6301,15 @@
                 if (b & 2) {
                     gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + 
reg);
                     gen_op_mov_TN_reg(ot, 0, rm);
-                    gen_op_movl_crN_T0(reg);
+                    tcg_gen_helper_0_2(helper_movl_crN_T0, 
+                                       tcg_const_i32(reg), cpu_T[0]);
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
                 } else {
                     gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + 
reg);
 #if !defined(CONFIG_USER_ONLY)
                     if (reg == 8)
-                        gen_op_movtl_T0_cr8();
+                        tcg_gen_helper_1_0(helper_movtl_T0_cr8, cpu_T[0]);
                     else
 #endif
                         gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
@@ -6338,7 +6341,8 @@
             if (b & 2) {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
                 gen_op_mov_TN_reg(ot, 0, rm);
-                gen_op_movl_drN_T0(reg);
+                tcg_gen_helper_0_2(helper_movl_drN_T0,
+                                   tcg_const_i32(reg), cpu_T[0]);
                 gen_jmp_im(s->pc - s->cs_base);
                 gen_eob(s);
             } else {
@@ -6353,7 +6357,7 @@
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
-            gen_op_clts();
+            tcg_gen_helper_0_0(helper_clts);
             /* abort block because static cpu state changed */
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
@@ -6485,11 +6489,11 @@
     }
     /* lock generation */
     if (s->prefix & PREFIX_LOCK)
-        gen_op_unlock();
+        tcg_gen_helper_0_0(helper_unlock);
     return s->pc;
  illegal_op:
     if (s->prefix & PREFIX_LOCK)
-        gen_op_unlock();
+        tcg_gen_helper_0_0(helper_unlock);
     /* XXX: ensure that no lock was generated */
     gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
     return s->pc;
@@ -6861,7 +6865,8 @@
     cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
     cpu_A0 = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "A0");
 #endif
-#if defined(__i386__)
+#if defined(__i386__) && (TARGET_LONG_BITS <= HOST_LONG_BITS)
+    /* XXX: must be suppressed once there are less fixed registers */
     cpu_tmp1 = tcg_global_reg2_new_hack(TCG_TYPE_I64, TCG_AREG1, TCG_AREG2, 
"tmp1");
 #endif
 }
@@ -6957,10 +6962,11 @@
 #endif
 
     cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL);
-#if !defined(__i386__)
+#if !(defined(__i386__) && (TARGET_LONG_BITS <= HOST_LONG_BITS))
     cpu_tmp1 = tcg_temp_new(TCG_TYPE_I64);
 #endif
     cpu_tmp2 = tcg_temp_new(TCG_TYPE_I32);
+    cpu_tmp3 = tcg_temp_new(TCG_TYPE_I32);
     cpu_ptr0 = tcg_temp_new(TCG_TYPE_PTR);
     cpu_ptr1 = tcg_temp_new(TCG_TYPE_PTR);
 






reply via email to

[Prev in Thread] Current Thread [Next in Thread]