monitor/mwait support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2044 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
4f2092904d
commit
3d7374c5da
@ -496,6 +496,9 @@ void save_native_fp_state(CPUState *env);
|
||||
float approx_rsqrt(float a);
|
||||
float approx_rcp(float a);
|
||||
void update_fp_status(void);
|
||||
void helper_hlt(void);
|
||||
void helper_monitor(void);
|
||||
void helper_mwait(void);
|
||||
|
||||
extern const uint8_t parity_table[256];
|
||||
extern const uint8_t rclw_table[32];
|
||||
|
@ -3408,6 +3408,34 @@ void helper_bswapq_T0(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
void helper_hlt(void)
|
||||
{
|
||||
env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
|
||||
env->hflags |= HF_HALTED_MASK;
|
||||
env->exception_index = EXCP_HLT;
|
||||
cpu_loop_exit();
|
||||
}
|
||||
|
||||
void helper_monitor(void)
|
||||
{
|
||||
if (ECX != 0)
|
||||
raise_exception(EXCP0D_GPF);
|
||||
/* XXX: store address ? */
|
||||
}
|
||||
|
||||
void helper_mwait(void)
|
||||
{
|
||||
if (ECX != 0)
|
||||
raise_exception(EXCP0D_GPF);
|
||||
/* XXX: not complete but not completely erroneous */
|
||||
if (env->cpu_index != 0 || env->next_cpu != NULL) {
|
||||
/* more than one CPU: do not sleep because another CPU may
|
||||
wake this one */
|
||||
} else {
|
||||
helper_hlt();
|
||||
}
|
||||
}
|
||||
|
||||
float approx_rsqrt(float a)
|
||||
{
|
||||
return 1.0 / sqrt(a);
|
||||
|
@ -614,10 +614,17 @@ void OPPROTO op_movq_eip_im64(void)
|
||||
|
||||
void OPPROTO op_hlt(void)
|
||||
{
|
||||
env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
|
||||
env->hflags |= HF_HALTED_MASK;
|
||||
env->exception_index = EXCP_HLT;
|
||||
cpu_loop_exit();
|
||||
helper_hlt();
|
||||
}
|
||||
|
||||
void OPPROTO op_monitor(void)
|
||||
{
|
||||
helper_monitor();
|
||||
}
|
||||
|
||||
void OPPROTO op_mwait(void)
|
||||
{
|
||||
helper_mwait();
|
||||
}
|
||||
|
||||
void OPPROTO op_debug(void)
|
||||
|
@ -100,6 +100,7 @@ typedef struct DisasContext {
|
||||
int popl_esp_hack; /* for correct popl with esp base handling */
|
||||
int rip_offset; /* only used in x86_64, but left for simplicity */
|
||||
int cpuid_features;
|
||||
int cpuid_ext_features;
|
||||
} DisasContext;
|
||||
|
||||
static void gen_eob(DisasContext *s);
|
||||
@ -5567,26 +5568,69 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
|
||||
modrm = ldub_code(s->pc++);
|
||||
mod = (modrm >> 6) & 3;
|
||||
op = (modrm >> 3) & 7;
|
||||
rm = modrm & 7;
|
||||
switch(op) {
|
||||
case 0: /* sgdt */
|
||||
case 1: /* sidt */
|
||||
if (mod == 3)
|
||||
goto illegal_op;
|
||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||
if (op == 0)
|
||||
gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
|
||||
else
|
||||
gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
|
||||
gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
|
||||
gen_op_st_T0_A0[OT_WORD + s->mem_index]();
|
||||
gen_add_A0_im(s, 2);
|
||||
if (op == 0)
|
||||
gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base));
|
||||
else
|
||||
gen_op_movtl_T0_env(offsetof(CPUX86State,idt.base));
|
||||
gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base));
|
||||
if (!s->dflag)
|
||||
gen_op_andl_T0_im(0xffffff);
|
||||
gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
|
||||
break;
|
||||
case 1:
|
||||
if (mod == 3) {
|
||||
switch (rm) {
|
||||
case 0: /* monitor */
|
||||
if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
|
||||
s->cpl != 0)
|
||||
goto illegal_op;
|
||||
gen_jmp_im(pc_start - s->cs_base);
|
||||
#ifdef TARGET_X86_64
|
||||
if (s->aflag == 2) {
|
||||
gen_op_movq_A0_reg[R_EBX]();
|
||||
gen_op_addq_A0_AL();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
gen_op_movl_A0_reg[R_EBX]();
|
||||
gen_op_addl_A0_AL();
|
||||
if (s->aflag == 0)
|
||||
gen_op_andl_A0_ffff();
|
||||
}
|
||||
gen_add_A0_ds_seg(s);
|
||||
gen_op_monitor();
|
||||
break;
|
||||
case 1: /* mwait */
|
||||
if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
|
||||
s->cpl != 0)
|
||||
goto illegal_op;
|
||||
if (s->cc_op != CC_OP_DYNAMIC) {
|
||||
gen_op_set_cc_op(s->cc_op);
|
||||
s->cc_op = CC_OP_DYNAMIC;
|
||||
}
|
||||
gen_jmp_im(s->pc - s->cs_base);
|
||||
gen_op_mwait();
|
||||
gen_eob(s);
|
||||
break;
|
||||
default:
|
||||
goto illegal_op;
|
||||
}
|
||||
} else { /* sidt */
|
||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||
gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
|
||||
gen_op_st_T0_A0[OT_WORD + s->mem_index]();
|
||||
gen_add_A0_im(s, 2);
|
||||
gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base));
|
||||
if (!s->dflag)
|
||||
gen_op_andl_T0_im(0xffffff);
|
||||
gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
|
||||
}
|
||||
break;
|
||||
case 2: /* lgdt */
|
||||
case 3: /* lidt */
|
||||
if (mod == 3)
|
||||
@ -5629,7 +5673,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
|
||||
} else {
|
||||
if (mod == 3) {
|
||||
#ifdef TARGET_X86_64
|
||||
if (CODE64(s) && (modrm & 7) == 0) {
|
||||
if (CODE64(s) && rm == 0) {
|
||||
/* swapgs */
|
||||
gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
|
||||
gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
|
||||
@ -6348,6 +6392,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
|
||||
dc->mem_index = 1 * 4;
|
||||
}
|
||||
dc->cpuid_features = env->cpuid_features;
|
||||
dc->cpuid_ext_features = env->cpuid_ext_features;
|
||||
#ifdef TARGET_X86_64
|
||||
dc->lma = (flags >> HF_LMA_SHIFT) & 1;
|
||||
dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
|
||||
|
Loading…
Reference in New Issue
Block a user