aboutsummaryrefslogtreecommitdiff
path: root/target-i386/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386/translate.c')
-rw-r--r--target-i386/translate.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 0f6b0eb7c6..dab0378079 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -1700,6 +1700,31 @@ static inline int insn_const_size(unsigned int ot)
return 4;
}
+static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
+{
+ TranslationBlock *tb;
+ target_ulong pc;
+
+ pc = s->cs_base + eip;
+ tb = s->tb;
+ /* NOTE: we handle the case where the TB spans two pages here */
+ if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
+ (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
+ /* jump to same page: we can use a direct jump */
+ if (tb_num == 0)
+ gen_op_goto_tb0(TBPARAM(tb));
+ else
+ gen_op_goto_tb1(TBPARAM(tb));
+ gen_jmp_im(eip);
+ gen_op_movl_T0_im((long)tb + tb_num);
+ gen_op_exit_tb();
+ } else {
+ /* jump to another page: currently not optimized */
+ gen_jmp_im(eip);
+ gen_eob(s);
+ }
+}
+
static inline void gen_jcc(DisasContext *s, int b,
target_ulong val, target_ulong next_eip)
{
@@ -1779,8 +1804,10 @@ static inline void gen_jcc(DisasContext *s, int b,
break;
}
- if (s->cc_op != CC_OP_DYNAMIC)
+ if (s->cc_op != CC_OP_DYNAMIC) {
gen_op_set_cc_op(s->cc_op);
+ s->cc_op = CC_OP_DYNAMIC;
+ }
if (!func) {
gen_setcc_slow[jcc_op]();
@@ -1797,16 +1824,10 @@ static inline void gen_jcc(DisasContext *s, int b,
l1 = gen_new_label();
func(l1);
- gen_op_goto_tb0(TBPARAM(tb));
- gen_jmp_im(next_eip);
- gen_op_movl_T0_im((long)tb + 0);
- gen_op_exit_tb();
+ gen_goto_tb(s, 0, next_eip);
gen_set_label(l1);
- gen_op_goto_tb1(TBPARAM(tb));
- gen_jmp_im(val);
- gen_op_movl_T0_im((long)tb + 1);
- gen_op_exit_tb();
+ gen_goto_tb(s, 1, val);
s->is_jmp = 3;
} else {
@@ -2217,18 +2238,12 @@ static void gen_eob(DisasContext *s)
direct call to the next block may occur */
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
{
- 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);
- if (tb_num)
- gen_op_goto_tb1(TBPARAM(tb));
- else
- gen_op_goto_tb0(TBPARAM(tb));
- gen_jmp_im(eip);
- gen_op_movl_T0_im((long)tb + tb_num);
- gen_op_exit_tb();
+ s->cc_op = CC_OP_DYNAMIC;
+ }
+ gen_goto_tb(s, tb_num, eip);
s->is_jmp = 3;
} else {
gen_jmp_im(eip);