finished simplifying string operations - correct TF flag handling for string operations and ss loading - simplified basic block exit code generation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@381 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									4cbb86e1c4
								
							
						
					
					
						commit
						dbc5594cb6
					
				
							
								
								
									
										425
									
								
								translate-i386.c
									
									
									
									
									
								
							
							
						
						
									
										425
									
								
								translate-i386.c
									
									
									
									
									
								
							@ -60,11 +60,15 @@ typedef struct DisasContext {
 | 
				
			|||||||
    int cpl;
 | 
					    int cpl;
 | 
				
			||||||
    int iopl;
 | 
					    int iopl;
 | 
				
			||||||
    int tf;     /* TF cpu flag */
 | 
					    int tf;     /* TF cpu flag */
 | 
				
			||||||
 | 
					    int jmp_opt; /* use direct block chaining for direct jumps */
 | 
				
			||||||
    int mem_index; /* select memory access functions */
 | 
					    int mem_index; /* select memory access functions */
 | 
				
			||||||
    struct TranslationBlock *tb;
 | 
					    struct TranslationBlock *tb;
 | 
				
			||||||
    int popl_esp_hack; /* for correct popl with esp base handling */
 | 
					    int popl_esp_hack; /* for correct popl with esp base handling */
 | 
				
			||||||
} DisasContext;
 | 
					} DisasContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_eob(DisasContext *s);
 | 
				
			||||||
 | 
					static void gen_jmp(DisasContext *s, unsigned int eip);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* i386 arith/logic operations */
 | 
					/* i386 arith/logic operations */
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    OP_ADDL, 
 | 
					    OP_ADDL, 
 | 
				
			||||||
@ -635,31 +639,6 @@ static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
 | 
				
			|||||||
    gen_op_stl_user_T0_A0,
 | 
					    gen_op_stl_user_T0_A0,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* the _a32 and _a16 string operations use A0 as the base register. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define STRINGOP_NB 9
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define STRINGOP(x) \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## b_fast, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## w_fast, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## l_fast, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## b_a32, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## w_a32, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## l_a32, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## b_a16, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## w_a16, \
 | 
					 | 
				
			||||||
    gen_op_ ## x ## l_a16,
 | 
					 | 
				
			||||||
     
 | 
					 | 
				
			||||||
