qemu-stable
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-stable] [PATCH 1/2] target-xtensa: fix translation for opcodes cro


From: Max Filippov
Subject: [Qemu-stable] [PATCH 1/2] target-xtensa: fix translation for opcodes crossing page boundary
Date: Sun, 14 Dec 2014 08:58:39 +0300

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: address@hidden
Signed-off-by: Max Filippov <address@hidden>
---
 target-xtensa/translate.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index badca19..a81573d 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -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 { \
@@ -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
@@ -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*/
@@ -2949,6 +2961,12 @@ invalid_opcode:
 #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));
@@ -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);
-- 
1.8.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]