From 3c1cf9fa865927759a78d476a218a7759fb38fb4 Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 7 Jul 2003 11:30:47 +0000 Subject: [PATCH] dummy rdmsr and wrmsr support - xor reg, reg optimization git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@311 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-i386.h | 14 ++++++++++++++ exec-i386.h | 2 ++ exec.h | 15 +++++++++++++++ helper-i386.c | 39 +++++++++++++++++++++++++++++++++++++++ op-i386.c | 10 ++++++++++ translate-i386.c | 29 +++++++++++++++++++++++++---- translate.c | 13 ++++++++++++- 7 files changed, 117 insertions(+), 5 deletions(-) diff --git a/cpu-i386.h b/cpu-i386.h index 4029746c80..e6318fb7f2 100644 --- a/cpu-i386.h +++ b/cpu-i386.h @@ -125,6 +125,15 @@ #define PG_ERROR_U_MASK 0x04 #define PG_ERROR_RSVD_MASK 0x08 +#define MSR_IA32_APICBASE 0x1b +#define MSR_IA32_APICBASE_BSP (1<<8) +#define MSR_IA32_APICBASE_ENABLE (1<<11) +#define MSR_IA32_APICBASE_BASE (0xfffff<<12) + +#define MSR_IA32_SYSENTER_CS 0x174 +#define MSR_IA32_SYSENTER_ESP 0x175 +#define MSR_IA32_SYSENTER_EIP 0x176 + #define EXCP00_DIVZ 0 #define EXCP01_SSTP 1 #define EXCP02_NMI 2 @@ -244,6 +253,11 @@ typedef struct CPUX86State { SegmentCache tr; SegmentCache gdt; /* only base and limit are used */ SegmentCache idt; /* only base and limit are used */ + + /* sysenter registers */ + uint32_t sysenter_cs; + uint32_t sysenter_esp; + uint32_t sysenter_eip; /* exception/interrupt handling */ jmp_buf jmp_env; diff --git a/exec-i386.h b/exec-i386.h index 12e22bb412..84a1dabf09 100644 --- a/exec-i386.h +++ b/exec-i386.h @@ -159,6 +159,8 @@ void helper_idivl_EAX_T0(uint32_t eip); void helper_cmpxchg8b(void); void helper_cpuid(void); void helper_rdtsc(void); +void helper_rdmsr(void); +void helper_wrmsr(void); void helper_lsl(void); void helper_lar(void); diff --git a/exec.h b/exec.h index 92b248db03..1f46e4a469 100644 --- a/exec.h +++ b/exec.h @@ -324,6 +324,7 @@ typedef int spinlock_t; #define SPIN_LOCK_UNLOCKED 0 +#if 1 static inline void spin_lock(spinlock_t *lock) { while (testandset(lock)); @@ -338,6 +339,20 @@ static inline int spin_trylock(spinlock_t *lock) { return !testandset(lock); } +#else +static inline void spin_lock(spinlock_t *lock) +{ +} + +static inline void spin_unlock(spinlock_t *lock) +{ +} + +static inline int spin_trylock(spinlock_t *lock) +{ + return 1; +} +#endif extern spinlock_t tb_lock; diff --git a/helper-i386.c b/helper-i386.c index fef7c351e6..72b75a5c21 100644 --- a/helper-i386.c +++ b/helper-i386.c @@ -947,6 +947,45 @@ void helper_rdtsc(void) EDX = val >> 32; } +void helper_wrmsr(void) +{ + switch(ECX) { + case MSR_IA32_SYSENTER_CS: + env->sysenter_cs = EAX & 0xffff; + break; + case MSR_IA32_SYSENTER_ESP: + env->sysenter_esp = EAX; + break; + case MSR_IA32_SYSENTER_EIP: + env->sysenter_eip = EAX; + break; + default: + /* XXX: exception ? */ + break; + } +} + +void helper_rdmsr(void) +{ + switch(ECX) { + case MSR_IA32_SYSENTER_CS: + EAX = env->sysenter_cs; + EDX = 0; + break; + case MSR_IA32_SYSENTER_ESP: + EAX = env->sysenter_esp; + EDX = 0; + break; + case MSR_IA32_SYSENTER_EIP: + EAX = env->sysenter_eip; + EDX = 0; + break; + default: + /* XXX: exception ? */ + break; + } +} + void helper_lsl(void) { unsigned int selector, limit; diff --git a/op-i386.c b/op-i386.c index ee951b1da9..84b75d07b0 100644 --- a/op-i386.c +++ b/op-i386.c @@ -751,6 +751,16 @@ void OPPROTO op_cpuid(void) helper_cpuid(); } +void OPPROTO op_rdmsr(void) +{ + helper_rdmsr(); +} + +void OPPROTO op_wrmsr(void) +{ + helper_wrmsr(); +} + /* bcd */ /* XXX: exception */ diff --git a/translate-i386.c b/translate-i386.c index c8bd12f3d9..fdbd5ee922 100644 --- a/translate-i386.c +++ b/translate-i386.c @@ -1575,14 +1575,22 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) switch(f) { case 0: /* OP Ev, Gv */ modrm = ldub(s->pc++); - reg = ((modrm >> 3) & 7) + OR_EAX; + reg = ((modrm >> 3) & 7); mod = (modrm >> 6) & 3; rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); opreg = OR_TMP0; + } else if (op == OP_XORL && rm == reg) { + xor_zero: + /* xor reg, reg optimisation */ + gen_op_movl_T0_0(); + s->cc_op = CC_OP_LOGICB + ot; + gen_op_mov_reg_T0[ot][reg](); + gen_op_update1_cc(); + break; } else { - opreg = OR_EAX + rm; + opreg = rm; } gen_op_mov_TN_reg[ot][1][reg](); gen_op(s, op, ot, opreg); @@ -1590,11 +1598,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) case 1: /* OP Gv, Ev */ modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; - reg = ((modrm >> 3) & 7) + OR_EAX; + reg = ((modrm >> 3) & 7); rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_ld_T1_A0[ot](); + } else if (op == OP_XORL && rm == reg) { + goto xor_zero; } else { gen_op_mov_TN_reg[ot][1][rm](); } @@ -3464,6 +3474,17 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_loop[s->aflag][b & 3](val, next_eip); s->is_jmp = 1; break; + case 0x130: /* wrmsr */ + case 0x132: /* rdmsr */ + if (s->cpl != 0) { + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); + } else { + if (b & 2) + gen_op_rdmsr(); + else + gen_op_wrmsr(); + } + break; case 0x131: /* rdtsc */ gen_op_rdtsc(); break; @@ -4267,7 +4288,7 @@ void cpu_x86_update_cr0(CPUX86State *env) void cpu_x86_update_cr3(CPUX86State *env) { if (env->cr[0] & CR0_PG_MASK) { -#ifdef DEBUG_MMU +#if defined(DEBUG_MMU) printf("CR3 update: CR3=%08x\n", env->cr[3]); #endif page_unmap(); diff --git a/translate.c b/translate.c index 2f11dfc030..72b4d24b79 100644 --- a/translate.c +++ b/translate.c @@ -179,7 +179,18 @@ int cpu_restore_state(TranslationBlock *tb, #if defined(TARGET_I386) { int cc_op; - +#ifdef DEBUG_DISAS + if (loglevel) { + int i; + for(i=0;i<=j; i++) { + if (gen_opc_instr_start[i]) { + fprintf(logfile, "0x%04x: 0x%08x", i, gen_opc_pc[i]); + } + } + fprintf(logfile, "j=0x%x eip=0x%lx cs_base=%lx\n", + j, gen_opc_pc[j] - tb->cs_base, tb->cs_base); + } +#endif env->eip = gen_opc_pc[j] - tb->cs_base; cc_op = gen_opc_cc_op[j]; if (cc_op != CC_OP_DYNAMIC)