diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 7e363654b8..3ecff96325 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -28,6 +28,9 @@ #define TARGET_LONG_BITS 32 #endif +/* Maximum instruction code size */ +#define TARGET_MAX_INSN_SIZE 16 + /* target supports implicit self modifying code */ #define TARGET_HAS_SMC /* support for self modifying code even if the modified instruction is diff --git a/target-i386/translate.c b/target-i386/translate.c index 782f7d2666..31a9f74467 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -8022,6 +8022,20 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, gen_eob(dc); break; } + /* Do not cross the boundary of the pages in icount mode, + it can cause an exception. Do it only when boundary is + crossed by the first instruction in the block. + If current instruction already crossed the bound - it's ok, + because an exception hasn't stopped this code. + */ + if (use_icount + && ((pc_ptr & TARGET_PAGE_MASK) + != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK) + || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) { + gen_jmp_im(pc_ptr - dc->cs_base); + gen_eob(dc); + break; + } /* if too long translation, stop generation too */ if (tcg_ctx.gen_opc_ptr >= gen_opc_end || (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||