Skip to contentSkip to conversation

target-xtensa: translator optimizations

PATCH In review Max Filippov 2 participants 5 messages Dec 14, 2014 – Dec 15, 2014

lore
Share & tools
lore
#0 lore raw

cover target-xtensa: translator optimizations

Hi,

this series moves decision about throwing window overflow exception to translation phase and stops code generation early when privilege, window overflow or coprocessor exception is thrown.
LTP test suite with this series applied runs 6% faster.

Max Filippov (2):
target-xtensa: record available window in TB flags
target-xtensa: don't generate dead code

 target-xtensa/cpu.h       |  12 +
 target-xtensa/helper.h    |   2 +-
 target-xtensa/op_helper.c |  29 +-
 target-xtensa/translate.c | 661 ++++++++++++++++++++++++----------------------
 4 files changed, 363 insertions(+), 341 deletions(-)
Signature · 1 line
1.8.1.4
#1 lore raw

PATCH 1/2 target-xtensa: record available window in TB flags

Record last valid 4-register window pane number in TB flags so that a window overflow exception throw point is known at the translation time.

---
 target-xtensa/cpu.h       | 12 ++++++++++
 target-xtensa/helper.h    |  2 +-
 target-xtensa/op_helper.c | 29 +++++++++-------------
 target-xtensa/translate.c | 61 ++++++++++++++---------------------------------
 4 files changed, 42 insertions(+), 62 deletions(-)
target-xtensa/cpu.h +12 -0
index ac463f2..a1bfbf7 100644
@@ -497,6 +497,8 @@ static inline int cpu_mmu_index(CPUXtensaState *env)
 #define XTENSA_TBFLAG_CPENABLE_MASK 0x3fc0
 #define XTENSA_TBFLAG_CPENABLE_SHIFT 6
 #define XTENSA_TBFLAG_EXCEPTION 0x4000
+#define XTENSA_TBFLAG_WINDOW_MASK 0x18000
+#define XTENSA_TBFLAG_WINDOW_SHIFT 15
 
 static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -528,6 +530,16 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
     if (cs->singlestep_enabled && env->exception_taken) {
         *flags |= XTENSA_TBFLAG_EXCEPTION;
     }
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER) &&
+        (env->sregs[PS] & (PS_WOE | PS_EXCM)) == PS_WOE) {
+        uint32_t windowstart = xtensa_replicate_windowstart(env) >>
+            (env->sregs[WINDOW_BASE] + 1);
+        uint32_t w = ctz32(windowstart | 0x8);
+
+        *flags |= w << XTENSA_TBFLAG_WINDOW_SHIFT;
+    } else {
+        *flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT;
+    }
 }
 
 #include "exec/cpu-all.h"
target-xtensa/helper.h +1 -1
index ed3af0b..5ea9c5b 100644
@@ -9,7 +9,7 @@ DEF_HELPER_2(wsr_windowbase, void, env, i32)
 DEF_HELPER_4(entry, void, env, i32, i32, i32)
 DEF_HELPER_2(retw, i32, env, i32)
 DEF_HELPER_2(rotw, void, env, i32)
-DEF_HELPER_3(window_check, void, env, i32, i32)
+DEF_HELPER_3(window_check, noreturn, env, i32, i32)
 DEF_HELPER_1(restore_owb, void, env)
 DEF_HELPER_2(movsp, void, env, i32)
 DEF_HELPER_2(wsr_lbeg, void, env, i32)
target-xtensa/op_helper.c +11 -18
index c4c9cb7..be657e6 100644
@@ -265,34 +265,27 @@ void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
 void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
 {
     uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
-    uint32_t windowstart = env->sregs[WINDOW_START];
-    uint32_t m, n;
+    uint32_t windowstart = xtensa_replicate_windowstart(env) >>
+        (env->sregs[WINDOW_BASE] + 1);
+    uint32_t n = ctz32(windowstart) + 1;
 
-    if ((env->sregs[PS] & (PS_WOE | PS_EXCM)) ^ PS_WOE) {
-        return;
-    }
+    assert(n <= w);
 
-    for (n = 1; ; ++n) {
-        if (n > w) {
-            return;
-        }
-        if (windowstart & windowstart_bit(windowbase + n, env)) {
-            break;
-        }
-    }
-
-    m = windowbase_bound(windowbase + n, env);
     rotate_window(env, n);
     env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
         (windowbase << PS_OWB_SHIFT) | PS_EXCM;
     env->sregs[EPC1] = env->pc = pc;
 
-    if (windowstart & windowstart_bit(m + 1, env)) {
+    switch (ctz32(windowstart >> n)) {
+    case 0:
         HELPER(exception)(env, EXC_WINDOW_OVERFLOW4);
-    } else if (windowstart & windowstart_bit(m + 2, env)) {
+        break;
+    case 1:
         HELPER(exception)(env, EXC_WINDOW_OVERFLOW8);
-    } else {
+        break;
+    default:
         HELPER(exception)(env, EXC_WINDOW_OVERFLOW12);
+        break;
     }
 }
 
target-xtensa/translate.c +18 -43

127 lines not on this page · raw message

Signature · 1 line
1.8.1.4
#2 lore raw

PATCH 2/2 target-xtensa: don't generate dead code

In reply to Max Filippov

Don't generate TCG operations when privilege, register window or coprocessor checks fail.

---
 target-xtensa/translate.c | 600 +++++++++++++++++++++++++---------------------
 1 file changed, 321 insertions(+), 279 deletions(-)
target-xtensa/translate.c +321 -279
index 18743d5..80c3ed1 100644
@@ -367,21 +367,25 @@ static void gen_debug_exception(DisasContext *dc, uint32_t cause)
     }
 }
 
-static void gen_check_privilege(DisasContext *dc)
+static bool gen_check_privilege(DisasContext *dc)
 {
     if (dc->cring) {
         gen_exception_cause(dc, PRIVILEGED_CAUSE);
         dc->is_jmp = DISAS_UPDATE;
+        return false;
     }
+    return true;
 }
 
-static void gen_check_cpenable(DisasContext *dc, unsigned cp)
+static bool gen_check_cpenable(DisasContext *dc, unsigned cp)
 {
     if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) &&
             !(dc->cpenable & (1 << cp))) {
         gen_exception_cause(dc, COPROCESSOR0_DISABLED + cp);
         dc->is_jmp = DISAS_UPDATE;
+        return false;
     }
