aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv/translate.c')
-rw-r--r--target/riscv/translate.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index a719aa6e63..f8af6daa70 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1154,12 +1154,21 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
}
ctx->nftemp = 0;
+ /* Only the first insn within a TB is allowed to cross a page boundary. */
if (ctx->base.is_jmp == DISAS_NEXT) {
- target_ulong page_start;
-
- page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
- if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) {
+ if (!is_same_page(&ctx->base, ctx->base.pc_next)) {
ctx->base.is_jmp = DISAS_TOO_MANY;
+ } else {
+ unsigned page_ofs = ctx->base.pc_next & ~TARGET_PAGE_MASK;
+
+ if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
+ uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
+ int len = insn_len(next_insn);
+
+ if (!is_same_page(&ctx->base, ctx->base.pc_next + len)) {
+ ctx->base.is_jmp = DISAS_TOO_MANY;
+ }
+ }
}
}
}