diff options
-rw-r--r-- | target-i386/TODO | 1 | ||||
-rw-r--r-- | target-i386/helper.c | 14 | ||||
-rw-r--r-- | target-i386/helper.h | 2 | ||||
-rw-r--r-- | target-i386/op.c | 135 | ||||
-rw-r--r-- | target-i386/translate.c | 42 |
5 files changed, 46 insertions, 148 deletions
diff --git a/target-i386/TODO b/target-i386/TODO index 15a3b36602..1a1bf562b6 100644 --- a/target-i386/TODO +++ b/target-i386/TODO @@ -1,5 +1,6 @@ Correctness issues: +- some eflags manipulation incorrectly reset the bit 0x2. - rework eflags optimization (will be a consequence of TCG port) - SVM: rework the implementation: simplify code, move most intercept tests as dynamic, correct segment access, verify exception safety, diff --git a/target-i386/helper.c b/target-i386/helper.c index 731d7a328c..d04622ff1c 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -108,6 +108,20 @@ void helper_unlock(void) spin_unlock(&global_cpu_lock); } +void helper_write_eflags(target_ulong t0, uint32_t update_mask) +{ + load_eflags(t0, update_mask); +} + +target_ulong helper_read_eflags(void) +{ + uint32_t eflags; + eflags = cc_table[CC_OP].compute_all(); + eflags |= (DF & DF_MASK); + eflags |= env->eflags & ~(VM_MASK | RF_MASK); + return eflags; +} + /* return non zero if error */ static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, int selector) diff --git a/target-i386/helper.h b/target-i386/helper.h index e0ff417b23..9df198a0e4 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -2,6 +2,8 @@ void helper_lock(void); void helper_unlock(void); +void helper_write_eflags(target_ulong t0, uint32_t update_mask); +target_ulong helper_read_eflags(void); void helper_divb_AL(target_ulong t0); void helper_idivb_AL(target_ulong t0); void helper_divw_AX(target_ulong t0); diff --git a/target-i386/op.c b/target-i386/op.c index 0a0532c6bf..bb7a488768 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -255,138 +255,3 @@ void OPPROTO op_xor_T0_1(void) { T0 ^= 1; } - -/* XXX: clear VIF/VIP in all ops ? */ - -void OPPROTO op_movl_eflags_T0(void) -{ - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK)); -} - -void OPPROTO op_movw_eflags_T0(void) -{ - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff); -} - -void OPPROTO op_movl_eflags_T0_io(void) -{ - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)); -} - -void OPPROTO op_movw_eflags_T0_io(void) -{ - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff); -} - -void OPPROTO op_movl_eflags_T0_cpl0(void) -{ - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)); -} - -void OPPROTO op_movw_eflags_T0_cpl0(void) -{ - load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff); -} - -#if 0 -/* vm86plus version */ -void OPPROTO op_movw_eflags_T0_vm(void) -{ - int eflags; - eflags = T0; - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); - DF = 1 - (2 * ((eflags >> 10) & 1)); - /* we also update some system flags as in user mode */ - env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) | - (eflags & FL_UPDATE_MASK16); - if (eflags & IF_MASK) { - env->eflags |= VIF_MASK; - if (env->eflags & VIP_MASK) { - EIP = PARAM1; - raise_exception(EXCP0D_GPF); - } - } - FORCE_RET(); -} - -void OPPROTO op_movl_eflags_T0_vm(void) -{ - int eflags; - eflags = T0; - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); - DF = 1 - (2 * ((eflags >> 10) & 1)); - /* we also update some system flags as in user mode */ - env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) | - (eflags & FL_UPDATE_MASK32); - if (eflags & IF_MASK) { - env->eflags |= VIF_MASK; - if (env->eflags & VIP_MASK) { - EIP = PARAM1; - raise_exception(EXCP0D_GPF); - } - } - FORCE_RET(); -} -#endif - -/* XXX: compute only O flag */ -void OPPROTO op_movb_eflags_T0(void) -{ - int of; - of = cc_table[CC_OP].compute_all() & CC_O; - CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of; -} - -void OPPROTO op_movl_T0_eflags(void) -{ - int eflags; - eflags = cc_table[CC_OP].compute_all(); - eflags |= (DF & DF_MASK); - eflags |= env->eflags & ~(VM_MASK | RF_MASK); - T0 = eflags; -} - -/* vm86plus version */ -#if 0 -void OPPROTO op_movl_T0_eflags_vm(void) -{ - int eflags; - eflags = cc_table[CC_OP].compute_all(); - eflags |= (DF & DF_MASK); - eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); - if (env->eflags & VIF_MASK) - eflags |= IF_MASK; - T0 = eflags; -} -#endif - -void OPPROTO op_clc(void) -{ - int eflags; - eflags = cc_table[CC_OP].compute_all(); - eflags &= ~CC_C; - CC_SRC = eflags; -} - -void OPPROTO op_stc(void) -{ - int eflags; - eflags = cc_table[CC_OP].compute_all(); - eflags |= CC_C; - CC_SRC = eflags; -} - -void OPPROTO op_cmc(void) -{ - int eflags; - eflags = cc_table[CC_OP].compute_all(); - eflags ^= CC_C; - CC_SRC = eflags; -} - -void OPPROTO op_salc(void) -{ - int cf; - cf = cc_table[CC_OP].compute_c(); - EAX = (EAX & ~0xff) | ((-cf) & 0xff); -} diff --git a/target-i386/translate.c b/target-i386/translate.c index 6ad32de883..da66d1eaa8 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -5733,7 +5733,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_movl_T0_eflags(); + tcg_gen_helper_1_0(helper_read_eflags, cpu_T[0]); gen_push_T0(s); } break; @@ -5746,22 +5746,28 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_pop_T0(s); if (s->cpl == 0) { if (s->dflag) { - gen_op_movl_eflags_T0_cpl0(); + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK))); } else { - gen_op_movw_eflags_T0_cpl0(); + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff)); } } else { if (s->cpl <= s->iopl) { if (s->dflag) { - gen_op_movl_eflags_T0_io(); + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK))); } else { - gen_op_movw_eflags_T0_io(); + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff)); } } else { if (s->dflag) { - gen_op_movl_eflags_T0(); + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK))); } else { - gen_op_movw_eflags_T0(); + tcg_gen_helper_0_2(helper_write_eflags, cpu_T[0], + tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff)); } } } @@ -5778,7 +5784,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_movb_eflags_T0(); + gen_compute_eflags(cpu_cc_src); + tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C); + tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]); s->cc_op = CC_OP_EFLAGS; break; case 0x9f: /* lahf */ @@ -5786,25 +5795,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_movl_T0_eflags(); + gen_compute_eflags(cpu_T[0]); + /* Note: gen_compute_eflags() only gives the condition codes */ + tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 0x02); gen_op_mov_reg_T0(OT_BYTE, R_AH); break; case 0xf5: /* cmc */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_cmc(); + gen_compute_eflags(cpu_cc_src); + tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C); s->cc_op = CC_OP_EFLAGS; break; case 0xf8: /* clc */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_clc(); + gen_compute_eflags(cpu_cc_src); + tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C); s->cc_op = CC_OP_EFLAGS; break; case 0xf9: /* stc */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_stc(); + gen_compute_eflags(cpu_cc_src); + tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); s->cc_op = CC_OP_EFLAGS; break; case 0xfc: /* cld */ @@ -6127,7 +6141,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_salc(); + gen_compute_eflags_c(cpu_T[0]); + tcg_gen_neg_tl(cpu_T[0], cpu_T[0]); + gen_op_mov_reg_T0(OT_BYTE, R_EAX); break; case 0xe0: /* loopnz */ case 0xe1: /* loopz */ |