+    return true;
 }
 
 static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
@@ -824,7 +828,7 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
     tcg_temp_free(intlevel);
 }
 
-static void gen_window_check1(DisasContext *dc, unsigned r1)
+static bool gen_window_check1(DisasContext *dc, unsigned r1)
 {
     if (r1 / 4 > dc->window) {
         TCGv_i32 pc = tcg_const_i32(dc->pc);
@@ -833,18 +837,20 @@ static void gen_window_check1(DisasContext *dc, unsigned r1)
         gen_advance_ccount(dc);
         gen_helper_window_check(cpu_env, pc, w);
         dc->is_jmp = DISAS_UPDATE;
+        return false;
     }
+    return true;
 }
 
-static void gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2)
+static bool gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2)
 {
-    gen_window_check1(dc, r1 > r2 ? r1 : r2);
+    return gen_window_check1(dc, r1 > r2 ? r1 : r2);
 }
 
-static void gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
+static bool gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
         unsigned r3)
 {
-    gen_window_check2(dc, r1, r2 > r3 ? r2 : r3);
+    return gen_window_check2(dc, r1, r2 > r3 ? r2 : r3);
 }
 
 static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
@@ -1003,8 +1009,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                         switch (CALLX_N) {
                         case 0: /*RET*/
                         case 2: /*JX*/
-                            gen_window_check1(dc, CALLX_S);
-                            gen_jump(dc, cpu_R[CALLX_S]);
+                            if (gen_window_check1(dc, CALLX_S)) {
+                                gen_jump(dc, cpu_R[CALLX_S]);
+                            }
                             break;
 
                         case 1: /*RETWw*/
@@ -1025,7 +1032,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                         break;
 
                     case 3: /*CALLX*/
-                        gen_window_check2(dc, CALLX_S, CALLX_N << 2);
+                        if (!gen_window_check2(dc, CALLX_S, CALLX_N << 2)) {
+                            break;
+                        }
                         switch (CALLX_N) {
                         case 0: /*CALLX0*/
                             {
@@ -1056,8 +1065,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
                 case 1: /*MOVSPw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                    gen_window_check2(dc, RRR_T, RRR_S);
-                    {
+                    if (gen_window_check2(dc, RRR_T, RRR_S)) {
                         TCGv_i32 pc = tcg_const_i32(dc->pc);
                         gen_advance_ccount(dc);
                         gen_helper_movsp(cpu_env, pc);
@@ -1105,10 +1113,11 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                         HAS_OPTION(XTENSA_OPTION_EXCEPTION);
                         switch (RRR_S) {
                         case 0: /*RFEx*/
-                            gen_check_privilege(dc);
-                            tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
-                            gen_helper_check_interrupts(cpu_env);
-                            gen_jump(dc, cpu_SR[EPC1]);
+                            if (gen_check_privilege(dc)) {
+                                tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
+                                gen_helper_check_interrupts(cpu_env);
+                                gen_jump(dc, cpu_SR[EPC1]);
+                            }
                             break;
 
                         case 1: /*RFUEx*/
@@ -1116,16 +1125,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                             break;
 
                         case 2: /*RFDEx*/
-                            gen_check_privilege(dc);
-                            gen_jump(dc, cpu_SR[
-                                    dc->config->ndepc ? DEPC : EPC1]);
+                            if (gen_check_privilege(dc)) {
+                                gen_jump(dc, cpu_SR[
+                                         dc->config->ndepc ? DEPC : EPC1]);
+                            }
                             break;
 
                         case 4: /*RFWOw*/
                         case 5: /*RFWUw*/
                             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                            gen_check_privilege(dc);
-                            {
+                            if (gen_check_privilege(dc)) {
                                 TCGv_i32 tmp = tcg_const_i32(1);
 
                                 tcg_gen_andi_i32(
@@ -1157,11 +1166,12 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                     case 1: /*RFIx*/
                         HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
                         if (RRR_S >= 2 && RRR_S <= dc->config->nlevel) {
-                            gen_check_privilege(dc);
-                            tcg_gen_mov_i32(cpu_SR[PS],
-                                    cpu_SR[EPS2 + RRR_S - 2]);
-                            gen_helper_check_interrupts(cpu_env);
-                            gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]);
+                            if (gen_check_privilege(dc)) {
+                                tcg_gen_mov_i32(cpu_SR[PS],
+                                                cpu_SR[EPS2 + RRR_S - 2]);
+                                gen_helper_check_interrupts(cpu_env);
+                                gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]);
+                            }
                         } else {
                             qemu_log("RFI %d is illegal\n", RRR_S);
                             gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
@@ -1195,8 +1205,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
                     case 1: /*SIMCALL*/
                         if (semihosting_enabled) {
-                            gen_check_privilege(dc);
-                            gen_helper_simcall(cpu_env);
+                            if (gen_check_privilege(dc)) {
+                                gen_helper_simcall(cpu_env);
+                            }
                         } else {
                             qemu_log("SIMCALL but semihosting is disabled\n");
                             gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
@@ -1211,19 +1222,21 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
                 case 6: /*RSILx*/
                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
-                    gen_check_privilege(dc);
-                    gen_window_check1(dc, RRR_T);
-                    tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
-                    tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
-                    tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
-                    gen_helper_check_interrupts(cpu_env);
-                    gen_jumpi_check_loop_end(dc, 0);
+                    if (gen_check_privilege(dc) &&
+                        gen_window_check1(dc, RRR_T)) {
+                        tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
+                        tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
+                        tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
+                        gen_helper_check_interrupts(cpu_env);
+                        gen_jumpi_check_loop_end(dc, 0);
+                    }
                     break;
 
                 case 7: /*WAITIx*/
                     HAS_OPTION(XTENSA_OPTION_INTERRUPT);
-                    gen_check_privilege(dc);
-                    gen_waiti(dc, RRR_S);
+                    if (gen_check_privilege(dc)) {
+                        gen_waiti(dc, RRR_S);
+                    }
                     break;
 
                 case 8: /*ANY4p*/
@@ -1259,35 +1272,39 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 1: /*AND*/
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
+                    tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                }
                 break;
 
             case 2: /*OR*/
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
+                    tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                }
                 break;
 
             case 3: /*XOR*/
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
+                    tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                }
                 break;
 
             case 4: /*ST1*/
                 switch (RRR_R) {
                 case 0: /*SSR*/
-                    gen_window_check1(dc, RRR_S);
-                    gen_right_shift_sar(dc, cpu_R[RRR_S]);
+                    if (gen_window_check1(dc, RRR_S)) {
+                        gen_right_shift_sar(dc, cpu_R[RRR_S]);
+                    }
                     break;
 
                 case 1: /*SSL*/
-                    gen_window_check1(dc, RRR_S);
-                    gen_left_shift_sar(dc, cpu_R[RRR_S]);
+                    if (gen_window_check1(dc, RRR_S)) {
+                        gen_left_shift_sar(dc, cpu_R[RRR_S]);
+                    }
                     break;
 
                 case 2: /*SSA8L*/
-                    gen_window_check1(dc, RRR_S);
-                    {
+                    if (gen_window_check1(dc, RRR_S)) {
                         TCGv_i32 tmp = tcg_temp_new_i32();
                         tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
                         gen_right_shift_sar(dc, tmp);
@@ -1296,8 +1313,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                     break;
 
                 case 3: /*SSA8B*/
-                    gen_window_check1(dc, RRR_S);
-                    {
+                    if (gen_window_check1(dc, RRR_S)) {
                         TCGv_i32 tmp = tcg_temp_new_i32();
                         tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
                         gen_left_shift_sar(dc, tmp);
@@ -1324,8 +1340,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
                 case 8: /*ROTWw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                    gen_check_privilege(dc);
-                    {
+                    if (gen_check_privilege(dc)) {
                         TCGv_i32 tmp = tcg_const_i32(
                                 RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
                         gen_helper_rotw(cpu_env, tmp);
@@ -1337,14 +1352,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
                 case 14: /*NSAu*/
                     HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);
-                    gen_window_check2(dc, RRR_S, RRR_T);
-                    gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);
+                    if (gen_window_check2(dc, RRR_S, RRR_T)) {
+                        gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);
+                    }
                     break;
 
                 case 15: /*NSAUu*/
                     HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);
-                    gen_window_check2(dc, RRR_S, RRR_T);
-                    gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);
+                    if (gen_window_check2(dc, RRR_S, RRR_T)) {
+                        gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);
+                    }
                     break;
 
                 default: /*reserved*/
