convert eflags manipulation insns to TCG
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4515 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									3bd7da9e18
								
							
						
					
					
						commit
						bd7a7b33df
					
				| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										135
									
								
								target-i386/op.c
								
								
								
								
							
							
						
						
									
										135
									
								
								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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue