Skip to content

Commit 6e64c4e

Browse files
jcmvbkbcmdroth
authored andcommitted
target-xtensa: fix translation for opcodes crossing page boundary
If TB ends with an opcode that crosses page boundary and the following page is not executable then EPC1 for the code fetch exception wrongly points at the beginning of the TB. Always treat instruction that crosses page boundary as a separate TB. Cc: [email protected] Signed-off-by: Max Filippov <[email protected]> (cherry picked from commit 01673a3) Signed-off-by: Michael Roth <[email protected]>
1 parent 73c1527 commit 6e64c4e

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

target-xtensa/translate.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,11 @@ static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
884884
return m;
885885
}
886886

887+
static inline unsigned xtensa_op0_insn_len(unsigned op0)
888+
{
889+
return op0 >= 8 ? 2 : 3;
890+
}
891+
887892
static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
888893
{
889894
#define HAS_OPTION_BITS(opt) do { \
@@ -986,6 +991,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
986991
uint8_t b0 = cpu_ldub_code(env, dc->pc);
987992
uint8_t b1 = cpu_ldub_code(env, dc->pc + 1);
988993
uint8_t b2 = 0;
994+
unsigned len = xtensa_op0_insn_len(OP0);
989995

990996
static const uint32_t B4CONST[] = {
991997
0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
@@ -995,13 +1001,19 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
9951001
32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
9961002
};
9971003

998-
if (OP0 >= 8) {
999-
dc->next_pc = dc->pc + 2;
1004+
switch (len) {
1005+
case 2:
10001006
HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
1001-
} else {
1002-
dc->next_pc = dc->pc + 3;
1007+
break;
1008+
1009+
case 3:
10031010
b2 = cpu_ldub_code(env, dc->pc + 2);
1011+
break;
1012+
1013+
default:
1014+
RESERVED();
10041015
}
1016+
dc->next_pc = dc->pc + len;
10051017

10061018
switch (OP0) {
10071019
case 0: /*QRST*/
@@ -2946,6 +2958,12 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
29462958
#undef HAS_OPTION
29472959
}
29482960

2961+
static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc)
2962+
{
2963+
uint8_t b0 = cpu_ldub_code(env, dc->pc);
2964+
return xtensa_op0_insn_len(OP0);
2965+
}
2966+
29492967
static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
29502968
{
29512969
CPUState *cs = CPU(xtensa_env_get_cpu(env));
@@ -3078,6 +3096,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
30783096
} while (dc.is_jmp == DISAS_NEXT &&
30793097
insn_count < max_insns &&
30803098
dc.pc < next_page_start &&
3099+
dc.pc + xtensa_insn_len(env, &dc) <= next_page_start &&
30813100
tcg_ctx.gen_opc_ptr < gen_opc_end);
30823101

30833102
reset_litbase(&dc);

0 commit comments

Comments
 (0)