@@ -1358,9 +1375,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                         XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |
                         XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
                         XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION));
-                gen_check_privilege(dc);
-                gen_window_check2(dc, RRR_S, RRR_T);
-                {
+                if (gen_check_privilege(dc) &&
+                    gen_window_check2(dc, RRR_S, RRR_T)) {
                     TCGv_i32 dtlb = tcg_const_i32((RRR_R & 8) != 0);
 
                     switch (RRR_R & 7) {
@@ -1403,7 +1419,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 6: /*RT0*/
-                gen_window_check2(dc, RRR_R, RRR_T);
+                if (!gen_window_check2(dc, RRR_R, RRR_T)) {
+                    break;
+                }
                 switch (RRR_S) {
                 case 0: /*NEG*/
                     tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
@@ -1433,15 +1451,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 8: /*ADD*/
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
+                    tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                }
                 break;
 
             case 9: /*ADD**/
             case 10:
             case 11:
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                {
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);
                     tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
@@ -1450,15 +1468,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 12: /*SUB*/
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
+                    tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
+                }
                 break;
 
             case 13: /*SUB**/
             case 14:
             case 15:
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                {
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);
                     tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
@@ -1472,31 +1490,32 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             switch (OP2) {
             case 0: /*SLLI*/
             case 1:
-                gen_window_check2(dc, RRR_R, RRR_S);
-                tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],
-                        32 - (RRR_T | ((OP2 & 1) << 4)));
+                if (gen_window_check2(dc, RRR_R, RRR_S)) {
+                    tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],
+                                     32 - (RRR_T | ((OP2 & 1) << 4)));
+                }
                 break;
 
             case 2: /*SRAI*/
             case 3:
-                gen_window_check2(dc, RRR_R, RRR_T);
-                tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],
-                        RRR_S | ((OP2 & 1) << 4));
+                if (gen_window_check2(dc, RRR_R, RRR_T)) {
+                    tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],
+                                     RRR_S | ((OP2 & 1) << 4));
+                }
                 break;
 
             case 4: /*SRLI*/
-                gen_window_check2(dc, RRR_R, RRR_T);
-                tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);
+                if (gen_window_check2(dc, RRR_R, RRR_T)) {
+                    tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);
+                }
                 break;
 
             case 6: /*XSR*/
