Revisão | d0264d86b026e9d948de577b05ff86d708658576 (tree) |
---|---|
Hora | 2017-09-07 00:06:48 |
Autor | Richard Henderson <rth@twid...> |
Commiter | Richard Henderson |
target/arm: Perform per-insn cross-page check only for Thumb
ARM is a fixed-length ISA and we can compute the page crossing
condition exactly once during init_disas_context.
Reviewed-by: Emilio G. Cota <cota@braap.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
@@ -11888,6 +11888,13 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase, | ||
11888 | 11888 | max_insns = 1; |
11889 | 11889 | } |
11890 | 11890 | |
11891 | + /* ARM is a fixed-length ISA. Bound the number of insns to execute | |
11892 | + to those left on the page. */ | |
11893 | + if (!dc->thumb) { | |
11894 | + int bound = (dc->next_page_start - dc->base.pc_first) / 4; | |
11895 | + max_insns = MIN(max_insns, bound); | |
11896 | + } | |
11897 | + | |
11891 | 11898 | cpu_F0s = tcg_temp_new_i32(); |
11892 | 11899 | cpu_F1s = tcg_temp_new_i32(); |
11893 | 11900 | cpu_F0d = tcg_temp_new_i64(); |
@@ -12015,34 +12022,12 @@ static bool arm_pre_translate_insn(DisasContext *dc) | ||
12015 | 12022 | return false; |
12016 | 12023 | } |
12017 | 12024 | |
12018 | -static void arm_post_translate_insn(CPUARMState *env, DisasContext *dc) | |
12025 | +static void arm_post_translate_insn(DisasContext *dc) | |
12019 | 12026 | { |
12020 | 12027 | if (dc->condjmp && !dc->base.is_jmp) { |
12021 | 12028 | gen_set_label(dc->condlabel); |
12022 | 12029 | dc->condjmp = 0; |
12023 | 12030 | } |
12024 | - | |
12025 | - /* Translation stops when a conditional branch is encountered. | |
12026 | - * Otherwise the subsequent code could get translated several times. | |
12027 | - * Also stop translation when a page boundary is reached. This | |
12028 | - * ensures prefetch aborts occur at the right place. | |
12029 | - * | |
12030 | - * We want to stop the TB if the next insn starts in a new page, | |
12031 | - * or if it spans between this page and the next. This means that | |
12032 | - * if we're looking at the last halfword in the page we need to | |
12033 | - * see if it's a 16-bit Thumb insn (which will fit in this TB) | |
12034 | - * or a 32-bit Thumb insn (which won't). | |
12035 | - * This is to avoid generating a silly TB with a single 16-bit insn | |
12036 | - * in it at the end of this page (which would execute correctly | |
12037 | - * but isn't very efficient). | |
12038 | - */ | |
12039 | - if (dc->base.is_jmp == DISAS_NEXT | |
12040 | - && (dc->pc >= dc->next_page_start | |
12041 | - || (dc->pc >= dc->next_page_start - 3 | |
12042 | - && insn_crosses_page(env, dc)))) { | |
12043 | - dc->base.is_jmp = DISAS_TOO_MANY; | |
12044 | - } | |
12045 | - | |
12046 | 12031 | dc->base.pc_next = dc->pc; |
12047 | 12032 | translator_loop_temp_check(&dc->base); |
12048 | 12033 | } |
@@ -12061,7 +12046,10 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | ||
12061 | 12046 | dc->pc += 4; |
12062 | 12047 | disas_arm_insn(dc, insn); |
12063 | 12048 | |
12064 | - arm_post_translate_insn(env, dc); | |
12049 | + arm_post_translate_insn(dc); | |
12050 | + | |
12051 | + /* ARM is a fixed-length ISA. We performed the cross-page check | |
12052 | + in init_disas_context by adjusting max_insns. */ | |
12065 | 12053 | } |
12066 | 12054 | |
12067 | 12055 | static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) |
@@ -12085,7 +12073,27 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) | ||
12085 | 12073 | } |
12086 | 12074 | } |
12087 | 12075 | |
12088 | - arm_post_translate_insn(env, dc); | |
12076 | + arm_post_translate_insn(dc); | |
12077 | + | |
12078 | + /* Thumb is a variable-length ISA. Stop translation when the next insn | |
12079 | + * will touch a new page. This ensures that prefetch aborts occur at | |
12080 | + * the right place. | |
12081 | + * | |
12082 | + * We want to stop the TB if the next insn starts in a new page, | |
12083 | + * or if it spans between this page and the next. This means that | |
12084 | + * if we're looking at the last halfword in the page we need to | |
12085 | + * see if it's a 16-bit Thumb insn (which will fit in this TB) | |
12086 | + * or a 32-bit Thumb insn (which won't). | |
12087 | + * This is to avoid generating a silly TB with a single 16-bit insn | |
12088 | + * in it at the end of this page (which would execute correctly | |
12089 | + * but isn't very efficient). | |
12090 | + */ | |
12091 | + if (dc->base.is_jmp == DISAS_NEXT | |
12092 | + && (dc->pc >= dc->next_page_start | |
12093 | + || (dc->pc >= dc->next_page_start - 3 | |
12094 | + && insn_crosses_page(env, dc)))) { | |
12095 | + dc->base.is_jmp = DISAS_TOO_MANY; | |
12096 | + } | |
12089 | 12097 | } |
12090 | 12098 | |
12091 | 12099 | static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) |