summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-07-07 11:30:47 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-07-07 11:30:47 +0000
commit3c1cf9fa865927759a78d476a218a7759fb38fb4 (patch)
tree3685bb1a07b7db30483ecd3282adbb321866324a
parent1f47a9223ebe3d0c9c779f72341afc10c206d574 (diff)
downloadqemu-3c1cf9fa865927759a78d476a218a7759fb38fb4.tar.gz
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
-rw-r--r--cpu-i386.h14
-rw-r--r--exec-i386.h2
-rw-r--r--exec.h15
-rw-r--r--helper-i386.c39
-rw-r--r--op-i386.c10
-rw-r--r--translate-i386.c29
-rw-r--r--translate.c13
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, &reg_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, &reg_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)