-                if (gen_check_sr(dc, RSR_SR, SR_X)) {
+                if (gen_check_sr(dc, RSR_SR, SR_X) &&
+                    (RSR_SR < 64 || gen_check_privilege(dc)) &&
+                    gen_window_check1(dc, RRR_T)) {
                     TCGv_i32 tmp = tcg_temp_new_i32();
 
-                    if (RSR_SR >= 64) {
-                        gen_check_privilege(dc);
-                    }
-                    gen_window_check1(dc, RRR_T);
                     tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
                     gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
@@ -1520,8 +1539,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 #define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
 
             case 8: /*SRC*/
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                {
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
                     TCGv_i64 v = tcg_temp_new_i64();
                     tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
                     gen_shift(shr);
@@ -1529,7 +1547,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 9: /*SRL*/
-                gen_window_check2(dc, RRR_R, RRR_T);
+                if (!gen_window_check2(dc, RRR_R, RRR_T)) {
+                    break;
+                }
                 if (dc->sar_5bit) {
                     tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
                 } else {
@@ -1540,7 +1560,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 10: /*SLL*/
-                gen_window_check2(dc, RRR_R, RRR_S);
+                if (!gen_window_check2(dc, RRR_R, RRR_S)) {
+                    break;
+                }
                 if (dc->sar_m32_5bit) {
                     tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32);
                 } else {
@@ -1555,7 +1577,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 11: /*SRA*/
-                gen_window_check2(dc, RRR_R, RRR_T);
+                if (!gen_window_check2(dc, RRR_R, RRR_T)) {
+                    break;
+                }
                 if (dc->sar_5bit) {
                     tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
                 } else {
@@ -1569,8 +1593,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 12: /*MUL16U*/
                 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                {
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
                     TCGv_i32 v1 = tcg_temp_new_i32();
                     TCGv_i32 v2 = tcg_temp_new_i32();
                     tcg_gen_ext16u_i32(v1, cpu_R[RRR_S]);
@@ -1583,8 +1606,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 13: /*MUL16S*/
                 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                {
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
                     TCGv_i32 v1 = tcg_temp_new_i32();
                     TCGv_i32 v2 = tcg_temp_new_i32();
                     tcg_gen_ext16s_i32(v1, cpu_R[RRR_S]);
@@ -1602,8 +1624,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             break;
 
         case 2: /*RST2*/
-            if (OP2 >= 8) {
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
+            if (OP2 >= 8 && !gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
+                break;
             }
 
             if (OP2 >= 12) {
@@ -1715,29 +1737,24 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         case 3: /*RST3*/
             switch (OP2) {
             case 0: /*RSR*/
-                if (gen_check_sr(dc, RSR_SR, SR_R)) {
-                    if (RSR_SR >= 64) {
-                        gen_check_privilege(dc);
-                    }
-                    gen_window_check1(dc, RRR_T);
+                if (gen_check_sr(dc, RSR_SR, SR_R) &&
+                    (RSR_SR < 64 || gen_check_privilege(dc)) &&
+                    gen_window_check1(dc, RRR_T)) {
                     gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
                 }
                 break;
 
             case 1: /*WSR*/
-                if (gen_check_sr(dc, RSR_SR, SR_W)) {
-                    if (RSR_SR >= 64) {
-                        gen_check_privilege(dc);
-                    }
-                    gen_window_check1(dc, RRR_T);
+                if (gen_check_sr(dc, RSR_SR, SR_W) &&
+                    (RSR_SR < 64 || gen_check_privilege(dc)) &&
+                    gen_window_check1(dc, RRR_T)) {
                     gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
                 }
                 break;
 
             case 2: /*SEXTu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP_SEXT);
-                gen_window_check2(dc, RRR_R, RRR_S);
-                {
+                if (gen_window_check2(dc, RRR_R, RRR_S)) {
                     int shift = 24 - RRR_T;
 
                     if (shift == 24) {
@@ -1755,8 +1772,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 3: /*CLAMPSu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP_CLAMPS);
-                gen_window_check2(dc, RRR_R, RRR_S);
-                {
+                if (gen_window_check2(dc, RRR_R, RRR_S)) {
                     TCGv_i32 tmp1 = tcg_temp_new_i32();
                     TCGv_i32 tmp2 = tcg_temp_new_i32();
                     TCGv_i32 zero = tcg_const_i32(0);
@@ -1781,8 +1797,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 6: /*MINUu*/
             case 7: /*MAXUu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP_MINMAX);
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                {
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
                     static const TCGCond cond[] = {
                         TCG_COND_LE,
                         TCG_COND_GE,
@@ -1799,8 +1814,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 9: /*MOVNEZ*/
             case 10: /*MOVLTZ*/
             case 11: /*MOVGEZ*/
-                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
-                {
+                if (gen_window_check3(dc, RRR_R, RRR_S, RRR_T)) {
                     static const TCGCond cond[] = {
                         TCG_COND_EQ,
                         TCG_COND_NE,
@@ -1818,8 +1832,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 12: /*MOVFp*/
             case 13: /*MOVTp*/
                 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
-                gen_window_check2(dc, RRR_R, RRR_S);
-                {
+                if (gen_window_check2(dc, RRR_R, RRR_S)) {
                     TCGv_i32 zero = tcg_const_i32(0);
                     TCGv_i32 tmp = tcg_temp_new_i32();
 
@@ -1834,8 +1847,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 14: /*RUR*/
-                gen_window_check1(dc, RRR_R);
-                {
+                if (gen_window_check1(dc, RRR_R)) {
                     int st = (RRR_S << 4) + RRR_T;
                     if (uregnames[st].name) {
                         tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
@@ -1847,12 +1859,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 15: /*WUR*/
-                gen_window_check1(dc, RRR_T);
-                if (uregnames[RSR_SR].name) {
-                    gen_wur(RSR_SR, cpu_R[RRR_T]);
-                } else {
-                    qemu_log("WUR %d not implemented, ", RSR_SR);
-                    TBD();
+                if (gen_window_check1(dc, RRR_T)) {
+                    if (uregnames[RSR_SR].name) {
+                        gen_wur(RSR_SR, cpu_R[RRR_T]);
+                    } else {
+                        qemu_log("WUR %d not implemented, ", RSR_SR);
+                        TBD();
+                    }
                 }
                 break;
 
@@ -1861,8 +1874,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
         case 4: /*EXTUI*/
         case 5:
-            gen_window_check2(dc, RRR_R, RRR_T);
-            {
+            if (gen_window_check2(dc, RRR_R, RRR_T)) {
                 int shiftimm = RRR_S | ((OP1 & 1) << 4);
                 int maskimm = (1 << (OP2 + 1)) - 1;
 
@@ -1888,9 +1900,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 4: /*SSXf*/
             case 5: /*SSXUf*/
                 HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
-                gen_window_check2(dc, RRR_S, RRR_T);
-                gen_check_cpenable(dc, 0);
-                {
+                if (gen_window_check2(dc, RRR_S, RRR_T) &&
+                    gen_check_cpenable(dc, 0)) {
                     TCGv_i32 addr = tcg_temp_new_i32();
                     tcg_gen_add_i32(addr, cpu_R[RRR_S], cpu_R[RRR_T]);
                     gen_load_store_alignment(dc, 2, addr, false);
@@ -1913,12 +1924,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             break;
 
         case 9: /*LSC4*/
-            gen_window_check2(dc, RRR_S, RRR_T);
+            if (!gen_window_check2(dc, RRR_S, RRR_T)) {
+                break;
+            }
             switch (OP2) {
             case 0: /*L32E*/
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                gen_check_privilege(dc);
-                {
+                if (gen_check_privilege(dc)) {
                     TCGv_i32 addr = tcg_temp_new_i32();
                     tcg_gen_addi_i32(addr, cpu_R[RRR_S],
                             (0xffffffc0 | (RRR_R << 2)));
@@ -1929,8 +1941,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 4: /*S32E*/
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-                gen_check_privilege(dc);
-                {
+                if (gen_check_privilege(dc)) {
                     TCGv_i32 addr = tcg_temp_new_i32();
                     tcg_gen_addi_i32(addr, cpu_R[RRR_S],
                             (0xffffffc0 | (RRR_R << 2)));
@@ -1949,33 +1960,40 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
             switch (OP2) {
             case 0: /*ADD.Sf*/
-                gen_check_cpenable(dc, 0);
-                gen_helper_add_s(cpu_FR[RRR_R], cpu_env,
-                        cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                if (gen_check_cpenable(dc, 0)) {
+                    gen_helper_add_s(cpu_FR[RRR_R], cpu_env,
+                                     cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                }
                 break;
 
             case 1: /*SUB.Sf*/
-                gen_check_cpenable(dc, 0);
-                gen_helper_sub_s(cpu_FR[RRR_R], cpu_env,
-                        cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                if (gen_check_cpenable(dc, 0)) {
+                    gen_helper_sub_s(cpu_FR[RRR_R], cpu_env,
+                                     cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                }
                 break;
 
             case 2: /*MUL.Sf*/
-                gen_check_cpenable(dc, 0);
-                gen_helper_mul_s(cpu_FR[RRR_R], cpu_env,
-                        cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                if (gen_check_cpenable(dc, 0)) {
+                    gen_helper_mul_s(cpu_FR[RRR_R], cpu_env,
+                                     cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                }
                 break;
 
             case 4: /*MADD.Sf*/
-                gen_check_cpenable(dc, 0);
-                gen_helper_madd_s(cpu_FR[RRR_R], cpu_env,
-                        cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                if (gen_check_cpenable(dc, 0)) {
+                    gen_helper_madd_s(cpu_FR[RRR_R], cpu_env,
+                                      cpu_FR[RRR_R], cpu_FR[RRR_S],
+                                      cpu_FR[RRR_T]);
+                }
                 break;
 
             case 5: /*MSUB.Sf*/
-                gen_check_cpenable(dc, 0);
-                gen_helper_msub_s(cpu_FR[RRR_R], cpu_env,
-                        cpu_FR[RRR_R], cpu_FR[RRR_S], cpu_FR[RRR_T]);
+                if (gen_check_cpenable(dc, 0)) {
+                    gen_helper_msub_s(cpu_FR[RRR_R], cpu_env,
+                                      cpu_FR[RRR_R], cpu_FR[RRR_S],
+                                      cpu_FR[RRR_T]);
+                }
                 break;
 
             case 8: /*ROUND.Sf*/
@@ -1983,9 +2001,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 10: /*FLOOR.Sf*/
             case 11: /*CEIL.Sf*/
             case 14: /*UTRUNC.Sf*/
-                gen_window_check1(dc, RRR_R);
-                gen_check_cpenable(dc, 0);
-                {
+                if (gen_window_check1(dc, RRR_R) &&
+                    gen_check_cpenable(dc, 0)) {
                     static const unsigned rounding_mode_const[] = {
                         float_round_nearest_even,
                         float_round_to_zero,
@@ -2012,9 +2029,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 12: /*FLOAT.Sf*/
             case 13: /*UFLOAT.Sf*/
-                gen_window_check1(dc, RRR_S);
-                gen_check_cpenable(dc, 0);
-                {
+                if (gen_window_check1(dc, RRR_S) &&
+                    gen_check_cpenable(dc, 0)) {
                     TCGv_i32 scale = tcg_const_i32(-RRR_T);
 
                     if (OP2 == 13) {
@@ -2031,30 +2047,35 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 15: /*FP1OP*/
                 switch (RRR_T) {
                 case 0: /*MOV.Sf*/
-                    gen_check_cpenable(dc, 0);
-                    tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
+                    if (gen_check_cpenable(dc, 0)) {
+                        tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_FR[RRR_S]);
+                    }
                     break;
 
                 case 1: /*ABS.Sf*/
-                    gen_check_cpenable(dc, 0);
-                    gen_helper_abs_s(cpu_FR[RRR_R], cpu_FR[RRR_S]);
+                    if (gen_check_cpenable(dc, 0)) {
+                        gen_helper_abs_s(cpu_FR[RRR_R], cpu_FR[RRR_S]);
+                    }
                     break;
 
                 case 4: /*RFRf*/
-                    gen_window_check1(dc, RRR_R);
-                    gen_check_cpenable(dc, 0);
-                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_FR[RRR_S]);
+                    if (gen_window_check1(dc, RRR_R) &&
+                        gen_check_cpenable(dc, 0)) {
+                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_FR[RRR_S]);
+                    }
                     break;
 
                 case 5: /*WFRf*/
-                    gen_window_check1(dc, RRR_S);
-                    gen_check_cpenable(dc, 0);
-                    tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_R[RRR_S]);
+                    if (gen_window_check1(dc, RRR_S) &&
+                        gen_check_cpenable(dc, 0)) {
+                        tcg_gen_mov_i32(cpu_FR[RRR_R], cpu_R[RRR_S]);
+                    }
                     break;
 
                 case 6: /*NEG.Sf*/
-                    gen_check_cpenable(dc, 0);
-                    gen_helper_neg_s(cpu_FR[RRR_R], cpu_FR[RRR_S]);
+                    if (gen_check_cpenable(dc, 0)) {
+                        gen_helper_neg_s(cpu_FR[RRR_R], cpu_FR[RRR_S]);
+                    }
                     break;
 
                 default: /*reserved*/
@@ -2074,11 +2095,12 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
 #define gen_compare(rel, br, a, b) \
     do { \
-        TCGv_i32 bit = tcg_const_i32(1 << br); \
-        \
-        gen_check_cpenable(dc, 0); \
-        gen_helper_##rel(cpu_env, bit, cpu_FR[a], cpu_FR[b]); \
-        tcg_temp_free(bit); \
+        if (gen_check_cpenable(dc, 0)) { \
+            TCGv_i32 bit = tcg_const_i32(1 << br); \
+            \
+            gen_helper_##rel(cpu_env, bit, cpu_FR[a], cpu_FR[b]); \
+            tcg_temp_free(bit); \
+        } \
     } while (0)
 
             switch (OP2) {
@@ -2116,9 +2138,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 9: /*MOVNEZ.Sf*/
             case 10: /*MOVLTZ.Sf*/
             case 11: /*MOVGEZ.Sf*/
-                gen_window_check1(dc, RRR_T);
-                gen_check_cpenable(dc, 0);
-                {
+                if (gen_window_check1(dc, RRR_T) &&
+                    gen_check_cpenable(dc, 0)) {
                     static const TCGCond cond[] = {
                         TCG_COND_EQ,
                         TCG_COND_NE,
@@ -2136,8 +2157,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 12: /*MOVF.Sf*/
             case 13: /*MOVT.Sf*/
                 HAS_OPTION(XTENSA_OPTION_BOOLEAN);
-                gen_check_cpenable(dc, 0);
-                {
+                if (gen_check_cpenable(dc, 0)) {
                     TCGv_i32 zero = tcg_const_i32(0);
                     TCGv_i32 tmp = tcg_temp_new_i32();
 
@@ -2168,8 +2188,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         break;
 
     case 1: /*L32R*/
-        gen_window_check1(dc, RRR_T);
-        {
+        if (gen_window_check1(dc, RRR_T)) {
             TCGv_i32 tmp = tcg_const_i32(
                     ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
                      0 : ((dc->pc + 3) & ~3)) +
@@ -2185,14 +2204,16 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
     case 2: /*LSAI*/
 #define gen_load_store(type, shift) do { \
-            TCGv_i32 addr = tcg_temp_new_i32(); \
-            gen_window_check2(dc, RRI8_S, RRI8_T); \
-            tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
-            if (shift) { \
-                gen_load_store_alignment(dc, shift, addr, false); \
+            if (gen_window_check2(dc, RRI8_S, RRI8_T)) { \
+                TCGv_i32 addr = tcg_temp_new_i32(); \
+                \
+                tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
+                if (shift) { \
+                    gen_load_store_alignment(dc, shift, addr, false); \
+                } \
+                tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
+                tcg_temp_free(addr); \
             } \
-            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
-            tcg_temp_free(addr); \
         } while (0)
 
         switch (RRI8_R) {
@@ -2221,14 +2242,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             break;
 
 #define gen_dcache_hit_test(w, shift) do { \
-            TCGv_i32 addr = tcg_temp_new_i32(); \
-            TCGv_i32 res = tcg_temp_new_i32(); \
-            gen_window_check1(dc, RRI##w##_S); \
-            tcg_gen_addi_i32(addr, cpu_R[RRI##w##_S], \
-                             RRI##w##_IMM##w << shift); \
-            tcg_gen_qemu_ld8u(res, addr, dc->cring); \
-            tcg_temp_free(addr); \
-            tcg_temp_free(res); \
+            if (gen_window_check1(dc, RRI##w##_S)) { \
+                TCGv_i32 addr = tcg_temp_new_i32(); \
+                TCGv_i32 res = tcg_temp_new_i32(); \
+                tcg_gen_addi_i32(addr, cpu_R[RRI##w##_S], \
+                                 RRI##w##_IMM##w << shift); \
+                tcg_gen_qemu_ld8u(res, addr, dc->cring); \
+                tcg_temp_free(addr); \
+                tcg_temp_free(res); \
+            } \
         } while (0)
 
 #define gen_dcache_hit_test4() gen_dcache_hit_test(4, 4)
@@ -2265,45 +2287,52 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 6: /*DHIc*/
-                gen_check_privilege(dc);
-                gen_dcache_hit_test8();
+                if (gen_check_privilege(dc)) {
+                    gen_dcache_hit_test8();
+                }
                 break;
 
             case 7: /*DIIc*/
-                gen_check_privilege(dc);
-                gen_window_check1(dc, RRI8_S);
+                if (gen_check_privilege(dc)) {
+                    gen_window_check1(dc, RRI8_S);
+                }
                 break;
 
             case 8: /*DCEc*/
                 switch (OP1) {
                 case 0: /*DPFLl*/
                     HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
-                    gen_check_privilege(dc);
-                    gen_dcache_hit_test4();
+                    if (gen_check_privilege(dc)) {
+                        gen_dcache_hit_test4();
+                    }
                     break;
 
                 case 2: /*DHUl*/
                     HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
-                    gen_check_privilege(dc);
-                    gen_dcache_hit_test4();
+                    if (gen_check_privilege(dc)) {
+                        gen_dcache_hit_test4();
+                    }
                     break;
 
                 case 3: /*DIUl*/
                     HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
-                    gen_check_privilege(dc);
-                    gen_window_check1(dc, RRI4_S);
+                    if (gen_check_privilege(dc)) {
+                        gen_window_check1(dc, RRI4_S);
+                    }
                     break;
 
                 case 4: /*DIWBc*/
                     HAS_OPTION(XTENSA_OPTION_DCACHE);
-                    gen_check_privilege(dc);
-                    gen_window_check1(dc, RRI4_S);
+                    if (gen_check_privilege(dc)) {
+                        gen_window_check1(dc, RRI4_S);
+                    }
                     break;
 
                 case 5: /*DIWBIc*/
                     HAS_OPTION(XTENSA_OPTION_DCACHE);
-                    gen_check_privilege(dc);
-                    gen_window_check1(dc, RRI4_S);
+                    if (gen_check_privilege(dc)) {
+                        gen_window_check1(dc, RRI4_S);
+                    }
                     break;
 
                 default: /*reserved*/
@@ -2318,13 +2347,14 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 #undef gen_dcache_hit_test8
 
 #define gen_icache_hit_test(w, shift) do { \
-            TCGv_i32 addr = tcg_temp_new_i32(); \
-            gen_window_check1(dc, RRI##w##_S); \
-            tcg_gen_movi_i32(cpu_pc, dc->pc); \
-            tcg_gen_addi_i32(addr, cpu_R[RRI##w##_S], \
-                             RRI##w##_IMM##w << shift); \
-            gen_helper_itlb_hit_test(cpu_env, addr); \
-            tcg_temp_free(addr); \
+            if (gen_window_check1(dc, RRI##w##_S)) { \
+                TCGv_i32 addr = tcg_temp_new_i32(); \
+                tcg_gen_movi_i32(cpu_pc, dc->pc); \
+                tcg_gen_addi_i32(addr, cpu_R[RRI##w##_S], \
+                                 RRI##w##_IMM##w << shift); \
+                gen_helper_itlb_hit_test(cpu_env, addr); \
+                tcg_temp_free(addr); \
+            }\
         } while (0)
 
 #define gen_icache_hit_test4() gen_icache_hit_test(4, 4)
@@ -2339,20 +2369,23 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 switch (OP1) {
                 case 0: /*IPFLl*/
                     HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
-                    gen_check_privilege(dc);
-                    gen_icache_hit_test4();
+                    if (gen_check_privilege(dc)) {
+                        gen_icache_hit_test4();
+                    }
                     break;
 
                 case 2: /*IHUl*/
                     HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
-                    gen_check_privilege(dc);
-                    gen_icache_hit_test4();
+                    if (gen_check_privilege(dc)) {
+                        gen_icache_hit_test4();
+                    }
                     break;
 
                 case 3: /*IIUl*/
                     HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
-                    gen_check_privilege(dc);
-                    gen_window_check1(dc, RRI4_S);
+                    if (gen_check_privilege(dc)) {
+                        gen_window_check1(dc, RRI4_S);
+                    }
                     break;
 
                 default: /*reserved*/
@@ -2368,8 +2401,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 15: /*IIIc*/
                 HAS_OPTION(XTENSA_OPTION_ICACHE);
-                gen_check_privilege(dc);
-                gen_window_check1(dc, RRI8_S);
+                if (gen_check_privilege(dc)) {
+                    gen_window_check1(dc, RRI8_S);
+                }
                 break;
 
             default: /*reserved*/
@@ -2388,19 +2422,21 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 #undef gen_load_store
 
         case 10: /*MOVI*/
-            gen_window_check1(dc, RRI8_T);
-            tcg_gen_movi_i32(cpu_R[RRI8_T],
-                    RRI8_IMM8 | (RRI8_S << 8) |
-                    ((RRI8_S & 0x8) ? 0xfffff000 : 0));
+            if (gen_window_check1(dc, RRI8_T)) {
+                tcg_gen_movi_i32(cpu_R[RRI8_T],
+                                 RRI8_IMM8 | (RRI8_S << 8) |
+                                 ((RRI8_S & 0x8) ? 0xfffff000 : 0));
+            }
             break;
 
 #define gen_load_store_no_hw_align(type) do { \
-            TCGv_i32 addr = tcg_temp_local_new_i32(); \
-            gen_window_check2(dc, RRI8_S, RRI8_T); \
-            tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
-            gen_load_store_alignment(dc, 2, addr, true); \
-            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
-            tcg_temp_free(addr); \
+            if (gen_window_check2(dc, RRI8_S, RRI8_T)) { \
+                TCGv_i32 addr = tcg_temp_local_new_i32(); \
+                tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
+                gen_load_store_alignment(dc, 2, addr, true); \
+                tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
+                tcg_temp_free(addr); \
+            } \
         } while (0)
 
         case 11: /*L32AIy*/
@@ -2409,19 +2445,21 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             break;
 
         case 12: /*ADDI*/
-            gen_window_check2(dc, RRI8_S, RRI8_T);
-            tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);
+            if (gen_window_check2(dc, RRI8_S, RRI8_T)) {
+                tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);
+            }
             break;
 
         case 13: /*ADDMI*/
-            gen_window_check2(dc, RRI8_S, RRI8_T);
-            tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8);
+            if (gen_window_check2(dc, RRI8_S, RRI8_T)) {
+                tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S],
+                                 RRI8_IMM8_SE << 8);
+            }
             break;
 
         case 14: /*S32C1Iy*/
             HAS_OPTION(XTENSA_OPTION_CONDITIONAL_STORE);
-            gen_window_check2(dc, RRI8_S, RRI8_T);
-            {
+            if (gen_window_check2(dc, RRI8_S, RRI8_T)) {
                 int label = gen_new_label();
                 TCGv_i32 tmp = tcg_temp_local_new_i32();
                 TCGv_i32 addr = tcg_temp_local_new_i32();
@@ -2466,9 +2504,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         case 8: /*LSIUf*/
         case 12: /*SSIUf*/
             HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
-            gen_window_check1(dc, RRI8_S);
-            gen_check_cpenable(dc, 0);
-            {
+            if (gen_window_check1(dc, RRI8_S) &&
+                gen_check_cpenable(dc, 0)) {
                 TCGv_i32 addr = tcg_temp_new_i32();
                 tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
                 gen_load_store_alignment(dc, 2, addr, false);
@@ -2532,20 +2569,23 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             }
 
             if (op != MAC16_NONE) {
-                if (!is_m1_sr) {
-                    gen_window_check1(dc, RRR_S);
+                if (!is_m1_sr && !gen_window_check1(dc, RRR_S)) {
+                    break;
                 }
-                if (!is_m2_sr) {
-                    gen_window_check1(dc, RRR_T);
+                if (!is_m2_sr && !gen_window_check1(dc, RRR_T)) {
+                    break;
                 }
             }
 
+            if (ld_offset && !gen_window_check1(dc, RRR_S)) {
+                break;
+            }
+
             {
                 TCGv_i32 vaddr = tcg_temp_new_i32();
                 TCGv_i32 mem32 = tcg_temp_new_i32();
 
                 if (ld_offset) {
-                    gen_window_check1(dc, RRR_S);
                     tcg_gen_addi_i32(vaddr, cpu_R[RRR_S], ld_offset);
                     gen_load_store_alignment(dc, 2, vaddr, false);
                     tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
@@ -2609,9 +2649,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
-            gen_window_check1(dc, CALL_N << 2);
-            gen_callwi(dc, CALL_N,
-                    (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
+            if (gen_window_check1(dc, CALL_N << 2)) {
+                gen_callwi(dc, CALL_N,
+                           (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
+            }
             break;
         }
         break;
@@ -2623,8 +2664,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             break;
 
         case 1: /*BZ*/
-            gen_window_check1(dc, BRI12_S);
-            {
+            if (gen_window_check1(dc, BRI12_S)) {
                 static const TCGCond cond[] = {
                     TCG_COND_EQ, /*BEQZ*/
                     TCG_COND_NE, /*BNEZ*/
@@ -2638,8 +2678,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             break;
 
         case 2: /*BI0*/
-            gen_window_check1(dc, BRI8_S);
-            {
+            if (gen_window_check1(dc, BRI8_S)) {
                 static const TCGCond cond[] = {
                     TCG_COND_EQ, /*BEQI*/
                     TCG_COND_NE, /*BNEI*/
@@ -2689,8 +2728,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 case 9: /*LOOPNEZ*/
                 case 10: /*LOOPGTZ*/
                     HAS_OPTION(XTENSA_OPTION_LOOP);
-                    gen_window_check1(dc, RRI8_S);
-                    {
+                    if (gen_window_check1(dc, RRI8_S)) {
                         uint32_t lend = dc->pc + RRI8_IMM8 + 4;
                         TCGv_i32 tmp = tcg_const_i32(lend);
 
@@ -2721,9 +2759,11 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 2: /*BLTUI*/
             case 3: /*BGEUI*/
-                gen_window_check1(dc, BRI8_S);
-                gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
-                        cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);
+                if (gen_window_check1(dc, BRI8_S)) {
+                    gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
+                                cpu_R[BRI8_S], B4CONSTU[BRI8_R],
+                                4 + BRI8_IMM8_SE);
+                }
                 break;
             }
             break;
@@ -2737,8 +2777,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             switch (RRI8_R & 7) {
             case 0: /*BNONE*/ /*BANY*/
-                gen_window_check2(dc, RRI8_S, RRI8_T);
-                {
+                if (gen_window_check2(dc, RRI8_S, RRI8_T)) {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
                     gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
@@ -2749,8 +2788,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
             case 1: /*BEQ*/ /*BNE*/
             case 2: /*BLT*/ /*BGE*/
             case 3: /*BLTU*/ /*BGEU*/
-                gen_window_check2(dc, RRI8_S, RRI8_T);
-                {
+                if (gen_window_check2(dc, RRI8_S, RRI8_T)) {
                     static const TCGCond cond[] = {
                         [1] = TCG_COND_EQ,
                         [2] = TCG_COND_LT,
@@ -2765,8 +2803,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 4: /*BALL*/ /*BNALL*/
-                gen_window_check2(dc, RRI8_S, RRI8_T);
-                {
+                if (gen_window_check2(dc, RRI8_S, RRI8_T)) {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
                     gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T],
@@ -2776,8 +2813,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                 break;
 
             case 5: /*BBC*/ /*BBS*/
-                gen_window_check2(dc, RRI8_S, RRI8_T);
-                {
+                if (gen_window_check2(dc, RRI8_S, RRI8_T)) {
 #ifdef TARGET_WORDS_BIGENDIAN
                     TCGv_i32 bit = tcg_const_i32(0x80000000);
 #else
@@ -2799,8 +2835,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 
             case 6: /*BBCI*/ /*BBSI*/
             case 7:
-                gen_window_check1(dc, RRI8_S);
-                {
+                if (gen_window_check1(dc, RRI8_S)) {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -2818,12 +2853,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
         break;
 
 #define gen_narrow_load_store(type) do { \
-            TCGv_i32 addr = tcg_temp_new_i32(); \
-            gen_window_check2(dc, RRRN_S, RRRN_T); \
-            tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
-            gen_load_store_alignment(dc, 2, addr, false); \
-            tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
-            tcg_temp_free(addr); \
+            if (gen_window_check2(dc, RRRN_S, RRRN_T)) { \
+                TCGv_i32 addr = tcg_temp_new_i32(); \
+                tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
+                gen_load_store_alignment(dc, 2, addr, false); \
+                tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
+                tcg_temp_free(addr); \
+            } \
         } while (0)
 
     case 8: /*L32I.Nn*/
@@ -2836,17 +2872,22 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
 #undef gen_narrow_load_store
 
     case 10: /*ADD.Nn*/
-        gen_window_check3(dc, RRRN_R, RRRN_S, RRRN_T);
-        tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
+        if (gen_window_check3(dc, RRRN_R, RRRN_S, RRRN_T)) {
+            tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
+        }
         break;
 
     case 11: /*ADDI.Nn*/
-        gen_window_check2(dc, RRRN_R, RRRN_S);
-        tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);
+        if (gen_window_check2(dc, RRRN_R, RRRN_S)) {
+            tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S],
+                             RRRN_T ? RRRN_T : -1);
+        }
         break;
 
     case 12: /*ST2n*/
-        gen_window_check1(dc, RRRN_S);
+        if (!gen_window_check1(dc, RRRN_S)) {
+            break;
+        }
         if (RRRN_T < 8) { /*MOVI.Nn*/
             tcg_gen_movi_i32(cpu_R[RRRN_S],
                     RRRN_R | (RRRN_T << 4) |
@@ -2862,8 +2903,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
     case 13: /*ST3n*/
         switch (RRRN_R) {
         case 0: /*MOV.Nn*/
-            gen_window_check2(dc, RRRN_S, RRRN_T);
-            tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
+            if (gen_window_check2(dc, RRRN_S, RRRN_T)) {
+                tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
+            }
             break;
 
         case 15: /*S3*/
Signature · 1 line
1.8.1.4
Reviewed-by on the v1 series
#3 lore raw
In reply to Max Filippov
Quoted 9 lines · Max Filippov

Max Filippov (2):
target-xtensa: record available window in TB flags
target-xtensa: don't generate dead code

 target-xtensa/cpu.h       |  12 +
 target-xtensa/helper.h    |   2 +-
 target-xtensa/op_helper.c |  29 +-
 target-xtensa/translate.c | 661 ++++++++++++++++++++++++----------------------
 4 files changed, 363 insertions(+), 341 deletions(-)

Nice improvement.

r~

#4 lore raw
Quoted 11 lines · Richard Henderson
Quoted 9 lines · Max Filippov

Max Filippov (2):
target-xtensa: record available window in TB flags
target-xtensa: don't generate dead code

 target-xtensa/cpu.h       |  12 +
 target-xtensa/helper.h    |   2 +-
 target-xtensa/op_helper.c |  29 +-
 target-xtensa/translate.c | 661 ++++++++++++++++++++++++----------------------
 4 files changed, 363 insertions(+), 341 deletions(-)
Quoted 3 lines

Nice improvement.

Thanks for the review, Richard.

-- Max