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) | ... | ... |