See ISA, 4.7.1.3 for details.

Window check is inserted before commands that push "used register
watermark" beyond its current level. Used register watermark is reset on
instructions that change WINDOW_BASE/WINDOW_START SRs.

Signed-off-by: Max Filippov <jcmvb...@gmail.com>
---
 target-xtensa/translate.c |  105 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index ce1fbf6..4df1b57 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -47,6 +47,7 @@ typedef struct DisasContext {
     uint32_t lend;
     int is_jmp;
     int singlestep_enabled;
+    unsigned used_window;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -153,6 +154,11 @@ static void gen_check_interrupts(DisasContext *dc)
     gen_helper_check_interrupts();
 }
 
+static void reset_used_window(DisasContext *dc)
+{
+    dc->used_window = 0;
+}
+
 static void gen_rsr(TCGv_i32 d, int sr)
 {
     if (sregnames[sr]) {
@@ -170,11 +176,19 @@ static void gen_wsr_lend(DisasContext *dc, uint32_t sr, 
TCGv_i32 v)
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     gen_helper_wsr_windowbase(v);
+    reset_used_window(dc);
+}
+
+static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_mov_i32(cpu_SR[sr], v);
+    reset_used_window(dc);
 }
 
 static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_mov_i32(cpu_SR[sr], v);
+    reset_used_window(dc);
     gen_check_interrupts(dc);
 }
 
@@ -194,6 +208,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 
s)
             uint32_t sr, TCGv_i32 v) = {
         [LEND] = gen_wsr_lend,
         [WINDOW_BASE] = gen_wsr_windowbase,
+        [WINDOW_START] = gen_wsr_windowstart,
         [PS] = gen_wsr_ps,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
@@ -333,6 +348,31 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
     tcg_temp_free(intlevel);
 }
 
+static void gen_window_check1(DisasContext *dc, unsigned r1)
+{
+    if (option_enabled(dc, XTENSA_OPTION_WINDOWED_REGISTER) &&
+            r1 / 4 > dc->used_window) {
+        TCGv_i32 pc = tcg_const_i32(dc->pc);
+        TCGv_i32 w = tcg_const_i32(r1 / 4);
+
+        gen_helper_window_check(pc, w);
+
+        tcg_temp_free(w);
+        tcg_temp_free(pc);
+    }
+}
+
+static void gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2)
+{
+    gen_window_check1(dc, r1 > r2 ? r1 : r2);
+}
+
+static void gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
+        unsigned r3)
+{
+    gen_window_check2(dc, r1, r2 > r3 ? r2 : r3);
+}
+
 static void disas_xtensa_insn(DisasContext *dc)
 {
 #define HAS_OPTION(opt) do { \
@@ -453,6 +493,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         switch (CALLX_N) {
                         case 0: /*RET*/
                         case 2: /*JX*/
+                            gen_window_check1(dc, CALLX_S);
                             gen_jump(dc, cpu_R[CALLX_S]);
                             break;
 
@@ -473,6 +514,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                         break;
 
                     case 3: /*CALLX*/
+                        gen_window_check2(dc, CALLX_S, CALLX_N << 2);
                         switch (CALLX_N) {
                         case 0: /*CALLX0*/
                             {
@@ -503,6 +545,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 1: /*MOVSPw*/
                     HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+                    gen_window_check2(dc, RRR_T, RRR_S);
                     {
                         TCGv_i32 pc = tcg_const_i32(dc->pc);
                         gen_helper_movsp(pc);
@@ -640,6 +683,7 @@ static void disas_xtensa_insn(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_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
                     tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS],
@@ -681,24 +725,29 @@ static void disas_xtensa_insn(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]);
                 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]);
                 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]);
                 break;
 
             case 4: /*ST1*/
                 switch (RRR_R) {
                 case 0: /*SSR*/
+                    gen_window_check1(dc, RRR_S);
                     tcg_gen_andi_i32(cpu_SR[SAR], cpu_R[RRR_S], 0x1f);
                     break;
 
                 case 1: /*SSL*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 base = tcg_const_i32(32);
                         TCGv_i32 tmp = tcg_temp_new_i32();
@@ -710,6 +759,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 2: /*SSA8L*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 tmp = tcg_temp_new_i32();
                         tcg_gen_andi_i32(tmp, cpu_R[RRR_S], 0x3);
@@ -719,6 +769,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 3: /*SSA8B*/
+                    gen_window_check1(dc, RRR_S);
                     {
                         TCGv_i32 base = tcg_const_i32(32);
                         TCGv_i32 tmp = tcg_temp_new_i32();
@@ -750,6 +801,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                                 RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
                         gen_helper_rotw(tmp);
                         tcg_temp_free(tmp);
+                        reset_used_window(dc);
                     }
                     break;
 
@@ -760,6 +812,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                 case 15: /*NSAUu*/
                     HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    gen_window_check2(dc, RRR_S, RRR_T);
                     {
 #define gen_bit_bisect(w) do { \
         int label = gen_new_label(); \
@@ -806,6 +859,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 6: /*RT0*/
+                gen_window_check2(dc, RRR_R, RRR_T);
                 switch (RRR_S) {
                 case 0: /*NEG*/
                     tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
@@ -833,12 +887,14 @@ static void disas_xtensa_insn(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]);
                 break;
 
             case 9: /*ADD**/
             case 10:
             case 11:
+                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);
@@ -848,12 +904,14 @@ static void disas_xtensa_insn(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]);
                 break;
 
             case 13: /*SUB**/
             case 14:
             case 15:
