提交 f115e911 编写于 作者: B bellard

iret and int fix for vm86 - added undefined instructions for real and vm86...

iret and int fix for vm86 - added undefined instructions for real and vm86 modes - added verr, verrw, arpl - added port io map


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@454 c046a42c-6fe2-441c-8c8c-71466251a162
上级 3ab493de
...@@ -749,6 +749,43 @@ static GenOpFunc *gen_op_out_DX_T0[3] = { ...@@ -749,6 +749,43 @@ static GenOpFunc *gen_op_out_DX_T0[3] = {
gen_op_outl_DX_T0, gen_op_outl_DX_T0,
}; };
static GenOpFunc *gen_op_in[3] = {
gen_op_inb_T0_T1,
gen_op_inw_T0_T1,
gen_op_inl_T0_T1,
};
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, int cur_eip)
{
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_op_jmp_im(cur_eip);
if (use_dx)
gen_check_io_DX[ot]();
else
gen_check_io_T0[ot]();
}
}
static inline void gen_movs(DisasContext *s, int ot) static inline void gen_movs(DisasContext *s, int ot)
{ {
gen_string_movl_A0_ESI(s); gen_string_movl_A0_ESI(s);
...@@ -912,18 +949,6 @@ GEN_REPZ(outs) ...@@ -912,18 +949,6 @@ GEN_REPZ(outs)
GEN_REPZ2(scas) GEN_REPZ2(scas)
GEN_REPZ2(cmps) GEN_REPZ2(cmps)
static GenOpFunc *gen_op_in[3] = {
gen_op_inb_T0_T1,
gen_op_inw_T0_T1,
gen_op_inl_T0_T1,
};
static GenOpFunc *gen_op_out[3] = {
gen_op_outb_T0_T1,
gen_op_outw_T0_T1,
gen_op_outl_T0_T1,
};
enum { enum {
JCC_O, JCC_O,
JCC_B, JCC_B,
...@@ -3221,36 +3246,28 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3221,36 +3246,28 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
break; break;
case 0x6c: /* insS */ case 0x6c: /* insS */
case 0x6d: case 0x6d:
if (s->pe && (s->cpl > s->iopl || s->vm86)) { if ((b & 1) == 0)
/* NOTE: even for (E)CX = 0 the exception is raised */ ot = OT_BYTE;
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); else
ot = dflag ? OT_LONG : OT_WORD;
gen_check_io(s, ot, 1, pc_start - s->cs_base);
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
} else { } else {
if ((b & 1) == 0) gen_ins(s, ot);
ot = OT_BYTE;
else
ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
} else {
gen_ins(s, ot);
}
} }
break; break;
case 0x6e: /* outsS */ case 0x6e: /* outsS */
case 0x6f: case 0x6f:
if (s->pe && (s->cpl > s->iopl || s->vm86)) { if ((b & 1) == 0)
/* NOTE: even for (E)CX = 0 the exception is raised */ ot = OT_BYTE;
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); else
ot = dflag ? OT_LONG : OT_WORD;
gen_check_io(s, ot, 1, pc_start - s->cs_base);
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
} else { } else {
if ((b & 1) == 0) gen_outs(s, ot);
ot = OT_BYTE;
else
ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
} else {
gen_outs(s, ot);
}
} }
break; break;
...@@ -3258,61 +3275,49 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3258,61 +3275,49 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
/* port I/O */ /* port I/O */
case 0xe4: case 0xe4:
case 0xe5: case 0xe5:
if (s->pe && (s->cpl > s->iopl || s->vm86)) { if ((b & 1) == 0)
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); ot = OT_BYTE;
} else { else
if ((b & 1) == 0) ot = dflag ? OT_LONG : OT_WORD;
ot = OT_BYTE; val = ldub_code(s->pc++);
else gen_op_movl_T0_im(val);
ot = dflag ? OT_LONG : OT_WORD; gen_check_io(s, ot, 0, pc_start - s->cs_base);
val = ldub_code(s->pc++); gen_op_in[ot]();
gen_op_movl_T0_im(val); gen_op_mov_reg_T1[ot][R_EAX]();
gen_op_in[ot]();
gen_op_mov_reg_T1[ot][R_EAX]();
}
break; break;
case 0xe6: case 0xe6:
case 0xe7: case 0xe7:
if (s->pe && (s->cpl > s->iopl || s->vm86)) { if ((b & 1) == 0)
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); ot = OT_BYTE;
} else { else
if ((b & 1) == 0) ot = dflag ? OT_LONG : OT_WORD;
ot = OT_BYTE; val = ldub_code(s->pc++);
else gen_op_movl_T0_im(val);
ot = dflag ? OT_LONG : OT_WORD; gen_check_io(s, ot, 0, pc_start - s->cs_base);
val = ldub_code(s->pc++); gen_op_mov_TN_reg[ot][1][R_EAX]();
gen_op_movl_T0_im(val); gen_op_out[ot]();
gen_op_mov_TN_reg[ot][1][R_EAX]();
gen_op_out[ot]();
}
break; break;
case 0xec: case 0xec:
case 0xed: case 0xed:
if (s->pe && (s->cpl > s->iopl || s->vm86)) { if ((b & 1) == 0)
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); ot = OT_BYTE;
} else { else
if ((b & 1) == 0) ot = dflag ? OT_LONG : OT_WORD;
ot = OT_BYTE; gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
else gen_check_io(s, ot, 0, pc_start - s->cs_base);
ot = dflag ? OT_LONG : OT_WORD; gen_op_in[ot]();
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); gen_op_mov_reg_T1[ot][R_EAX]();
gen_op_in[ot]();
gen_op_mov_reg_T1[ot][R_EAX]();
}
break; break;
case 0xee: case 0xee:
case 0xef: case 0xef:
if (s->pe && (s->cpl > s->iopl || s->vm86)) { if ((b & 1) == 0)
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); ot = OT_BYTE;
} else { else
if ((b & 1) == 0) ot = dflag ? OT_LONG : OT_WORD;
ot = OT_BYTE; gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
else gen_check_io(s, ot, 0, pc_start - s->cs_base);
ot = dflag ? OT_LONG : OT_WORD; gen_op_mov_TN_reg[ot][1][R_EAX]();
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); gen_op_out[ot]();
gen_op_mov_TN_reg[ot][1][R_EAX]();
gen_op_out[ot]();
}
break; break;
/************************/ /************************/
...@@ -3370,8 +3375,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3370,8 +3375,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
/* real mode */ /* real mode */
gen_op_iret_real(s->dflag); gen_op_iret_real(s->dflag);
s->cc_op = CC_OP_EFLAGS; s->cc_op = CC_OP_EFLAGS;
} else if (s->vm86 && s->iopl != 3) { } else if (s->vm86) {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); if (s->iopl != 3) {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else {
gen_op_iret_real(s->dflag);
s->cc_op = CC_OP_EFLAGS;
}
} else { } else {
if (s->cc_op != CC_OP_DYNAMIC) if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op); gen_op_set_cc_op(s->cc_op);
...@@ -3675,11 +3685,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3675,11 +3685,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
break; break;
case 0xcd: /* int N */ case 0xcd: /* int N */
val = ldub_code(s->pc++); val = ldub_code(s->pc++);
/* XXX: add error code for vm86 GPF */ if (s->vm86 && s->iopl != 3) {
if (!s->vm86)
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
else
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else {
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
}
break; break;
case 0xce: /* into */ case 0xce: /* into */
if (s->cc_op != CC_OP_DYNAMIC) if (s->cc_op != CC_OP_DYNAMIC)
...@@ -3799,6 +3809,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3799,6 +3809,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
op = (modrm >> 3) & 7; op = (modrm >> 3) & 7;
switch(op) { switch(op) {
case 0: /* sldt */ case 0: /* sldt */
if (!s->pe || s->vm86)
goto illegal_op;
gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector)); gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
ot = OT_WORD; ot = OT_WORD;
if (mod == 3) if (mod == 3)
...@@ -3806,6 +3818,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3806,6 +3818,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
break; break;
case 2: /* lldt */ case 2: /* lldt */
if (!s->pe || s->vm86)
goto illegal_op;
if (s->cpl != 0) { if (s->cpl != 0) {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else { } else {
...@@ -3815,6 +3829,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3815,6 +3829,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
} }
break; break;
case 1: /* str */ case 1: /* str */
if (!s->pe || s->vm86)
goto illegal_op;
gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector)); gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
ot = OT_WORD; ot = OT_WORD;
if (mod == 3) if (mod == 3)
...@@ -3822,6 +3838,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3822,6 +3838,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
break; break;
case 3: /* ltr */ case 3: /* ltr */
if (!s->pe || s->vm86)
goto illegal_op;
if (s->cpl != 0) { if (s->cpl != 0) {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else { } else {
...@@ -3832,6 +3850,17 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3832,6 +3850,17 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
break; break;
case 4: /* verr */ case 4: /* verr */
case 5: /* verw */ case 5: /* verw */
if (!s->pe || s->vm86)
goto illegal_op;
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
if (op == 4)
gen_op_verr();
else
gen_op_verw();
s->cc_op = CC_OP_EFLAGS;
break;
default: default:
goto illegal_op; goto illegal_op;
} }
...@@ -3908,6 +3937,31 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -3908,6 +3937,31 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
goto illegal_op; goto illegal_op;
} }
break; break;
case 0x63: /* arpl */
if (!s->pe || s->vm86)
goto illegal_op;
ot = dflag ? OT_LONG : OT_WORD;
modrm = ldub_code(s->pc++);
reg = (modrm >> 3) & 7;
mod = (modrm >> 6) & 3;
rm = modrm & 7;
if (mod != 3) {
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_op_ld_T0_A0[ot + s->mem_index]();
} else {
gen_op_mov_TN_reg[ot][0][rm]();
}
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
gen_op_arpl();
s->cc_op = CC_OP_EFLAGS;
if (mod != 3) {
gen_op_st_T0_A0[ot + s->mem_index]();
} else {
gen_op_mov_reg_T0[ot][rm]();
}
gen_op_arpl_update();
break;
case 0x102: /* lar */ case 0x102: /* lar */
case 0x103: /* lsl */ case 0x103: /* lsl */
if (!s->pe || s->vm86) if (!s->pe || s->vm86)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册