Commit 6e256c935cbd5ce9bf1891477188549bbb43e55b
1 parent
c1942362
use direct jump only for jumps in the same page
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1629 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
110 additions
and
72 deletions
target-arm/translate.c
@@ -903,16 +903,26 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -903,16 +903,26 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
903 | return 0; | 903 | return 0; |
904 | } | 904 | } |
905 | 905 | ||
906 | -static inline void gen_jmp_tb(long tb, int n, uint32_t dest) | 906 | +static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) |
907 | { | 907 | { |
908 | - if (n == 0) | ||
909 | - gen_op_goto_tb0(TBPARAM(tb)); | ||
910 | - else | ||
911 | - gen_op_goto_tb1(TBPARAM(tb)); | ||
912 | - gen_op_movl_T0_im(dest); | ||
913 | - gen_op_movl_r15_T0(); | ||
914 | - gen_op_movl_T0_im(tb + n); | ||
915 | - gen_op_exit_tb(); | 908 | + TranslationBlock *tb; |
909 | + | ||
910 | + tb = s->tb; | ||
911 | + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { | ||
912 | + if (n == 0) | ||
913 | + gen_op_goto_tb0(TBPARAM(tb)); | ||
914 | + else | ||
915 | + gen_op_goto_tb1(TBPARAM(tb)); | ||
916 | + gen_op_movl_T0_im(dest); | ||
917 | + gen_op_movl_r15_T0(); | ||
918 | + gen_op_movl_T0_im((long)tb + n); | ||
919 | + gen_op_exit_tb(); | ||
920 | + } else { | ||
921 | + gen_op_movl_T0_im(dest); | ||
922 | + gen_op_movl_r15_T0(); | ||
923 | + gen_op_movl_T0_0(); | ||
924 | + gen_op_exit_tb(); | ||
925 | + } | ||
916 | } | 926 | } |
917 | 927 | ||
918 | static inline void gen_jmp (DisasContext *s, uint32_t dest) | 928 | static inline void gen_jmp (DisasContext *s, uint32_t dest) |
@@ -924,8 +934,7 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest) | @@ -924,8 +934,7 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest) | ||
924 | gen_op_movl_T0_im(dest); | 934 | gen_op_movl_T0_im(dest); |
925 | gen_bx(s); | 935 | gen_bx(s); |
926 | } else { | 936 | } else { |
927 | - long tb = (long)s->tb; | ||
928 | - gen_jmp_tb(tb, 0, dest); | 937 | + gen_goto_tb(s, 0, dest); |
929 | s->is_jmp = DISAS_TB_JUMP; | 938 | s->is_jmp = DISAS_TB_JUMP; |
930 | } | 939 | } |
931 | } | 940 | } |
@@ -2137,7 +2146,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -2137,7 +2146,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
2137 | } else { | 2146 | } else { |
2138 | switch(dc->is_jmp) { | 2147 | switch(dc->is_jmp) { |
2139 | case DISAS_NEXT: | 2148 | case DISAS_NEXT: |
2140 | - gen_jmp_tb((long)dc->tb, 1, dc->pc); | 2149 | + gen_goto_tb(dc, 1, dc->pc); |
2141 | break; | 2150 | break; |
2142 | default: | 2151 | default: |
2143 | case DISAS_JUMP: | 2152 | case DISAS_JUMP: |
@@ -2152,7 +2161,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -2152,7 +2161,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
2152 | } | 2161 | } |
2153 | if (dc->condjmp) { | 2162 | if (dc->condjmp) { |
2154 | gen_set_label(dc->condlabel); | 2163 | gen_set_label(dc->condlabel); |
2155 | - gen_jmp_tb((long)dc->tb, 1, dc->pc); | 2164 | + gen_goto_tb(dc, 1, dc->pc); |
2156 | dc->condjmp = 0; | 2165 | dc->condjmp = 0; |
2157 | } | 2166 | } |
2158 | } | 2167 | } |
target-i386/translate.c
@@ -1700,6 +1700,31 @@ static inline int insn_const_size(unsigned int ot) | @@ -1700,6 +1700,31 @@ static inline int insn_const_size(unsigned int ot) | ||
1700 | return 4; | 1700 | return 4; |
1701 | } | 1701 | } |
1702 | 1702 | ||
1703 | +static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) | ||
1704 | +{ | ||
1705 | + TranslationBlock *tb; | ||
1706 | + target_ulong pc; | ||
1707 | + | ||
1708 | + pc = s->cs_base + eip; | ||
1709 | + tb = s->tb; | ||
1710 | + /* NOTE: we handle the case where the TB spans two pages here */ | ||
1711 | + if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) || | ||
1712 | + (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) { | ||
1713 | + /* jump to same page: we can use a direct jump */ | ||
1714 | + if (tb_num == 0) | ||
1715 | + gen_op_goto_tb0(TBPARAM(tb)); | ||
1716 | + else | ||
1717 | + gen_op_goto_tb1(TBPARAM(tb)); | ||
1718 | + gen_jmp_im(eip); | ||
1719 | + gen_op_movl_T0_im((long)tb + tb_num); | ||
1720 | + gen_op_exit_tb(); | ||
1721 | + } else { | ||
1722 | + /* jump to another page: currently not optimized */ | ||
1723 | + gen_jmp_im(eip); | ||
1724 | + gen_eob(s); | ||
1725 | + } | ||
1726 | +} | ||
1727 | + | ||
1703 | static inline void gen_jcc(DisasContext *s, int b, | 1728 | static inline void gen_jcc(DisasContext *s, int b, |
1704 | target_ulong val, target_ulong next_eip) | 1729 | target_ulong val, target_ulong next_eip) |
1705 | { | 1730 | { |
@@ -1779,8 +1804,10 @@ static inline void gen_jcc(DisasContext *s, int b, | @@ -1779,8 +1804,10 @@ static inline void gen_jcc(DisasContext *s, int b, | ||
1779 | break; | 1804 | break; |
1780 | } | 1805 | } |
1781 | 1806 | ||
1782 | - if (s->cc_op != CC_OP_DYNAMIC) | 1807 | + if (s->cc_op != CC_OP_DYNAMIC) { |
1783 | gen_op_set_cc_op(s->cc_op); | 1808 | gen_op_set_cc_op(s->cc_op); |
1809 | + s->cc_op = CC_OP_DYNAMIC; | ||
1810 | + } | ||
1784 | 1811 | ||
1785 | if (!func) { | 1812 | if (!func) { |
1786 | gen_setcc_slow[jcc_op](); | 1813 | gen_setcc_slow[jcc_op](); |
@@ -1797,16 +1824,10 @@ static inline void gen_jcc(DisasContext *s, int b, | @@ -1797,16 +1824,10 @@ static inline void gen_jcc(DisasContext *s, int b, | ||
1797 | l1 = gen_new_label(); | 1824 | l1 = gen_new_label(); |
1798 | func(l1); | 1825 | func(l1); |
1799 | 1826 | ||
1800 | - gen_op_goto_tb0(TBPARAM(tb)); | ||
1801 | - gen_jmp_im(next_eip); | ||
1802 | - gen_op_movl_T0_im((long)tb + 0); | ||
1803 | - gen_op_exit_tb(); | 1827 | + gen_goto_tb(s, 0, next_eip); |
1804 | 1828 | ||
1805 | gen_set_label(l1); | 1829 | gen_set_label(l1); |
1806 | - gen_op_goto_tb1(TBPARAM(tb)); | ||
1807 | - gen_jmp_im(val); | ||
1808 | - gen_op_movl_T0_im((long)tb + 1); | ||
1809 | - gen_op_exit_tb(); | 1830 | + gen_goto_tb(s, 1, val); |
1810 | 1831 | ||
1811 | s->is_jmp = 3; | 1832 | s->is_jmp = 3; |
1812 | } else { | 1833 | } else { |
@@ -2217,18 +2238,12 @@ static void gen_eob(DisasContext *s) | @@ -2217,18 +2238,12 @@ static void gen_eob(DisasContext *s) | ||
2217 | direct call to the next block may occur */ | 2238 | direct call to the next block may occur */ |
2218 | static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num) | 2239 | static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num) |
2219 | { | 2240 | { |
2220 | - TranslationBlock *tb = s->tb; | ||
2221 | - | ||
2222 | if (s->jmp_opt) { | 2241 | if (s->jmp_opt) { |
2223 | - if (s->cc_op != CC_OP_DYNAMIC) | 2242 | + if (s->cc_op != CC_OP_DYNAMIC) { |
2224 | gen_op_set_cc_op(s->cc_op); | 2243 | gen_op_set_cc_op(s->cc_op); |
2225 | - if (tb_num) | ||
2226 | - gen_op_goto_tb1(TBPARAM(tb)); | ||
2227 | - else | ||
2228 | - gen_op_goto_tb0(TBPARAM(tb)); | ||
2229 | - gen_jmp_im(eip); | ||
2230 | - gen_op_movl_T0_im((long)tb + tb_num); | ||
2231 | - gen_op_exit_tb(); | 2244 | + s->cc_op = CC_OP_DYNAMIC; |
2245 | + } | ||
2246 | + gen_goto_tb(s, tb_num, eip); | ||
2232 | s->is_jmp = 3; | 2247 | s->is_jmp = 3; |
2233 | } else { | 2248 | } else { |
2234 | gen_jmp_im(eip); | 2249 | gen_jmp_im(eip); |
target-mips/translate.c
@@ -928,15 +928,23 @@ static void gen_trap (DisasContext *ctx, uint16_t opc, | @@ -928,15 +928,23 @@ static void gen_trap (DisasContext *ctx, uint16_t opc, | ||
928 | ctx->bstate = BS_STOP; | 928 | ctx->bstate = BS_STOP; |
929 | } | 929 | } |
930 | 930 | ||
931 | -static inline void gen_jmp_tb(long tb, int n, uint32_t dest) | 931 | +static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) |
932 | { | 932 | { |
933 | - if (n == 0) | ||
934 | - gen_op_goto_tb0(TBPARAM(tb)); | ||
935 | - else | ||
936 | - gen_op_goto_tb1(TBPARAM(tb)); | ||
937 | - gen_op_save_pc(dest); | ||
938 | - gen_op_set_T0(tb + n); | ||
939 | - gen_op_exit_tb(); | 933 | + TranslationBlock *tb; |
934 | + tb = ctx->tb; | ||
935 | + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { | ||
936 | + if (n == 0) | ||
937 | + gen_op_goto_tb0(TBPARAM(tb)); | ||
938 | + else | ||
939 | + gen_op_goto_tb1(TBPARAM(tb)); | ||
940 | + gen_op_save_pc(dest); | ||
941 | + gen_op_set_T0((long)tb + n); | ||
942 | + gen_op_exit_tb(); | ||
943 | + } else { | ||
944 | + gen_op_save_pc(dest); | ||
945 | + gen_op_set_T0(0); | ||
946 | + gen_op_exit_tb(); | ||
947 | + } | ||
940 | } | 948 | } |
941 | 949 | ||
942 | /* Branches (before delay slot) */ | 950 | /* Branches (before delay slot) */ |
@@ -1035,7 +1043,7 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | @@ -1035,7 +1043,7 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | ||
1035 | case OPC_BLTZL: /* 0 < 0 likely */ | 1043 | case OPC_BLTZL: /* 0 < 0 likely */ |
1036 | /* Skip the instruction in the delay slot */ | 1044 | /* Skip the instruction in the delay slot */ |
1037 | MIPS_DEBUG("bnever and skip"); | 1045 | MIPS_DEBUG("bnever and skip"); |
1038 | - gen_jmp_tb((long)ctx->tb, 0, ctx->pc + 4); | 1046 | + gen_goto_tb(ctx, 0, ctx->pc + 4); |
1039 | return; | 1047 | return; |
1040 | case OPC_J: | 1048 | case OPC_J: |
1041 | ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; | 1049 | ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; |
@@ -1278,7 +1286,7 @@ static void gen_blikely(DisasContext *ctx) | @@ -1278,7 +1286,7 @@ static void gen_blikely(DisasContext *ctx) | ||
1278 | l1 = gen_new_label(); | 1286 | l1 = gen_new_label(); |
1279 | gen_op_jnz_T2(l1); | 1287 | gen_op_jnz_T2(l1); |
1280 | gen_op_save_state(ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS)); | 1288 | gen_op_save_state(ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS)); |
1281 | - gen_jmp_tb((long)ctx->tb, 1, ctx->pc + 4); | 1289 | + gen_goto_tb(ctx, 1, ctx->pc + 4); |
1282 | } | 1290 | } |
1283 | 1291 | ||
1284 | static void decode_opc (DisasContext *ctx) | 1292 | static void decode_opc (DisasContext *ctx) |
@@ -1502,12 +1510,12 @@ static void decode_opc (DisasContext *ctx) | @@ -1502,12 +1510,12 @@ static void decode_opc (DisasContext *ctx) | ||
1502 | case MIPS_HFLAG_B: | 1510 | case MIPS_HFLAG_B: |
1503 | /* unconditional branch */ | 1511 | /* unconditional branch */ |
1504 | MIPS_DEBUG("unconditional branch"); | 1512 | MIPS_DEBUG("unconditional branch"); |
1505 | - gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); | 1513 | + gen_goto_tb(ctx, 0, ctx->btarget); |
1506 | break; | 1514 | break; |
1507 | case MIPS_HFLAG_BL: | 1515 | case MIPS_HFLAG_BL: |
1508 | /* blikely taken case */ | 1516 | /* blikely taken case */ |
1509 | MIPS_DEBUG("blikely branch taken"); | 1517 | MIPS_DEBUG("blikely branch taken"); |
1510 | - gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); | 1518 | + gen_goto_tb(ctx, 0, ctx->btarget); |
1511 | break; | 1519 | break; |
1512 | case MIPS_HFLAG_BC: | 1520 | case MIPS_HFLAG_BC: |
1513 | /* Conditional branch */ | 1521 | /* Conditional branch */ |
@@ -1516,9 +1524,9 @@ static void decode_opc (DisasContext *ctx) | @@ -1516,9 +1524,9 @@ static void decode_opc (DisasContext *ctx) | ||
1516 | int l1; | 1524 | int l1; |
1517 | l1 = gen_new_label(); | 1525 | l1 = gen_new_label(); |
1518 | gen_op_jnz_T2(l1); | 1526 | gen_op_jnz_T2(l1); |
1519 | - gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); | 1527 | + gen_goto_tb(ctx, 0, ctx->btarget); |
1520 | gen_set_label(l1); | 1528 | gen_set_label(l1); |
1521 | - gen_jmp_tb((long)ctx->tb, 1, ctx->pc + 4); | 1529 | + gen_goto_tb(ctx, 1, ctx->pc + 4); |
1522 | } | 1530 | } |
1523 | break; | 1531 | break; |
1524 | case MIPS_HFLAG_BR: | 1532 | case MIPS_HFLAG_BR: |
@@ -1603,7 +1611,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, | @@ -1603,7 +1611,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, | ||
1603 | } | 1611 | } |
1604 | if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { | 1612 | if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { |
1605 | save_cpu_state(ctxp, 0); | 1613 | save_cpu_state(ctxp, 0); |
1606 | - gen_jmp_tb((long)ctx.tb, 0, ctx.pc); | 1614 | + gen_goto_tb(&ctx, 0, ctx.pc); |
1607 | } | 1615 | } |
1608 | gen_op_reset_T0(); | 1616 | gen_op_reset_T0(); |
1609 | /* Generate the return instruction */ | 1617 | /* Generate the return instruction */ |
target-sparc/translate.c
@@ -561,6 +561,32 @@ static inline void gen_movl_npc_im(target_ulong npc) | @@ -561,6 +561,32 @@ static inline void gen_movl_npc_im(target_ulong npc) | ||
561 | #endif | 561 | #endif |
562 | } | 562 | } |
563 | 563 | ||
564 | +static inline void gen_goto_tb(DisasContext *s, int tb_num, | ||
565 | + target_ulong pc, target_ulong npc) | ||
566 | +{ | ||
567 | + TranslationBlock *tb; | ||
568 | + | ||
569 | + tb = s->tb; | ||
570 | + if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) && | ||
571 | + (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) { | ||
572 | + /* jump to same page: we can use a direct jump */ | ||
573 | + if (tb_num == 0) | ||
574 | + gen_op_goto_tb0(TBPARAM(tb)); | ||
575 | + else | ||
576 | + gen_op_goto_tb1(TBPARAM(tb)); | ||
577 | + gen_jmp_im(pc); | ||
578 | + gen_movl_npc_im(npc); | ||
579 | + gen_op_movl_T0_im((long)tb + tb_num); | ||
580 | + gen_op_exit_tb(); | ||
581 | + } else { | ||
582 | + /* jump to another page: currently not optimized */ | ||
583 | + gen_jmp_im(pc); | ||
584 | + gen_movl_npc_im(npc); | ||
585 | + gen_op_movl_T0_0(); | ||
586 | + gen_op_exit_tb(); | ||
587 | + } | ||
588 | +} | ||
589 | + | ||
564 | static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2) | 590 | static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2) |
565 | { | 591 | { |
566 | int l1; | 592 | int l1; |
@@ -569,18 +595,10 @@ static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, targ | @@ -569,18 +595,10 @@ static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, targ | ||
569 | 595 | ||
570 | gen_op_jz_T2_label(l1); | 596 | gen_op_jz_T2_label(l1); |
571 | 597 | ||
572 | - gen_op_goto_tb0(TBPARAM(tb)); | ||
573 | - gen_jmp_im(pc1); | ||
574 | - gen_movl_npc_im(pc1 + 4); | ||
575 | - gen_op_movl_T0_im((long)tb + 0); | ||
576 | - gen_op_exit_tb(); | 598 | + gen_goto_tb(dc, 0, pc1, pc1 + 4); |
577 | 599 | ||
578 | gen_set_label(l1); | 600 | gen_set_label(l1); |
579 | - gen_op_goto_tb1(TBPARAM(tb)); | ||
580 | - gen_jmp_im(pc2); | ||
581 | - gen_movl_npc_im(pc2 + 4); | ||
582 | - gen_op_movl_T0_im((long)tb + 1); | ||
583 | - gen_op_exit_tb(); | 601 | + gen_goto_tb(dc, 1, pc2, pc2 + 4); |
584 | } | 602 | } |
585 | 603 | ||
586 | static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2) | 604 | static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2) |
@@ -591,27 +609,15 @@ static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, tar | @@ -591,27 +609,15 @@ static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, tar | ||
591 | 609 | ||
592 | gen_op_jz_T2_label(l1); | 610 | gen_op_jz_T2_label(l1); |
593 | 611 | ||
594 | - gen_op_goto_tb0(TBPARAM(tb)); | ||
595 | - gen_jmp_im(pc2); | ||
596 | - gen_movl_npc_im(pc1); | ||
597 | - gen_op_movl_T0_im((long)tb + 0); | ||
598 | - gen_op_exit_tb(); | 612 | + gen_goto_tb(dc, 0, pc2, pc1); |
599 | 613 | ||
600 | gen_set_label(l1); | 614 | gen_set_label(l1); |
601 | - gen_op_goto_tb1(TBPARAM(tb)); | ||
602 | - gen_jmp_im(pc2 + 4); | ||
603 | - gen_movl_npc_im(pc2 + 8); | ||
604 | - gen_op_movl_T0_im((long)tb + 1); | ||
605 | - gen_op_exit_tb(); | 615 | + gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8); |
606 | } | 616 | } |
607 | 617 | ||
608 | static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc) | 618 | static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc) |
609 | { | 619 | { |
610 | - gen_op_goto_tb0(TBPARAM(tb)); | ||
611 | - gen_jmp_im(pc); | ||
612 | - gen_movl_npc_im(npc); | ||
613 | - gen_op_movl_T0_im((long)tb + 0); | ||
614 | - gen_op_exit_tb(); | 620 | + gen_goto_tb(dc, 0, pc, npc); |
615 | } | 621 | } |
616 | 622 | ||
617 | static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2) | 623 | static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2) |