+                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);
@@ -868,17 +926,20 @@ static void disas_xtensa_insn(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)));
                 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));
                 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);
                 break;
 
@@ -888,6 +949,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     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(cpu_R[RRR_T], RSR_SR);
                     gen_wsr(dc, RSR_SR, tmp);
@@ -913,6 +975,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 8: /*SRC*/
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
+                    gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                     tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
                     gen_shift(shr);
                 }
@@ -921,6 +984,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 9: /*SRL*/
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
+                    gen_window_check2(dc, RRR_R, RRR_T);
                     tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
                     gen_shift(shr);
                 }
@@ -930,6 +994,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
                     TCGv_i32 s = tcg_const_i32(32);
+                    gen_window_check2(dc, RRR_R, RRR_S);
                     tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
                     tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]);
                     gen_shift_reg(shl, s);
@@ -940,6 +1005,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 11: /*SRA*/
                 {
                     TCGv_i64 v = tcg_temp_new_i64();
+                    gen_window_check2(dc, RRR_R, RRR_T);
                     tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
                     gen_shift(sar);
                 }
@@ -949,6 +1015,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 12: /*MUL16U*/
                 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     TCGv_i32 v1 = tcg_temp_new_i32();
                     TCGv_i32 v2 = tcg_temp_new_i32();
@@ -962,6 +1029,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 13: /*MUL16S*/
                 HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     TCGv_i32 v1 = tcg_temp_new_i32();
                     TCGv_i32 v2 = tcg_temp_new_i32();
