aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 15:21:33 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 15:21:33 +0000
commit3415a4ddb4dc88a206b25cc4daec4b506bfa5096 (patch)
treef82c08692532c8796cf1823b5f27516656670875
parentb7f0f463a55e4f4bded580905582f2dfa6652fca (diff)
invd and wbinvd support - fixed code gen logic for invlpg - simpler exception handling in load_seg()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@487 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--target-i386/op.c2
-rw-r--r--target-i386/translate.c21
2 files changed, 19 insertions, 4 deletions
diff --git a/target-i386/op.c b/target-i386/op.c
index 5423be5a3a..63e34cf01f 100644
--- a/target-i386/op.c
+++ b/target-i386/op.c
@@ -907,7 +907,7 @@ void OPPROTO op_das(void)
/* never use it with R_CS */
void OPPROTO op_movl_seg_T0(void)
{
- load_seg(PARAM1, T0 & 0xffff, PARAM2);
+ load_seg(PARAM1, T0);
}
/* faster VM86 version */
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 35067bff62..87b6711bc9 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -1538,10 +1538,15 @@ static void gen_setcc(DisasContext *s, int b)
call this function with seg_reg == R_CS */
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
{
- if (s->pe && !s->vm86)
- gen_op_movl_seg_T0(seg_reg, cur_eip);
- else
+ if (s->pe && !s->vm86) {
+ /* XXX: optimize by finding processor state dynamically */
+ if (s->cc_op != CC_OP_DYNAMIC)
+ gen_op_set_cc_op(s->cc_op);
+ gen_op_jmp_im(cur_eip);
+ gen_op_movl_seg_T0(seg_reg);
+ } else {
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
+ }
/* abort translation because the register may have a non zero base
or because ss32 may change. For R_SS, translation must always
stop as a special handling must be done to disable hardware
@@ -3982,12 +3987,22 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
goto illegal_op;
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_op_invlpg_A0();
+ gen_op_jmp_im(s->pc - s->cs_base);
+ gen_eob(s);
}
break;
default:
goto illegal_op;
}
break;
+ case 0x108: /* invd */
+ case 0x109: /* wbinvd */
+ if (s->cpl != 0) {
+ gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+ } else {
+ /* nothing to do */
+ }
+ break;
case 0x63: /* arpl */
if (!s->pe || s->vm86)
goto illegal_op;