mirror of https://github.com/xqemu/xqemu.git
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
543
translate-i386.c
543
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);
|
||||||
gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
|
s->cc_op = CC_OP_DYNAMIC;
|
||||||
gen_movs(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_jz_ecx_string(DisasContext *s, unsigned int next_eip)
|
||||||
|
{
|
||||||
|
if (s->jmp_opt) {
|
||||||
|
gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
|
||||||
|
} else {
|
||||||
|
/* XXX: does not work with gdbstub "ice" single step - not a
|
||||||
|
serious problem */
|
||||||
|
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,71 +1360,86 @@ 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;
|
||||||
switch(s->cc_op) {
|
|
||||||
/* we optimize the cmp/jcc case */
|
if (s->jmp_opt) {
|
||||||
case CC_OP_SUBB:
|
switch(s->cc_op) {
|
||||||
case CC_OP_SUBW:
|
/* we optimize the cmp/jcc case */
|
||||||
case CC_OP_SUBL:
|
case CC_OP_SUBB:
|
||||||
func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
|
case CC_OP_SUBW:
|
||||||
break;
|
case CC_OP_SUBL:
|
||||||
|
func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
|
||||||
/* some jumps are easy to compute */
|
|
||||||
case CC_OP_ADDB:
|
|
||||||
case CC_OP_ADDW:
|
|
||||||
case CC_OP_ADDL:
|
|
||||||
case CC_OP_ADCB:
|
|
||||||
case CC_OP_ADCW:
|
|
||||||
case CC_OP_ADCL:
|
|
||||||
case CC_OP_SBBB:
|
|
||||||
case CC_OP_SBBW:
|
|
||||||
case CC_OP_SBBL:
|
|
||||||
case CC_OP_LOGICB:
|
|
||||||
case CC_OP_LOGICW:
|
|
||||||
case CC_OP_LOGICL:
|
|
||||||
case CC_OP_INCB:
|
|
||||||
case CC_OP_INCW:
|
|
||||||
case CC_OP_INCL:
|
|
||||||
case CC_OP_DECB:
|
|
||||||
case CC_OP_DECW:
|
|
||||||
case CC_OP_DECL:
|
|
||||||
case CC_OP_SHLB:
|
|
||||||
case CC_OP_SHLW:
|
|
||||||
case CC_OP_SHLL:
|
|
||||||
case CC_OP_SARB:
|
|
||||||
case CC_OP_SARW:
|
|
||||||
case CC_OP_SARL:
|
|
||||||
switch(jcc_op) {
|
|
||||||
case JCC_Z:
|
|
||||||
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
|
||||||
break;
|
break;
|
||||||
case JCC_S:
|
|
||||||
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
/* some jumps are easy to compute */
|
||||||
|
case CC_OP_ADDB:
|
||||||
|
case CC_OP_ADDW:
|
||||||
|
case CC_OP_ADDL:
|
||||||
|
case CC_OP_ADCB:
|
||||||
|
case CC_OP_ADCW:
|
||||||
|
case CC_OP_ADCL:
|
||||||
|
case CC_OP_SBBB:
|
||||||
|
case CC_OP_SBBW:
|
||||||
|
case CC_OP_SBBL:
|
||||||
|
case CC_OP_LOGICB:
|
||||||
|
case CC_OP_LOGICW:
|
||||||
|
case CC_OP_LOGICL:
|
||||||
|
case CC_OP_INCB:
|
||||||
|
case CC_OP_INCW:
|
||||||
|
case CC_OP_INCL:
|
||||||
|
case CC_OP_DECB:
|
||||||
|
case CC_OP_DECW:
|
||||||
|
case CC_OP_DECL:
|
||||||
|
case CC_OP_SHLB:
|
||||||
|
case CC_OP_SHLW:
|
||||||
|
case CC_OP_SHLL:
|
||||||
|
case CC_OP_SARB:
|
||||||
|
case CC_OP_SARW:
|
||||||
|
case CC_OP_SARL:
|
||||||
|
switch(jcc_op) {
|
||||||
|
case JCC_Z:
|
||||||
|
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
||||||
|
break;
|
||||||
|
case JCC_S:
|
||||||
|
func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
func = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
func = NULL;
|
func = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
func = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
if (!func) {
|
if (!func) {
|
||||||
gen_setcc_slow[jcc_op]();
|
gen_setcc_slow[jcc_op]();
|
||||||
func = gen_op_jcc;
|
func = gen_op_jcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
tb = s->tb;
|
tb = s->tb;
|
||||||
if (!inv) {
|
if (!inv) {
|
||||||
func((long)tb, val, next_eip);
|
func((long)tb, val, next_eip);
|
||||||
|
} else {
|
||||||
|
func((long)tb, next_eip, val);
|
||||||
|
}
|
||||||
|
s->is_jmp = 3;
|
||||||
} else {
|
} else {
|
||||||
func((long)tb, next_eip, val);
|
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);
|
||||||
}
|
}
|
||||||
s->is_jmp = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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->cc_op != CC_OP_DYNAMIC)
|
if (s->jmp_opt) {
|
||||||
gen_op_set_cc_op(s->cc_op);
|
if (s->cc_op != CC_OP_DYNAMIC)
|
||||||
gen_op_jmp_tb_next((long)tb, eip);
|
gen_op_set_cc_op(s->cc_op);
|
||||||
s->is_jmp = 3;
|
gen_op_jmp((long)tb, eip);
|
||||||
|
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
|
break;
|
||||||
generating the code just before it */
|
|
||||||
if (pc_ptr == pc_start)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
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)
|
if (dc->tf) {
|
||||||
|
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;
|
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) {
|
|
||||||
gen_op_raise_exception(EXCP01_SSTP);
|
|
||||||
}
|
|
||||||
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…
Reference in New Issue