static GenOpFunc *gen_op_scas[STRINGOP_NB * 3] = {
 | 
					 | 
				
			||||||
    STRINGOP(repz_scas)
 | 
					 | 
				
			||||||
    STRINGOP(repnz_scas)
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static GenOpFunc *gen_op_cmps[STRINGOP_NB * 3] = {
 | 
					 | 
				
			||||||
    STRINGOP(repz_cmps)
 | 
					 | 
				
			||||||
    STRINGOP(repnz_cmps)
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void gen_string_movl_A0_ESI(DisasContext *s)
 | 
					static inline void gen_string_movl_A0_ESI(DisasContext *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int override;
 | 
					    int override;
 | 
				
			||||||
@ -712,12 +691,17 @@ static GenOpFunc2 *gen_op_jz_ecx[2] = {
 | 
				
			|||||||
    gen_op_jz_ecxl,
 | 
					    gen_op_jz_ecxl,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					static GenOpFunc1 *gen_op_jz_ecx_im[2] = {
 | 
				
			||||||
 | 
					    gen_op_jz_ecxw_im,
 | 
				
			||||||
 | 
					    gen_op_jz_ecxl_im,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GenOpFunc *gen_op_dec_ECX[2] = {
 | 
					static GenOpFunc *gen_op_dec_ECX[2] = {
 | 
				
			||||||
    gen_op_decw_ECX,
 | 
					    gen_op_decw_ECX,
 | 
				
			||||||
    gen_op_decl_ECX,
 | 
					    gen_op_decl_ECX,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GenOpFunc2 *gen_op_string_jnz_sub[2][3] = {
 | 
					static GenOpFunc1 *gen_op_string_jnz_sub[2][3] = {
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        gen_op_string_jnz_subb,
 | 
					        gen_op_string_jnz_subb,
 | 
				
			||||||
        gen_op_string_jnz_subw,
 | 
					        gen_op_string_jnz_subw,
 | 
				
			||||||
@ -730,6 +714,19 @@ static GenOpFunc2 *gen_op_string_jnz_sub[2][3] = {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static GenOpFunc1 *gen_op_string_jnz_sub_im[2][3] = {
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        gen_op_string_jnz_subb_im,
 | 
				
			||||||
 | 
					        gen_op_string_jnz_subw_im,
 | 
				
			||||||
 | 
					        gen_op_string_jnz_subl_im,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        gen_op_string_jz_subb_im,
 | 
				
			||||||
 | 
					        gen_op_string_jz_subw_im,
 | 
				
			||||||
 | 
					        gen_op_string_jz_subl_im,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GenOpFunc *gen_op_in_DX_T0[3] = {
 | 
					static GenOpFunc *gen_op_in_DX_T0[3] = {
 | 
				
			||||||
    gen_op_inb_DX_T0,
 | 
					    gen_op_inb_DX_T0,
 | 
				
			||||||
    gen_op_inw_DX_T0,
 | 
					    gen_op_inw_DX_T0,
 | 
				
			||||||
@ -758,18 +755,23 @@ static inline void gen_movs(DisasContext *s, int ot)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* same method as Valgrind : we generate jumps to current or next
 | 
					static inline void gen_update_cc_op(DisasContext *s)
 | 
				
			||||||
   instruction */
 | 
					 | 
				
			||||||
static inline void gen_repz_movs(DisasContext *s, int ot, 
 | 
					 | 
				
			||||||
                                 unsigned int cur_eip, unsigned int next_eip)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    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);
 | 
				
			||||||
 | 
					        s->cc_op = CC_OP_DYNAMIC;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void gen_jz_ecx_string(DisasContext *s, unsigned int next_eip)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (s->jmp_opt) {
 | 
				
			||||||
        gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
 | 
					        gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
 | 
				
			||||||
    gen_movs(s, ot);
 | 
					    } else {
 | 
				
			||||||
    gen_op_dec_ECX[s->aflag]();
 | 
					        /* XXX: does not work with gdbstub "ice" single step - not a
 | 
				
			||||||
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
 | 
					           serious problem */
 | 
				
			||||||
    s->is_jmp = 3;
 | 
					        gen_op_jz_ecx_im[s->aflag](next_eip);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_stos(DisasContext *s, int ot)
 | 
					static inline void gen_stos(DisasContext *s, int ot)
 | 
				
			||||||
@ -785,18 +787,6 @@ static inline void gen_stos(DisasContext *s, int ot)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_repz_stos(DisasContext *s, int ot, 
 | 
					 | 
				
			||||||
                                 unsigned int cur_eip, unsigned int next_eip)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (s->cc_op != CC_OP_DYNAMIC)
 | 
					 | 
				
			||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
 | 
					 | 
				
			||||||
    gen_stos(s, ot);
 | 
					 | 
				
			||||||
    gen_op_dec_ECX[s->aflag]();
 | 
					 | 
				
			||||||
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
 | 
					 | 
				
			||||||
    s->is_jmp = 3;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void gen_lods(DisasContext *s, int ot)
 | 
					static inline void gen_lods(DisasContext *s, int ot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gen_string_movl_A0_ESI(s);
 | 
					    gen_string_movl_A0_ESI(s);
 | 
				
			||||||
@ -810,18 +800,6 @@ static inline void gen_lods(DisasContext *s, int ot)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_repz_lods(DisasContext *s, int ot, 
 | 
					 | 
				
			||||||
                                 unsigned int cur_eip, unsigned int next_eip)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (s->cc_op != CC_OP_DYNAMIC)
 | 
					 | 
				
			||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
 | 
					 | 
				
			||||||
    gen_lods(s, ot);
 | 
					 | 
				
			||||||
    gen_op_dec_ECX[s->aflag]();
 | 
					 | 
				
			||||||
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
 | 
					 | 
				
			||||||
    s->is_jmp = 3;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void gen_scas(DisasContext *s, int ot)
 | 
					static inline void gen_scas(DisasContext *s, int ot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
 | 
					    gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
 | 
				
			||||||
@ -836,23 +814,6 @@ static inline void gen_scas(DisasContext *s, int ot)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
static inline void gen_repz_scas(DisasContext *s, int ot, 
 | 
					 | 
				
			||||||
                                 unsigned int cur_eip, unsigned int next_eip,
 | 
					 | 
				
			||||||
                                 int nz)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (s->cc_op != CC_OP_DYNAMIC)
 | 
					 | 
				
			||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
 | 
					 | 
				
			||||||
    gen_scas(s, ot);
 | 
					 | 
				
			||||||
    gen_op_set_cc_op(CC_OP_SUBB + ot);
 | 
					 | 
				
			||||||
    gen_op_string_jnz_sub[nz][ot]((long)s->tb, next_eip);
 | 
					 | 
				
			||||||
    gen_op_dec_ECX[s->aflag]();
 | 
					 | 
				
			||||||
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
 | 
					 | 
				
			||||||
    s->is_jmp = 3;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void gen_cmps(DisasContext *s, int ot)
 | 
					static inline void gen_cmps(DisasContext *s, int ot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gen_string_movl_A0_ESI(s);
 | 
					    gen_string_movl_A0_ESI(s);
 | 
				
			||||||
@ -883,18 +844,6 @@ static inline void gen_ins(DisasContext *s, int ot)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_repz_ins(DisasContext *s, int ot, 
 | 
					 | 
				
			||||||
                                 unsigned int cur_eip, unsigned int next_eip)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (s->cc_op != CC_OP_DYNAMIC)
 | 
					 | 
				
			||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
 | 
					 | 
				
			||||||
    gen_ins(s, ot);
 | 
					 | 
				
			||||||
    gen_op_dec_ECX[s->aflag]();
 | 
					 | 
				
			||||||
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
 | 
					 | 
				
			||||||
    s->is_jmp = 3;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void gen_outs(DisasContext *s, int ot)
 | 
					static inline void gen_outs(DisasContext *s, int ot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gen_string_movl_A0_ESI(s);
 | 
					    gen_string_movl_A0_ESI(s);
 | 
				
			||||||
@ -908,59 +857,50 @@ static inline void gen_outs(DisasContext *s, int ot)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_repz_outs(DisasContext *s, int ot, 
 | 
					/* same method as Valgrind : we generate jumps to current or next
 | 
				
			||||||
                                 unsigned int cur_eip, unsigned int next_eip)
 | 
					   instruction */
 | 
				
			||||||
{
 | 
					#define GEN_REPZ(op)                                                          \
 | 
				
			||||||
    if (s->cc_op != CC_OP_DYNAMIC)
 | 
					static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
 | 
				
			||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					                                 unsigned int cur_eip, unsigned int next_eip) \
 | 
				
			||||||
    gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
 | 
					{                                                                             \
 | 
				
			||||||
    gen_outs(s, ot);
 | 
					    gen_update_cc_op(s);                                                      \
 | 
				
			||||||
    gen_op_dec_ECX[s->aflag]();
 | 
					    gen_jz_ecx_string(s, next_eip);                                           \
 | 
				
			||||||
    gen_op_jmp_tb_next((long)s->tb, cur_eip);
 | 
					    gen_ ## op(s, ot);                                                        \
 | 
				
			||||||
    s->is_jmp = 3;
 | 
					    gen_op_dec_ECX[s->aflag]();                                               \
 | 
				
			||||||
 | 
					    /* a loop would cause two single step exceptions if ECX = 1               \
 | 
				
			||||||
 | 
					       before rep string_insn */                                              \
 | 
				
			||||||
 | 
					    if (!s->jmp_opt)                                                          \
 | 
				
			||||||
 | 
					        gen_op_jz_ecx_im[s->aflag](next_eip);                                 \
 | 
				
			||||||
 | 
					    gen_jmp(s, cur_eip);                                                      \
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
 | 
					#define GEN_REPZ2(op)                                                         \
 | 
				
			||||||
{
 | 
					static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
 | 
				
			||||||
    int index, override;
 | 
					                                   unsigned int cur_eip,                      \
 | 
				
			||||||
 | 
					                                   unsigned int next_eip,                     \
 | 
				
			||||||
    override = s->override;
 | 
					                                   int nz)                                    \
 | 
				
			||||||
    if (s->aflag) {
 | 
					{                                                                             \
 | 
				
			||||||
        /* 32 bit address */
 | 
					    gen_update_cc_op(s);                                                      \
 | 
				
			||||||
        if (s->addseg && override < 0)
 | 
					    gen_jz_ecx_string(s, next_eip);                                           \
 | 
				
			||||||
            override = R_DS;
 | 
					    gen_ ## op(s, ot);                                                        \
 | 
				
			||||||
        if (override >= 0) {
 | 
					    gen_op_dec_ECX[s->aflag]();                                               \
 | 
				
			||||||
            gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
 | 
					    gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
 | 
				
			||||||
            index = 3 + ot;
 | 
					    if (!s->jmp_opt)                                                          \
 | 
				
			||||||
        } else {
 | 
					        gen_op_string_jnz_sub_im[nz][ot](next_eip);                           \
 | 
				
			||||||
            index = ot;
 | 
					    else                                                                      \
 | 
				
			||||||
        }
 | 
					        gen_op_string_jnz_sub[nz][ot]((long)s->tb);                           \
 | 
				
			||||||
    } else {
 | 
					    if (!s->jmp_opt)                                                          \
 | 
				
			||||||
        if (override < 0)
 | 
					        gen_op_jz_ecx_im[s->aflag](next_eip);                                 \
 | 
				
			||||||
            override = R_DS;
 | 
					    gen_jmp(s, cur_eip);                                                      \
 | 
				
			||||||
        gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
 | 
					 | 
				
			||||||
        /* 16 address, always override */
 | 
					 | 
				
			||||||
        index = 6 + ot;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    func[index]();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int index;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
    if (s->aflag) {
 | 
					 | 
				
			||||||
        if (s->addseg) {
 | 
					 | 
				
			||||||
            index = 3 + ot;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            index = ot;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        index = 6 + ot;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    func[index]();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GEN_REPZ(movs)
 | 
				
			||||||
 | 
					GEN_REPZ(stos)
 | 
				
			||||||
 | 
					GEN_REPZ(lods)
 | 
				
			||||||
 | 
					GEN_REPZ(ins)
 | 
				
			||||||
 | 
					GEN_REPZ(outs)
 | 
				
			||||||
 | 
					GEN_REPZ2(scas)
 | 
				
			||||||
 | 
					GEN_REPZ2(cmps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GenOpFunc *gen_op_in[3] = {
 | 
					static GenOpFunc *gen_op_in[3] = {
 | 
				
			||||||
    gen_op_inb_T0_T1,
 | 
					    gen_op_inb_T0_T1,
 | 
				
			||||||
@ -1420,6 +1360,8 @@ static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    inv = b & 1;
 | 
					    inv = b & 1;
 | 
				
			||||||
    jcc_op = (b >> 1) & 7;
 | 
					    jcc_op = (b >> 1) & 7;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (s->jmp_opt) {
 | 
				
			||||||
        switch(s->cc_op) {
 | 
					        switch(s->cc_op) {
 | 
				
			||||||
            /* we optimize the cmp/jcc case */
 | 
					            /* we optimize the cmp/jcc case */
 | 
				
			||||||
        case CC_OP_SUBB:
 | 
					        case CC_OP_SUBB:
 | 
				
			||||||
@ -1485,6 +1427,19 @@ static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
 | 
				
			|||||||
            func((long)tb, next_eip, val);
 | 
					            func((long)tb, next_eip, val);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        s->is_jmp = 3;
 | 
					        s->is_jmp = 3;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (s->cc_op != CC_OP_DYNAMIC) {
 | 
				
			||||||
 | 
					            gen_op_set_cc_op(s->cc_op);
 | 
				
			||||||
 | 
					            s->cc_op = CC_OP_DYNAMIC;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        gen_setcc_slow[jcc_op]();
 | 
				
			||||||
 | 
					        if (!inv) {
 | 
				
			||||||
 | 
					            gen_op_jcc_im(val, next_eip);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            gen_op_jcc_im(next_eip, val);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        gen_eob(s);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_setcc(DisasContext *s, int b)
 | 
					static void gen_setcc(DisasContext *s, int b)
 | 
				
			||||||
@ -1557,7 +1512,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
 | 
				
			|||||||
       stop as a special handling must be done to disable hardware
 | 
					       stop as a special handling must be done to disable hardware
 | 
				
			||||||
       interrupts for the next instruction */
 | 
					       interrupts for the next instruction */
 | 
				
			||||||
    if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
 | 
					    if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
 | 
				
			||||||
        s->is_jmp = 2; 
 | 
					        s->is_jmp = 3;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* generate a push. It depends on ss32, addseg and dflag */
 | 
					/* generate a push. It depends on ss32, addseg and dflag */
 | 
				
			||||||
@ -1727,7 +1682,7 @@ static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
 | 
				
			|||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					        gen_op_set_cc_op(s->cc_op);
 | 
				
			||||||
    gen_op_jmp_im(cur_eip);
 | 
					    gen_op_jmp_im(cur_eip);
 | 
				
			||||||
    gen_op_raise_exception(trapno);
 | 
					    gen_op_raise_exception(trapno);
 | 
				
			||||||
    s->is_jmp = 1;
 | 
					    s->is_jmp = 3;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* an interrupt is different from an exception because of the
 | 
					/* an interrupt is different from an exception because of the
 | 
				
			||||||
@ -1739,7 +1694,7 @@ static void gen_interrupt(DisasContext *s, int intno,
 | 
				
			|||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					        gen_op_set_cc_op(s->cc_op);
 | 
				
			||||||
    gen_op_jmp_im(cur_eip);
 | 
					    gen_op_jmp_im(cur_eip);
 | 
				
			||||||
    gen_op_raise_interrupt(intno, next_eip);
 | 
					    gen_op_raise_interrupt(intno, next_eip);
 | 
				
			||||||
    s->is_jmp = 1;
 | 
					    s->is_jmp = 3;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_debug(DisasContext *s, unsigned int cur_eip)
 | 
					static void gen_debug(DisasContext *s, unsigned int cur_eip)
 | 
				
			||||||
@ -1748,7 +1703,22 @@ static void gen_debug(DisasContext *s, unsigned int cur_eip)
 | 
				
			|||||||
        gen_op_set_cc_op(s->cc_op);
 | 
					        gen_op_set_cc_op(s->cc_op);
 | 
				
			||||||
    gen_op_jmp_im(cur_eip);
 | 
					    gen_op_jmp_im(cur_eip);
 | 
				
			||||||
    gen_op_debug();
 | 
					    gen_op_debug();
 | 
				
			||||||
    s->is_jmp = 1;
 | 
					    s->is_jmp = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* generate a generic end of block. Trace exception is also generated
 | 
				
			||||||
 | 
					   if needed */
 | 
				
			||||||
 | 
					static void gen_eob(DisasContext *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (s->cc_op != CC_OP_DYNAMIC)
 | 
				
			||||||
 | 
					        gen_op_set_cc_op(s->cc_op);
 | 
				
			||||||
 | 
					    if (s->tf) {
 | 
				
			||||||
 | 
					        gen_op_raise_exception(EXCP01_SSTP);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        gen_op_movl_T0_0();
 | 
				
			||||||
 | 
					        gen_op_exit_tb();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    s->is_jmp = 3;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* generate a jump to eip. No segment change must happen before as a
 | 
					/* generate a jump to eip. No segment change must happen before as a
 | 
				
			||||||
@ -1757,16 +1727,20 @@ static void gen_jmp(DisasContext *s, unsigned int eip)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    TranslationBlock *tb = s->tb;
 | 
					    TranslationBlock *tb = s->tb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->jmp_opt) {
 | 
				
			||||||
        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);
 | 
				
			||||||
    gen_op_jmp_tb_next((long)tb, eip);
 | 
					        gen_op_jmp((long)tb, eip);
 | 
				
			||||||
        s->is_jmp = 3;
 | 
					        s->is_jmp = 3;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        gen_op_jmp_im(eip);
 | 
				
			||||||
 | 
					        gen_eob(s);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
 | 
					/* convert one instruction. s->is_jmp is set if the translation must
 | 
				
			||||||
   is set to true if the instruction sets the PC (last instruction of
 | 
					   be stopped. Return the next pc value */
 | 
				
			||||||
   a basic block) */
 | 
					static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			||||||
long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int b, prefixes, aflag, dflag;
 | 
					    int b, prefixes, aflag, dflag;
 | 
				
			||||||
    int shift, ot;
 | 
					    int shift, ot;
 | 
				
			||||||
@ -2106,9 +2080,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
            next_eip = s->pc - s->cs_base;
 | 
					            next_eip = s->pc - s->cs_base;
 | 
				
			||||||
            gen_op_movl_T0_im(next_eip);
 | 
					            gen_op_movl_T0_im(next_eip);
 | 
				
			||||||
            gen_push_T0(s);
 | 
					            gen_push_T0(s);
 | 
				
			||||||
            s->is_jmp = 1;
 | 
					            gen_eob(s);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 3: /* lcall Ev */
 | 
					        case 3: /*< lcall Ev */
 | 
				
			||||||
            gen_op_ld_T1_A0[ot + s->mem_index]();
 | 
					            gen_op_ld_T1_A0[ot + s->mem_index]();
 | 
				
			||||||
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
 | 
					            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
 | 
				
			||||||
            gen_op_ld_T0_A0[OT_WORD + s->mem_index]();
 | 
					            gen_op_ld_T0_A0[OT_WORD + s->mem_index]();
 | 
				
			||||||
@ -2121,13 +2095,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
 | 
					                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            s->is_jmp = 1;
 | 
					            gen_eob(s);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 4: /* jmp Ev */
 | 
					        case 4: /* jmp Ev */
 | 
				
			||||||
            if (s->dflag == 0)
 | 
					            if (s->dflag == 0)
 | 
				
			||||||
                gen_op_andl_T0_ffff();
 | 
					                gen_op_andl_T0_ffff();
 | 
				
			||||||
            gen_op_jmp_T0();
 | 
					            gen_op_jmp_T0();
 | 
				
			||||||
            s->is_jmp = 1;
 | 
					            gen_eob(s);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 5: /* ljmp Ev */
 | 
					        case 5: /* ljmp Ev */
 | 
				
			||||||
            gen_op_ld_T1_A0[ot + s->mem_index]();
 | 
					            gen_op_ld_T1_A0[ot + s->mem_index]();
 | 
				
			||||||
@ -2144,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
                gen_op_movl_T0_T1();
 | 
					                gen_op_movl_T0_T1();
 | 
				
			||||||
                gen_op_jmp_T0();
 | 
					                gen_op_jmp_T0();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            s->is_jmp = 1;
 | 
					            gen_eob(s);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 6: /* push Ev */
 | 
					        case 6: /* push Ev */
 | 
				
			||||||
            gen_push_T0(s);
 | 
					            gen_push_T0(s);
 | 
				
			||||||
@ -2366,6 +2340,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        if (reg == R_SS) {
 | 
					        if (reg == R_SS) {
 | 
				
			||||||
            /* if reg == SS, inhibit interrupts/trace */
 | 
					            /* if reg == SS, inhibit interrupts/trace */
 | 
				
			||||||
            gen_op_set_inhibit_irq();
 | 
					            gen_op_set_inhibit_irq();
 | 
				
			||||||
 | 
					            s->tf = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (s->is_jmp) {
 | 
				
			||||||
 | 
					            gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					            gen_eob(s);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0x1a1: /* pop fs */
 | 
					    case 0x1a1: /* pop fs */
 | 
				
			||||||
@ -2373,6 +2352,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        gen_pop_T0(s);
 | 
					        gen_pop_T0(s);
 | 
				
			||||||
        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
 | 
					        gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
 | 
				
			||||||
        gen_pop_update(s);
 | 
					        gen_pop_update(s);
 | 
				
			||||||
 | 
					        if (s->is_jmp) {
 | 
				
			||||||
 | 
					            gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					            gen_eob(s);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**************************/
 | 
					        /**************************/
 | 
				
			||||||
@ -2428,6 +2411,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        if (reg == R_SS) {
 | 
					        if (reg == R_SS) {
 | 
				
			||||||
            /* if reg == SS, inhibit interrupts/trace */
 | 
					            /* if reg == SS, inhibit interrupts/trace */
 | 
				
			||||||
            gen_op_set_inhibit_irq();
 | 
					            gen_op_set_inhibit_irq();
 | 
				
			||||||
 | 
					            s->tf = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (s->is_jmp) {
 | 
				
			||||||
 | 
					            gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					            gen_eob(s);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0x8c: /* mov Gv, seg */
 | 
					    case 0x8c: /* mov Gv, seg */
 | 
				
			||||||
@ -2635,6 +2623,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
 | 
					        gen_movl_seg_T0(s, op, pc_start - s->cs_base);
 | 
				
			||||||
        /* then put the data */
 | 
					        /* then put the data */
 | 
				
			||||||
        gen_op_mov_reg_T1[ot][reg]();
 | 
					        gen_op_mov_reg_T1[ot][reg]();
 | 
				
			||||||
 | 
					        if (s->is_jmp) {
 | 
				
			||||||
 | 
					            gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					            gen_eob(s);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        /************************/
 | 
					        /************************/
 | 
				
			||||||
@ -3191,15 +3183,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        else
 | 
					        else
 | 
				
			||||||
                ot = dflag ? OT_LONG : OT_WORD;
 | 
					                ot = dflag ? OT_LONG : OT_WORD;
 | 
				
			||||||
        if (prefixes & PREFIX_REPNZ) {
 | 
					        if (prefixes & PREFIX_REPNZ) {
 | 
				
			||||||
            if (s->cc_op != CC_OP_DYNAMIC)
 | 
					            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
 | 
				
			||||||
                gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
            gen_string_es(s, ot, gen_op_scas + STRINGOP_NB);
 | 
					 | 
				
			||||||
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
 | 
					 | 
				
			||||||
        } else if (prefixes & PREFIX_REPZ) {
 | 
					        } else if (prefixes & PREFIX_REPZ) {
 | 
				
			||||||
            if (s->cc_op != CC_OP_DYNAMIC)
 | 
					            gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
 | 
				
			||||||
                gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
            gen_string_es(s, ot, gen_op_scas);
 | 
					 | 
				
			||||||
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            gen_scas(s, ot);
 | 
					            gen_scas(s, ot);
 | 
				
			||||||
            s->cc_op = CC_OP_SUBB + ot;
 | 
					            s->cc_op = CC_OP_SUBB + ot;
 | 
				
			||||||
@ -3213,15 +3199,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        else
 | 
					        else
 | 
				
			||||||
            ot = dflag ? OT_LONG : OT_WORD;
 | 
					            ot = dflag ? OT_LONG : OT_WORD;
 | 
				
			||||||
        if (prefixes & PREFIX_REPNZ) {
 | 
					        if (prefixes & PREFIX_REPNZ) {
 | 
				
			||||||
            if (s->cc_op != CC_OP_DYNAMIC)
 | 
					            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
 | 
				
			||||||
                gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
            gen_string_ds(s, ot, gen_op_cmps + STRINGOP_NB);
 | 
					 | 
				
			||||||
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
 | 
					 | 
				
			||||||
        } else if (prefixes & PREFIX_REPZ) {
 | 
					        } else if (prefixes & PREFIX_REPZ) {
 | 
				
			||||||
            if (s->cc_op != CC_OP_DYNAMIC)
 | 
					            gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
 | 
				
			||||||
                gen_op_set_cc_op(s->cc_op);
 | 
					 | 
				
			||||||
            gen_string_ds(s, ot, gen_op_cmps);
 | 
					 | 
				
			||||||
            s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            gen_cmps(s, ot);
 | 
					            gen_cmps(s, ot);
 | 
				
			||||||
            s->cc_op = CC_OP_SUBB + ot;
 | 
					            s->cc_op = CC_OP_SUBB + ot;
 | 
				
			||||||
@ -3333,7 +3313,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        if (s->dflag == 0)
 | 
					        if (s->dflag == 0)
 | 
				
			||||||
            gen_op_andl_T0_ffff();
 | 
					            gen_op_andl_T0_ffff();
 | 
				
			||||||
        gen_op_jmp_T0();
 | 
					        gen_op_jmp_T0();
 | 
				
			||||||
        s->is_jmp = 1;
 | 
					        gen_eob(s);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0xc3: /* ret */
 | 
					    case 0xc3: /* ret */
 | 
				
			||||||
        gen_pop_T0(s);
 | 
					        gen_pop_T0(s);
 | 
				
			||||||
@ -3341,7 +3321,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        if (s->dflag == 0)
 | 
					        if (s->dflag == 0)
 | 
				
			||||||
            gen_op_andl_T0_ffff();
 | 
					            gen_op_andl_T0_ffff();
 | 
				
			||||||
        gen_op_jmp_T0();
 | 
					        gen_op_jmp_T0();
 | 
				
			||||||
        s->is_jmp = 1;
 | 
					        gen_eob(s);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0xca: /* lret im */
 | 
					    case 0xca: /* lret im */
 | 
				
			||||||
        val = ldsw(s->pc);
 | 
					        val = ldsw(s->pc);
 | 
				
			||||||
@ -3368,7 +3348,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
            /* add stack offset */
 | 
					            /* add stack offset */
 | 
				
			||||||
            gen_stack_update(s, val + (4 << s->dflag));
 | 
					            gen_stack_update(s, val + (4 << s->dflag));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        s->is_jmp = 1;
 | 
					        gen_eob(s);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0xcb: /* lret */
 | 
					    case 0xcb: /* lret */
 | 
				
			||||||
        val = 0;
 | 
					        val = 0;
 | 
				
			||||||
@ -3387,7 +3367,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
            gen_op_iret_protected(s->dflag);
 | 
					            gen_op_iret_protected(s->dflag);
 | 
				
			||||||
            s->cc_op = CC_OP_EFLAGS;
 | 
					            s->cc_op = CC_OP_EFLAGS;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        s->is_jmp = 1;
 | 
					        gen_eob(s);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0xe8: /* call im */
 | 
					    case 0xe8: /* call im */
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -3512,7 +3492,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            gen_pop_update(s);
 | 
					            gen_pop_update(s);
 | 
				
			||||||
            s->cc_op = CC_OP_EFLAGS;
 | 
					            s->cc_op = CC_OP_EFLAGS;
 | 
				
			||||||
            s->is_jmp = 2; /* abort translation because TF flag may change */
 | 
					            /* abort translation because TF flag may change */
 | 
				
			||||||
 | 
					            gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					            gen_eob(s);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0x9e: /* sahf */
 | 
					    case 0x9e: /* sahf */
 | 
				
			||||||
@ -3713,19 +3695,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
    case 0xfb: /* sti */
 | 
					    case 0xfb: /* sti */
 | 
				
			||||||
        if (!s->vm86) {
 | 
					        if (!s->vm86) {
 | 
				
			||||||
            if (s->cpl <= s->iopl) {
 | 
					            if (s->cpl <= s->iopl) {
 | 
				
			||||||
 | 
					            gen_sti:
 | 
				
			||||||
                gen_op_sti();
 | 
					                gen_op_sti();
 | 
				
			||||||
                /* interruptions are enabled only the first insn after sti */
 | 
					                /* interruptions are enabled only the first insn after sti */
 | 
				
			||||||
                gen_op_set_inhibit_irq();
 | 
					                gen_op_set_inhibit_irq();
 | 
				
			||||||
                s->is_jmp = 2; /* give a chance to handle pending irqs */
 | 
					                /* give a chance to handle pending irqs */
 | 
				
			||||||
 | 
					                gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					                gen_eob(s);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
 | 
					                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if (s->iopl == 3) {
 | 
					            if (s->iopl == 3) {
 | 
				
			||||||
                gen_op_sti();
 | 
					                goto gen_sti;
 | 
				
			||||||
                /* interruptions are enabled only the first insn after sti */
 | 
					 | 
				
			||||||
                gen_op_set_inhibit_irq();
 | 
					 | 
				
			||||||
                s->is_jmp = 2; /* give a chance to handle pending irqs */
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
 | 
					                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -3769,7 +3751,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
        if (s->dflag == 0)
 | 
					        if (s->dflag == 0)
 | 
				
			||||||
            val &= 0xffff;
 | 
					            val &= 0xffff;
 | 
				
			||||||
        gen_op_loop[s->aflag][b & 3](val, next_eip);
 | 
					        gen_op_loop[s->aflag][b & 3](val, next_eip);
 | 
				
			||||||
        s->is_jmp = 1;
 | 
					        gen_eob(s);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0x130: /* wrmsr */
 | 
					    case 0x130: /* wrmsr */
 | 
				
			||||||
    case 0x132: /* rdmsr */
 | 
					    case 0x132: /* rdmsr */
 | 
				
			||||||
@ -3796,7 +3778,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
                gen_op_set_cc_op(s->cc_op);
 | 
					                gen_op_set_cc_op(s->cc_op);
 | 
				
			||||||
            gen_op_jmp_im(s->pc - s->cs_base);
 | 
					            gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
            gen_op_hlt();
 | 
					            gen_op_hlt();
 | 
				
			||||||
            s->is_jmp = 1;
 | 
					            s->is_jmp = 3;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 0x100:
 | 
					    case 0x100:
 | 
				
			||||||
@ -3968,7 +3950,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
                if (b & 2) {
 | 
					                if (b & 2) {
 | 
				
			||||||
                    gen_op_mov_TN_reg[OT_LONG][0][rm]();
 | 
					                    gen_op_mov_TN_reg[OT_LONG][0][rm]();
 | 
				
			||||||
                    gen_op_movl_crN_T0(reg);
 | 
					                    gen_op_movl_crN_T0(reg);
 | 
				
			||||||
                    s->is_jmp = 2;
 | 
					                    gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					                    gen_eob(s);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
 | 
					                    gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
 | 
				
			||||||
                    gen_op_mov_reg_T0[OT_LONG][rm]();
 | 
					                    gen_op_mov_reg_T0[OT_LONG][rm]();
 | 
				
			||||||
@ -3995,7 +3978,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
            if (b & 2) {
 | 
					            if (b & 2) {
 | 
				
			||||||
                gen_op_mov_TN_reg[OT_LONG][0][rm]();
 | 
					                gen_op_mov_TN_reg[OT_LONG][0][rm]();
 | 
				
			||||||
                gen_op_movl_drN_T0(reg);
 | 
					                gen_op_movl_drN_T0(reg);
 | 
				
			||||||
                s->is_jmp = 2;
 | 
					                gen_op_jmp_im(s->pc - s->cs_base);
 | 
				
			||||||
 | 
					                gen_eob(s);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
 | 
					                gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
 | 
				
			||||||
                gen_op_mov_reg_T0[OT_LONG][rm]();
 | 
					                gen_op_mov_reg_T0[OT_LONG][rm]();
 | 
				
			||||||
@ -4015,10 +3999,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
 | 
				
			|||||||
    /* lock generation */
 | 
					    /* lock generation */
 | 
				
			||||||
    if (s->prefix & PREFIX_LOCK)
 | 
					    if (s->prefix & PREFIX_LOCK)
 | 
				
			||||||
        gen_op_unlock();
 | 
					        gen_op_unlock();
 | 
				
			||||||
    return (long)s->pc;
 | 
					    return s->pc;
 | 
				
			||||||
 illegal_op:
 | 
					 illegal_op:
 | 
				
			||||||
    /* XXX: ensure that no lock was generated */
 | 
					    /* XXX: ensure that no lock was generated */
 | 
				
			||||||
    return -1;
 | 
					    gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
 | 
				
			||||||
 | 
					    return s->pc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
 | 
					#define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
 | 
				
			||||||
@ -4265,23 +4250,6 @@ static uint16_t opc_write_flags[NB_OPS] = {
 | 
				
			|||||||
    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
 | 
					    [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
 | 
				
			||||||
    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
 | 
					    [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#undef STRINGOP
 | 
					 | 
				
			||||||
#define STRINGOP(x) \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
 | 
					 | 
				
			||||||
    [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    STRINGOP(repz_scas)
 | 
					 | 
				
			||||||
    STRINGOP(repnz_scas)
 | 
					 | 
				
			||||||
    STRINGOP(repz_cmps)
 | 
					 | 
				
			||||||
    STRINGOP(repnz_cmps)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
 | 
					    [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
 | 
				
			||||||
    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
 | 
					    [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
 | 
				
			||||||
    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
 | 
					    [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
 | 
				
			||||||
@ -4383,7 +4351,6 @@ static inline int gen_intermediate_code_internal(CPUState *env,
 | 
				
			|||||||
    uint8_t *pc_ptr;
 | 
					    uint8_t *pc_ptr;
 | 
				
			||||||
    uint16_t *gen_opc_end;
 | 
					    uint16_t *gen_opc_end;
 | 
				
			||||||
    int flags, j, lj;
 | 
					    int flags, j, lj;
 | 
				
			||||||
    long ret;
 | 
					 | 
				
			||||||
    uint8_t *pc_start;
 | 
					    uint8_t *pc_start;
 | 
				
			||||||
    uint8_t *cs_base;
 | 
					    uint8_t *cs_base;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -4413,7 +4380,11 @@ static inline int gen_intermediate_code_internal(CPUState *env,
 | 
				
			|||||||
        else
 | 
					        else
 | 
				
			||||||
            dc->mem_index = 3;
 | 
					            dc->mem_index = 3;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    dc->jmp_opt = !(dc->tf || env->singlestep_enabled
 | 
				
			||||||
 | 
					#ifndef CONFIG_SOFT_MMU
 | 
				
			||||||
 | 
					                    || (flags & HF_SOFTMMU_MASK)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
    gen_opc_ptr = gen_opc_buf;
 | 
					    gen_opc_ptr = gen_opc_buf;
 | 
				
			||||||
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
 | 
					    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
 | 
				
			||||||
    gen_opparam_ptr = gen_opparam_buf;
 | 
					    gen_opparam_ptr = gen_opparam_buf;
 | 
				
			||||||
@ -4428,12 +4399,12 @@ static inline int gen_intermediate_code_internal(CPUState *env,
 | 
				
			|||||||
    if (flags & HF_INHIBIT_IRQ_MASK) {
 | 
					    if (flags & HF_INHIBIT_IRQ_MASK) {
 | 
				
			||||||
        gen_op_reset_inhibit_irq();
 | 
					        gen_op_reset_inhibit_irq();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    do {
 | 
					    for(;;) {
 | 
				
			||||||
        if (env->nb_breakpoints > 0) {
 | 
					        if (env->nb_breakpoints > 0) {
 | 
				
			||||||
            for(j = 0; j < env->nb_breakpoints; j++) {
 | 
					            for(j = 0; j < env->nb_breakpoints; j++) {
 | 
				
			||||||
                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
 | 
					                if (env->breakpoints[j] == (unsigned long)pc_ptr) {
 | 
				
			||||||
                    gen_debug(dc, pc_ptr - dc->cs_base);
 | 
					                    gen_debug(dc, pc_ptr - dc->cs_base);
 | 
				
			||||||
                    goto the_end;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -4448,44 +4419,24 @@ static inline int gen_intermediate_code_internal(CPUState *env,
 | 
				
			|||||||
            gen_opc_cc_op[lj] = dc->cc_op;
 | 
					            gen_opc_cc_op[lj] = dc->cc_op;
 | 
				
			||||||
            gen_opc_instr_start[lj] = 1;
 | 
					            gen_opc_instr_start[lj] = 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ret = disas_insn(dc, pc_ptr);
 | 
					        pc_ptr = disas_insn(dc, pc_ptr);
 | 
				
			||||||
        if (ret == -1) {
 | 
					        /* stop translation if indicated */
 | 
				
			||||||
            /* we trigger an illegal instruction operation only if it
 | 
					        if (dc->is_jmp)
 | 
				
			||||||
               is the first instruction. Otherwise, we simply stop
 | 
					 | 
				
			||||||
               generating the code just before it */
 | 
					 | 
				
			||||||
            if (pc_ptr == pc_start)
 | 
					 | 
				
			||||||
                return -1;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        pc_ptr = (void *)ret;
 | 
					 | 
				
			||||||
        /* if single step mode, we generate only one instruction and
 | 
					        /* if single step mode, we generate only one instruction and
 | 
				
			||||||
           generate an exception */
 | 
					           generate an exception */
 | 
				
			||||||
        if (dc->tf)
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
 | 
					 | 
				
			||||||
             (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
 | 
					 | 
				
			||||||
    if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
 | 
					 | 
				
			||||||
        gen_jmp(dc, ret - (unsigned long)dc->cs_base);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* we must store the eflags state if it is not already done */
 | 
					 | 
				
			||||||
    if (dc->is_jmp != DISAS_TB_JUMP) {
 | 
					 | 
				
			||||||
        if (dc->cc_op != CC_OP_DYNAMIC)
 | 
					 | 
				
			||||||
            gen_op_set_cc_op(dc->cc_op);
 | 
					 | 
				
			||||||
        if (dc->is_jmp != DISAS_JUMP) {
 | 
					 | 
				
			||||||
            /* we add an additionnal jmp to update the simulated PC */
 | 
					 | 
				
			||||||
            gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
        if (dc->tf) {
 | 
					        if (dc->tf) {
 | 
				
			||||||
        gen_op_raise_exception(EXCP01_SSTP);
 | 
					            gen_op_jmp_im(pc_ptr - dc->cs_base);
 | 
				
			||||||
 | 
					            gen_eob(dc);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        /* if too long translation, stop generation too */
 | 
				
			||||||
 | 
					        if (gen_opc_ptr >= gen_opc_end ||
 | 
				
			||||||
 | 
					            (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
 | 
				
			||||||
 | 
					            gen_op_jmp_im(pc_ptr - dc->cs_base);
 | 
				
			||||||
 | 
					            gen_eob(dc);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 the_end:
 | 
					 | 
				
			||||||
    if (dc->is_jmp != DISAS_TB_JUMP) {
 | 
					 | 
				
			||||||
        /* indicate that the hash table must be used to find the next TB */
 | 
					 | 
				
			||||||
        gen_op_movl_T0_0();
 | 
					 | 
				
			||||||
        gen_op_exit_tb();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    *gen_opc_ptr = INDEX_op_end;
 | 
					    *gen_opc_ptr = INDEX_op_end;
 | 
				
			||||||
    /* we don't forget to fill the last values */
 | 
					    /* we don't forget to fill the last values */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user