@@ -980,6 +1048,8 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 2: /*RST2*/
+            gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
+
             if (_OP2 >= 12) {
                 HAS_OPTION(XTENSA_OPTION_32_BIT_IDIV);
                 int label = gen_new_label();
@@ -1047,6 +1117,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
+                gen_window_check1(dc, RRR_T);
                 gen_rsr(cpu_R[RRR_T], RSR_SR);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -1057,6 +1128,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 if (RSR_SR >= 64) {
                     gen_check_privilege(dc);
                 }
+                gen_window_check1(dc, RRR_T);
                 gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
                 if (!sregnames[RSR_SR]) {
                     TBD();
@@ -1065,6 +1137,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 2: /*SEXTu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                gen_window_check2(dc, RRR_R, RRR_S);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 24 - RRR_T);
@@ -1075,6 +1148,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 3: /*CLAMPSu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                gen_window_check2(dc, RRR_R, RRR_S);
                 {
                     TCGv_i32 tmp1 = tcg_temp_new_i32();
                     TCGv_i32 tmp2 = tcg_temp_new_i32();
@@ -1102,6 +1176,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 6: /*MINUu*/
             case 7: /*MAXUu*/
                 HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     static const TCGCond cond[] = {
                         TCG_COND_LE,
@@ -1129,6 +1204,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 9: /*MOVNEZ*/
             case 10: /*MOVLTZ*/
             case 11: /*MOVGEZ*/
+                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     static const TCGCond cond[] = {
                         TCG_COND_NE,
@@ -1154,6 +1230,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 14: /*RUR*/
+                gen_window_check1(dc, RRR_R);
                 {
                     int st = (RRR_S << 4) + RRR_T;
                     if (uregnames[st]) {
@@ -1166,6 +1243,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 15: /*WUR*/
+                gen_window_check1(dc, RRR_T);
                 {
                     if (uregnames[RSR_SR]) {
                         tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
@@ -1181,6 +1259,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
         case 4: /*EXTUI*/
         case 5:
+            gen_window_check2(dc, RRR_R, RRR_T);
             {
                 int shiftimm = RRR_S | (_OP1 << 4);
                 int maskimm = (1 << (_OP2 + 1)) - 1;
@@ -1206,6 +1285,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 9: /*LSC4*/
+            gen_window_check2(dc, RRR_S, RRR_T);
             switch (_OP2) {
             case 0: /*L32E*/
                 HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
@@ -1256,6 +1336,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         break;
 
     case 1: /*L32R*/
+        gen_window_check1(dc, RRR_T);
         {
             TCGv_i32 tmp = tcg_temp_local_new_i32();
 
@@ -1284,6 +1365,7 @@ static void disas_xtensa_insn(DisasContext *dc)
     case 2: /*LSAI*/
 #define gen_load_store(type, shift) 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 << shift); \
             if (shift) { \
                 gen_load_store_alignment(dc, shift, addr); \
@@ -1419,6 +1501,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         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));
@@ -1430,15 +1513,18 @@ static void disas_xtensa_insn(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);
             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);
             break;
 
         case 14: /*S32C1Iy*/
             HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
+            gen_window_check2(dc, RRI8_S, RRI8_T);
             {
                 int label = gen_new_label();
                 TCGv_i32 tmp = tcg_temp_local_new_i32();
@@ -1491,6 +1577,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         case 2: /*CALL8w*/
         case 3: /*CALL12w*/
             HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
+            gen_window_check1(dc, CALL_N << 2);
             {
                 TCGv_i32 tmp = tcg_const_i32(
                         (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4);
@@ -1508,6 +1595,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 1: /*BZ*/
+            gen_window_check1(dc, BRI12_S);
             {
                 int label = gen_new_label();
                 int inv = BRI12_M & 1;
@@ -1530,6 +1618,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 2: /*BI0*/
+            gen_window_check1(dc, BRI8_S);
             {
                 int label = gen_new_label();
                 int inv = BRI8_M & 1;
@@ -1563,6 +1652,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     tcg_temp_free(imm);
                     tcg_temp_free(s);
                     tcg_temp_free(pc);
+                    reset_used_window(dc);
                 }
                 break;
 
@@ -1582,6 +1672,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 case 9: /*LOOPNEZ*/
                 case 10: /*LOOPGTZ*/
                     HAS_OPTION(XTENSA_OPTION_LOOP);
+                    gen_window_check1(dc, RRI8_S);
                     {
                         uint32_t lend = dc->pc + RRI8_IMM8 + 4;
                         TCGv_i32 tmp = tcg_const_i32(lend);
@@ -1613,6 +1704,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 2: /*BLTUI*/
             case 3: /*BGEUI*/
+                gen_window_check1(dc, BRI8_S);
                 {
                     int label = gen_new_label();
                     int inv = BRI8_M & 1;
@@ -1638,6 +1730,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             switch (RRI8_R & 7) {
             case 0: /*BNONE*/
+                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]);
@@ -1648,21 +1741,25 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 1: /*BEQ*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 tcg_gen_brcond_i32(inv ? TCG_COND_EQ : TCG_COND_NE,
                         cpu_R[RRI8_S], cpu_R[RRI8_T], label);
                 break;
 
             case 2: /*BLT*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 tcg_gen_brcond_i32(inv ? TCG_COND_LT : TCG_COND_GE,
                         cpu_R[RRI8_S], cpu_R[RRI8_T], label);
                 break;
 
             case 3: /*BLTU*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 tcg_gen_brcond_i32(inv ? TCG_COND_LTU : TCG_COND_GEU,
                         cpu_R[RRI8_S], cpu_R[RRI8_T], label);
                 break;
 
             case 4: /*BALL*/
+                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]);
@@ -1673,6 +1770,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 5: /*BBC*/
+                gen_window_check2(dc, RRI8_S, RRI8_T);
                 {
                     TCGv_i32 bit = tcg_const_i32(1);
                     TCGv_i32 tmp = tcg_temp_new_i32();
@@ -1688,6 +1786,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 6: /*BBCI*/
             case 7:
+                gen_window_check1(dc, RRI8_S);
                 {
                     TCGv_i32 tmp = tcg_temp_new_i32();
                     tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
@@ -1707,6 +1806,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 #define gen_narrow_load_store(type) do { \
             TCGv_i32 addr = tcg_temp_local_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); \
             tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, 0); \
@@ -1723,14 +1823,17 @@ static void disas_xtensa_insn(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]);
         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);
         break;
 
     case 12: /*ST2n*/
+        gen_window_check1(dc, RRRN_S);
         if (RRRN_T < 8) { /*MOVI.Nn*/
             tcg_gen_movi_i32(cpu_R[RRRN_S],
                     RRRN_R | (RRRN_T << 4) |
@@ -1750,6 +1853,7 @@ static void disas_xtensa_insn(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]);
             break;
 
@@ -1868,6 +1972,7 @@ static void gen_intermediate_code_internal(
     dc.pc = env->pc;
     dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
+    reset_used_window(&dc);
 
     gen_icount_start();
 
-- 
1.7.3.4


Reply via email to