Skip to content

Commit

Permalink
target-xtensa: fix translation for opcodes crossing page boundary
Browse files Browse the repository at this point in the history
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: qemu-stable@nongnu.org
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
  • Loading branch information
jcmvbkbc committed Dec 17, 2014
1 parent 246ae24 commit 01673a3
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions target-xtensa/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,11 @@ static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
return m;
}

static inline unsigned xtensa_op0_insn_len(unsigned op0)
{
return op0 >= 8 ? 2 : 3;
}

static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
{
#define HAS_OPTION_BITS(opt) do { \
Expand Down Expand Up @@ -989,6 +994,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
uint8_t b0 = cpu_ldub_code(env, dc->pc);
uint8_t b1 = cpu_ldub_code(env, dc->pc + 1);
uint8_t b2 = 0;
unsigned len = xtensa_op0_insn_len(OP0);

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

if (OP0 >= 8) {
dc->next_pc = dc->pc + 2;
switch (len) {
case 2:
HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
} else {
dc->next_pc = dc->pc + 3;
break;

case 3:
b2 = cpu_ldub_code(env, dc->pc + 2);
break;

default:
RESERVED();
}
dc->next_pc = dc->pc + len;

switch (OP0) {
case 0: /*QRST*/
Expand Down Expand Up @@ -2949,6 +2961,12 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
#undef HAS_OPTION
}

static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc)
{
uint8_t b0 = cpu_ldub_code(env, dc->pc);
return xtensa_op0_insn_len(OP0);
}

static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
{
CPUState *cs = CPU(xtensa_env_get_cpu(env));
Expand Down Expand Up @@ -3081,6 +3099,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
} while (dc.is_jmp == DISAS_NEXT &&
insn_count < max_insns &&
dc.pc < next_page_start &&
dc.pc + xtensa_insn_len(env, &dc) <= next_page_start &&
tcg_ctx.gen_opc_ptr < gen_opc_end);

reset_litbase(&dc);
Expand Down

0 comments on commit 01673a3

Please sign in to comment.