- 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
- 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.
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);
#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);
-
-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);
+static inline void svm_check_intercept(uint32_t type)
+{
+ helper_svm_check_intercept_param(type, 0);
+}
#if !defined(CONFIG_USER_ONLY)
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];
* 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"
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);
}
}
}
-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)
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);
}
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;
}
}
-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;
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;
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;
stq(esp, ldq(ebp));
}
esp -= 8;
- stq(esp, T1);
+ stq(esp, t1);
} else {
/* 16 bit */
esp -= 2;
stw(esp, lduw(ebp));
}
esp -= 2;
- stw(esp, T1);
+ stw(esp, t1);
}
}
#endif
}
/* 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)
}
/* 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;
}
/* 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) {
#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)
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)
}
#endif
-void helper_lsl(uint32_t selector)
+uint32_t helper_lsl(uint32_t selector)
{
unsigned int limit;
uint32_t e1, e2, eflags;
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;
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)
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)
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);
}
#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
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);
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) {
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);
/* 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();
env->error_code = 0;
env->old_exception = -1;
- regs_to_env();
cpu_loop_exit();
}
#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);
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
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);
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);
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);
#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
void OPPROTO op_cmpxchg8b(void)
{
- helper_cmpxchg8b();
+ helper_cmpxchg8b(A0);
}
/* multiple size ops */
/* 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)
{
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)
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);
*(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)
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)
{
#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();
}
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);
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
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;
/* 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)
/* 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;
},
};
-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 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)
+static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
+ uint32_t svm_flags)
{
+ int state_saved;
+ target_ulong next_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));
}
}
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
{
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) {
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
}
}
-#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);
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 */
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;
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;
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);
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) );
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) );
} 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 */
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);
/* lock generation */
if (prefixes & PREFIX_LOCK)
- gen_op_lock();
+ tcg_gen_helper_0_0(helper_lock);
/* now check op code */
reswitch:
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;
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();
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;
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 {
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 {
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:
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:
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:
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;
/************************/
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 */
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);
gen_op_mov_TN_reg(ot, 0, reg);
gen_lea_modrm(s, modrm, ®_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);
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);
}
} 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();
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]));
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 {
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);
}
/* 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;
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
}
#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);