aboutsummaryrefslogtreecommitdiff
path: root/translate-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'translate-i386.c')
-rw-r--r--translate-i386.c68
1 files changed, 64 insertions, 4 deletions
diff --git a/translate-i386.c b/translate-i386.c
index 55e8a8dde6..4d8cbf391a 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -1919,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
break;
case 0x1a0: /* push fs */
case 0x1a8: /* push gs */
- gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
+ gen_op_movl_T0_seg((b >> 3) & 7);
gen_push_T0(s);
break;
case 0x07: /* pop es */
@@ -1932,7 +1932,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
case 0x1a1: /* pop fs */
case 0x1a9: /* pop gs */
gen_pop_T0(s);
- gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
+ gen_movl_seg_T0(s, (b >> 3) & 7);
gen_pop_update(s);
break;
@@ -2833,6 +2833,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
s->is_jmp = 1;
break;
case 0xca: /* lret im */
+ /* XXX: not restartable */
val = ldsw(s->pc);
s->pc += 2;
/* pop offset */
@@ -2853,6 +2854,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
s->is_jmp = 1;
break;
case 0xcb: /* lret */
+ /* XXX: not restartable */
/* pop offset */
gen_pop_T0(s);
if (s->dflag == 0)
@@ -2865,6 +2867,35 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
gen_pop_update(s);
s->is_jmp = 1;
break;
+ case 0xcf: /* iret */
+ /* XXX: not restartable */
+ /* pop offset */
+ gen_pop_T0(s);
+ if (s->dflag == 0)
+ gen_op_andl_T0_ffff();
+ gen_op_jmp_T0();
+ gen_pop_update(s);
+ /* pop selector */
+ gen_pop_T0(s);
+ gen_movl_seg_T0(s, R_CS);
+ gen_pop_update(s);
+ /* pop eflags */
+ gen_pop_T0(s);
+ if (s->dflag) {
+ if (s->vm86)
+ gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
+ else
+ gen_op_movl_eflags_T0();
+ } else {
+ if (s->vm86)
+ gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
+ else
+ gen_op_movw_eflags_T0();
+ }
+ gen_pop_update(s);
+ s->cc_op = CC_OP_EFLAGS;
+ s->is_jmp = 1;
+ break;
case 0xe8: /* call im */
{
unsigned int next_eip;
@@ -2978,12 +3009,25 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
case 0x9c: /* pushf */
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
- gen_op_movl_T0_eflags();
+ if (s->vm86)
+ gen_op_movl_T0_eflags_vm();
+ else
+ gen_op_movl_T0_eflags();
gen_push_T0(s);
break;
case 0x9d: /* popf */
gen_pop_T0(s);
- gen_op_movl_eflags_T0();
+ if (s->dflag) {
+ if (s->vm86)
+ gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
+ else
+ gen_op_movl_eflags_T0();
+ } else {
+ if (s->vm86)
+ gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
+ else
+ gen_op_movw_eflags_T0();
+ }
gen_pop_update(s);
s->cc_op = CC_OP_EFLAGS;
break;
@@ -3159,6 +3203,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_set_cc_op(s->cc_op);
gen_op_into();
break;
+ case 0xfa: /* cli */
+ if (s->vm86)
+ gen_op_cli_vm();
+ else
+ gen_op_cli();
+ break;
+ case 0xfb: /* sti */
+ if (s->vm86)
+ gen_op_sti_vm(pc_start - s->cs_base);
+ else
+ gen_op_sti();
+ break;
case 0x62: /* bound */
ot = dflag ? OT_LONG : OT_WORD;
modrm = ldub(s->pc++);
@@ -3308,6 +3364,7 @@ static uint16_t opc_read_flags[NB_OPS] = {
[INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
[INDEX_op_movl_T0_eflags] = CC_OSZAPC,
+ [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC,
[INDEX_op_cmc] = CC_C,
[INDEX_op_salc] = CC_C,
@@ -3356,7 +3413,10 @@ static uint16_t opc_write_flags[NB_OPS] = {
[INDEX_op_daa] = CC_OSZAPC,
[INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
+ [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
+ [INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC,
[INDEX_op_movl_eflags_T0] = CC_OSZAPC,
+ [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC,
[INDEX_op_clc] = CC_C,
[INDEX_op_stc] = CC_C,
[INDEX_op_cmc] = CC_C,