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 | 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 | 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 | 934 | gen_op_movl_T0_im(dest); |
925 | 935 | gen_bx(s); |
926 | 936 | } else { |
927 | - long tb = (long)s->tb; | |
928 | - gen_jmp_tb(tb, 0, dest); | |
937 | + gen_goto_tb(s, 0, dest); | |
929 | 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 | 2146 | } else { |
2138 | 2147 | switch(dc->is_jmp) { |
2139 | 2148 | case DISAS_NEXT: |
2140 | - gen_jmp_tb((long)dc->tb, 1, dc->pc); | |
2149 | + gen_goto_tb(dc, 1, dc->pc); | |
2141 | 2150 | break; |
2142 | 2151 | default: |
2143 | 2152 | case DISAS_JUMP: |
... | ... | @@ -2152,7 +2161,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
2152 | 2161 | } |
2153 | 2162 | if (dc->condjmp) { |
2154 | 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 | 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 | 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 | 1728 | static inline void gen_jcc(DisasContext *s, int b, |
1704 | 1729 | target_ulong val, target_ulong next_eip) |
1705 | 1730 | { |
... | ... | @@ -1779,8 +1804,10 @@ static inline void gen_jcc(DisasContext *s, int b, |
1779 | 1804 | break; |
1780 | 1805 | } |
1781 | 1806 | |
1782 | - if (s->cc_op != CC_OP_DYNAMIC) | |
1807 | + if (s->cc_op != CC_OP_DYNAMIC) { | |
1783 | 1808 | gen_op_set_cc_op(s->cc_op); |
1809 | + s->cc_op = CC_OP_DYNAMIC; | |
1810 | + } | |
1784 | 1811 | |
1785 | 1812 | if (!func) { |
1786 | 1813 | gen_setcc_slow[jcc_op](); |
... | ... | @@ -1797,16 +1824,10 @@ static inline void gen_jcc(DisasContext *s, int b, |
1797 | 1824 | l1 = gen_new_label(); |
1798 | 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 | 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 | 1832 | s->is_jmp = 3; |
1812 | 1833 | } else { |
... | ... | @@ -2217,18 +2238,12 @@ static void gen_eob(DisasContext *s) |
2217 | 2238 | direct call to the next block may occur */ |
2218 | 2239 | static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num) |
2219 | 2240 | { |
2220 | - TranslationBlock *tb = s->tb; | |
2221 | - | |
2222 | 2241 | if (s->jmp_opt) { |
2223 | - if (s->cc_op != CC_OP_DYNAMIC) | |
2242 | + if (s->cc_op != CC_OP_DYNAMIC) { | |
2224 | 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 | 2247 | s->is_jmp = 3; |
2233 | 2248 | } else { |
2234 | 2249 | gen_jmp_im(eip); | ... | ... |
target-mips/translate.c
... | ... | @@ -928,15 +928,23 @@ static void gen_trap (DisasContext *ctx, uint16_t opc, |
928 | 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 | 950 | /* Branches (before delay slot) */ |
... | ... | @@ -1035,7 +1043,7 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, |
1035 | 1043 | case OPC_BLTZL: /* 0 < 0 likely */ |
1036 | 1044 | /* Skip the instruction in the delay slot */ |
1037 | 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 | 1047 | return; |
1040 | 1048 | case OPC_J: |
1041 | 1049 | ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; |
... | ... | @@ -1278,7 +1286,7 @@ static void gen_blikely(DisasContext *ctx) |
1278 | 1286 | l1 = gen_new_label(); |
1279 | 1287 | gen_op_jnz_T2(l1); |
1280 | 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 | 1292 | static void decode_opc (DisasContext *ctx) |
... | ... | @@ -1502,12 +1510,12 @@ static void decode_opc (DisasContext *ctx) |
1502 | 1510 | case MIPS_HFLAG_B: |
1503 | 1511 | /* unconditional branch */ |
1504 | 1512 | MIPS_DEBUG("unconditional branch"); |
1505 | - gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); | |
1513 | + gen_goto_tb(ctx, 0, ctx->btarget); | |
1506 | 1514 | break; |
1507 | 1515 | case MIPS_HFLAG_BL: |
1508 | 1516 | /* blikely taken case */ |
1509 | 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 | 1519 | break; |
1512 | 1520 | case MIPS_HFLAG_BC: |
1513 | 1521 | /* Conditional branch */ |
... | ... | @@ -1516,9 +1524,9 @@ static void decode_opc (DisasContext *ctx) |
1516 | 1524 | int l1; |
1517 | 1525 | l1 = gen_new_label(); |
1518 | 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 | 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 | 1531 | break; |
1524 | 1532 | case MIPS_HFLAG_BR: |
... | ... | @@ -1603,7 +1611,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, |
1603 | 1611 | } |
1604 | 1612 | if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { |
1605 | 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 | 1616 | gen_op_reset_T0(); |
1609 | 1617 | /* Generate the return instruction */ | ... | ... |
target-sparc/translate.c
... | ... | @@ -561,6 +561,32 @@ static inline void gen_movl_npc_im(target_ulong npc) |
561 | 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 | 590 | static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2) |
565 | 591 | { |
566 | 592 | int l1; |
... | ... | @@ -569,18 +595,10 @@ static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, targ |
569 | 595 | |
570 | 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 | 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 | 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 | 609 | |
592 | 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 | 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 | 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 | 623 | static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2) | ... | ... |