]> Git Repo - qemu.git/blobdiff - target-xtensa/translate.c
s390: make kvm_stat work on s390
[qemu.git] / target-xtensa / translate.c
index 70bea623966ec425965877d0f5b24dec40d4e197..b883e6bb7286aaaee0a09a5a55d019cf72860f18 100644 (file)
@@ -37,9 +37,9 @@
 #include "qemu-log.h"
 #include "sysemu.h"
 
-#include "helpers.h"
+#include "helper.h"
 #define GEN_HELPER 1
-#include "helpers.h"
+#include "helper.h"
 
 typedef struct DisasContext {
     const XtensaConfig *config;
@@ -61,6 +61,10 @@ typedef struct DisasContext {
 
     uint32_t ccount_delta;
     unsigned used_window;
+
+    bool debug;
+    bool icount;
+    TCGv_i32 next_icount;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -91,6 +95,13 @@ static const char * const sregnames[256] = {
     [RASID] = "RASID",
     [ITLBCFG] = "ITLBCFG",
     [DTLBCFG] = "DTLBCFG",
+    [IBREAKENABLE] = "IBREAKENABLE",
+    [IBREAKA] = "IBREAKA0",
+    [IBREAKA + 1] = "IBREAKA1",
+    [DBREAKA] = "DBREAKA0",
+    [DBREAKA + 1] = "DBREAKA1",
+    [DBREAKC] = "DBREAKC0",
+    [DBREAKC + 1] = "DBREAKC1",
     [EPC1] = "EPC1",
     [EPC1 + 1] = "EPC2",
     [EPC1 + 2] = "EPC3",
@@ -119,8 +130,11 @@ static const char * const sregnames[256] = {
     [PS] = "PS",
     [VECBASE] = "VECBASE",
     [EXCCAUSE] = "EXCCAUSE",
+    [DEBUGCAUSE] = "DEBUGCAUSE",
     [CCOUNT] = "CCOUNT",
     [PRID] = "PRID",
+    [ICOUNT] = "ICOUNT",
+    [ICOUNTLEVEL] = "ICOUNTLEVEL",
     [EXCVADDR] = "EXCVADDR",
     [CCOMPARE] = "CCOMPARE0",
     [CCOMPARE + 1] = "CCOMPARE1",
@@ -145,18 +159,18 @@ void xtensa_translate_init(void)
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
     cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
-            offsetof(CPUState, pc), "pc");
+            offsetof(CPUXtensaState, pc), "pc");
 
     for (i = 0; i < 16; i++) {
         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                offsetof(CPUState, regs[i]),
+                offsetof(CPUXtensaState, regs[i]),
                 regnames[i]);
     }
 
     for (i = 0; i < 256; ++i) {
         if (sregnames[i]) {
             cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                    offsetof(CPUState, sregs[i]),
+                    offsetof(CPUXtensaState, sregs[i]),
                     sregnames[i]);
         }
     }
@@ -164,12 +178,12 @@ void xtensa_translate_init(void)
     for (i = 0; i < 256; ++i) {
         if (uregnames[i]) {
             cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
-                    offsetof(CPUState, uregs[i]),
+                    offsetof(CPUXtensaState, uregs[i]),
                     uregnames[i]);
         }
     }
 #define GEN_HELPER 2
-#include "helpers.h"
+#include "helper.h"
 }
 
 static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
@@ -240,7 +254,7 @@ static void gen_advance_ccount(DisasContext *dc)
     if (dc->ccount_delta > 0) {
         TCGv_i32 tmp = tcg_const_i32(dc->ccount_delta);
         dc->ccount_delta = 0;
-        gen_helper_advance_ccount(tmp);
+        gen_helper_advance_ccount(cpu_env, tmp);
         tcg_temp_free(tmp);
     }
 }
@@ -254,7 +268,7 @@ static void gen_exception(DisasContext *dc, int excp)
 {
     TCGv_i32 tmp = tcg_const_i32(excp);
     gen_advance_ccount(dc);
-    gen_helper_exception(tmp);
+    gen_helper_exception(cpu_env, tmp);
     tcg_temp_free(tmp);
 }
 
@@ -263,9 +277,13 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
     TCGv_i32 tpc = tcg_const_i32(dc->pc);
     TCGv_i32 tcause = tcg_const_i32(cause);
     gen_advance_ccount(dc);
-    gen_helper_exception_cause(tpc, tcause);
+    gen_helper_exception_cause(cpu_env, tpc, tcause);
     tcg_temp_free(tpc);
     tcg_temp_free(tcause);
+    if (cause == ILLEGAL_INSTRUCTION_CAUSE ||
+            cause == SYSCALL_CAUSE) {
+        dc->is_jmp = DISAS_UPDATE;
+    }
 }
 
 static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
@@ -274,25 +292,42 @@ static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
     TCGv_i32 tpc = tcg_const_i32(dc->pc);
     TCGv_i32 tcause = tcg_const_i32(cause);
     gen_advance_ccount(dc);
-    gen_helper_exception_cause_vaddr(tpc, tcause, vaddr);
+    gen_helper_exception_cause_vaddr(cpu_env, tpc, tcause, vaddr);
+    tcg_temp_free(tpc);
+    tcg_temp_free(tcause);
+}
+
+static void gen_debug_exception(DisasContext *dc, uint32_t cause)
+{
+    TCGv_i32 tpc = tcg_const_i32(dc->pc);
+    TCGv_i32 tcause = tcg_const_i32(cause);
+    gen_advance_ccount(dc);
+    gen_helper_debug_exception(cpu_env, tpc, tcause);
     tcg_temp_free(tpc);
     tcg_temp_free(tcause);
+    if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
+        dc->is_jmp = DISAS_UPDATE;
+    }
 }
 
 static void gen_check_privilege(DisasContext *dc)
 {
     if (dc->cring) {
         gen_exception_cause(dc, PRIVILEGED_CAUSE);
+        dc->is_jmp = DISAS_UPDATE;
     }
 }
 
 static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
+    gen_advance_ccount(dc);
+    if (dc->icount) {
+        tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount);
+    }
     if (dc->singlestep_enabled) {
         gen_exception(dc, EXCP_DEBUG);
     } else {
-        gen_advance_ccount(dc);
         if (slot >= 0) {
             tcg_gen_goto_tb(slot);
             tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
@@ -353,6 +388,7 @@ static bool gen_check_loop_end(DisasContext *dc, int slot)
             dc->next_pc == dc->lend) {
         int label = gen_new_label();
 
+        gen_advance_ccount(dc);
         tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_SR[LCOUNT], 0, label);
         tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_SR[LCOUNT], 1);
         gen_jumpi(dc, dc->lbeg, slot);
@@ -375,6 +411,7 @@ static void gen_brcond(DisasContext *dc, TCGCond cond,
 {
     int label = gen_new_label();
 
+    gen_advance_ccount(dc);
     tcg_gen_brcond_i32(cond, t0, t1, label);
     gen_jumpi_check_loop_end(dc, 0);
     gen_set_label(label);
@@ -423,12 +460,14 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
 
 static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
-    gen_helper_wsr_lbeg(s);
+    gen_helper_wsr_lbeg(cpu_env, s);
+    gen_jumpi_check_loop_end(dc, 0);
 }
 
 static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 {
-    gen_helper_wsr_lend(s);
+    gen_helper_wsr_lend(cpu_env, s);
+    gen_jumpi_check_loop_end(dc, 0);
 }
 
 static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
@@ -460,13 +499,13 @@ static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 
 static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
-    gen_helper_wsr_windowbase(v);
+    gen_helper_wsr_windowbase(cpu_env, 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);
+    tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1);
     reset_used_window(dc);
 }
 
@@ -477,7 +516,7 @@ static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 
 static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
-    gen_helper_wsr_rasid(v);
+    gen_helper_wsr_rasid(cpu_env, v);
     /* This can change tb->flags, so exit tb */
     gen_jumpi_check_loop_end(dc, -1);
 }
@@ -487,6 +526,46 @@ static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
 }
 
+static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    gen_helper_wsr_ibreakenable(cpu_env, v);
+    gen_jumpi_check_loop_end(dc, 0);
+}
+
+static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - IBREAKA;
+
+    if (id < dc->config->nibreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_ibreaka(cpu_env, tmp, v);
+        tcg_temp_free(tmp);
+        gen_jumpi_check_loop_end(dc, 0);
+    }
+}
+
+static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - DBREAKA;
+
+    if (id < dc->config->ndbreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_dbreaka(cpu_env, tmp, v);
+        tcg_temp_free(tmp);
+    }
+}
+
+static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - DBREAKC;
+
+    if (id < dc->config->ndbreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_dbreakc(cpu_env, tmp, v);
+        tcg_temp_free(tmp);
+    }
+}
+
 static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_andi_i32(cpu_SR[sr], v,
@@ -530,10 +609,30 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_jumpi_check_loop_end(dc, -1);
 }
 
+static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+}
+
 static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
 }
 
+static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    if (dc->icount) {
+        tcg_gen_mov_i32(dc->next_icount, v);
+    } else {
+        tcg_gen_mov_i32(cpu_SR[sr], v);
+    }
+}
+
+static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
+    /* This can change tb->flags, so exit tb */
+    gen_jumpi_check_loop_end(dc, -1);
+}
+
 static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     uint32_t id = sr - CCOMPARE;
@@ -562,11 +661,21 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [RASID] = gen_wsr_rasid,
         [ITLBCFG] = gen_wsr_tlbcfg,
         [DTLBCFG] = gen_wsr_tlbcfg,
+        [IBREAKENABLE] = gen_wsr_ibreakenable,
+        [IBREAKA] = gen_wsr_ibreaka,
+        [IBREAKA + 1] = gen_wsr_ibreaka,
+        [DBREAKA] = gen_wsr_dbreaka,
+        [DBREAKA + 1] = gen_wsr_dbreaka,
+        [DBREAKC] = gen_wsr_dbreakc,
+        [DBREAKC + 1] = gen_wsr_dbreakc,
         [INTSET] = gen_wsr_intset,
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
         [PS] = gen_wsr_ps,
+        [DEBUGCAUSE] = gen_wsr_debugcause,
         [PRID] = gen_wsr_prid,
+        [ICOUNT] = gen_wsr_icount,
+        [ICOUNTLEVEL] = gen_wsr_icountlevel,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
         [CCOMPARE + 2] = gen_wsr_ccompare,
@@ -605,7 +714,7 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
     TCGv_i32 pc = tcg_const_i32(dc->next_pc);
     TCGv_i32 intlevel = tcg_const_i32(imm4);
     gen_advance_ccount(dc);
-    gen_helper_waiti(pc, intlevel);
+    gen_helper_waiti(cpu_env, pc, intlevel);
     tcg_temp_free(pc);
     tcg_temp_free(intlevel);
 }
@@ -622,7 +731,7 @@ static void gen_window_check1(DisasContext *dc, unsigned r1)
 
         dc->used_window = r1 / 4;
         gen_advance_ccount(dc);
-        gen_helper_window_check(pc, w);
+        gen_helper_window_check(cpu_env, pc, w);
 
         tcg_temp_free(w);
         tcg_temp_free(pc);
@@ -742,9 +851,9 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 #define RSR_SR (b1)
 
-    uint8_t b0 = ldub_code(dc->pc);
-    uint8_t b1 = ldub_code(dc->pc + 1);
-    uint8_t b2 = ldub_code(dc->pc + 2);
+    uint8_t b0 = cpu_ldub_code(cpu_single_env, dc->pc);
+    uint8_t b1 = cpu_ldub_code(cpu_single_env, dc->pc + 1);
+    uint8_t b2 = 0;
 
     static const uint32_t B4CONST[] = {
         0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
@@ -759,6 +868,7 @@ static void disas_xtensa_insn(DisasContext *dc)
         HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
     } else {
         dc->next_pc = dc->pc + 3;
+        b2 = cpu_ldub_code(cpu_single_env, dc->pc + 2);
     }
 
     switch (OP0) {
@@ -795,7 +905,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                             {
                                 TCGv_i32 tmp = tcg_const_i32(dc->pc);
                                 gen_advance_ccount(dc);
-                                gen_helper_retw(tmp, tmp);
+                                gen_helper_retw(tmp, cpu_env, tmp);
                                 gen_jump(dc, tmp);
                                 tcg_temp_free(tmp);
                             }
@@ -843,7 +953,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     {
                         TCGv_i32 pc = tcg_const_i32(dc->pc);
                         gen_advance_ccount(dc);
-                        gen_helper_movsp(pc);
+                        gen_helper_movsp(cpu_env, pc);
                         tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
                         tcg_temp_free(pc);
                     }
@@ -923,7 +1033,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                                             cpu_SR[WINDOW_START], tmp);
                                 }
 
-                                gen_helper_restore_owb();
+                                gen_helper_restore_owb(cpu_env);
                                 gen_helper_check_interrupts(cpu_env);
                                 gen_jump(dc, cpu_SR[EPC1]);
 
@@ -963,8 +1073,10 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 4: /*BREAKx*/
-                    HAS_OPTION(XTENSA_OPTION_EXCEPTION);
-                    TBD();
+                    HAS_OPTION(XTENSA_OPTION_DEBUG);
+                    if (dc->debug) {
+                        gen_debug_exception(dc, DEBUGCAUSE_BI);
+                    }
                     break;
 
                 case 5: /*SYSCALLx*/
@@ -1109,20 +1221,20 @@ static void disas_xtensa_insn(DisasContext *dc)
                     {
                         TCGv_i32 tmp = tcg_const_i32(
                                 RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
-                        gen_helper_rotw(tmp);
+                        gen_helper_rotw(cpu_env, tmp);
                         tcg_temp_free(tmp);
                         reset_used_window(dc);
                     }
                     break;
 
                 case 14: /*NSAu*/
-                    HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    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]);
                     break;
 
                 case 15: /*NSAUu*/
-                    HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                    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]);
                     break;
@@ -1145,28 +1257,32 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                     switch (RRR_R & 7) {
                     case 3: /*RITLB0*/ /*RDTLB0*/
-                        gen_helper_rtlb0(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_rtlb0(cpu_R[RRR_T],
+                                cpu_env, cpu_R[RRR_S], dtlb);
                         break;
 
                     case 4: /*IITLB*/ /*IDTLB*/
-                        gen_helper_itlb(cpu_R[RRR_S], dtlb);
+                        gen_helper_itlb(cpu_env, cpu_R[RRR_S], dtlb);
                         /* This could change memory mapping, so exit tb */
                         gen_jumpi_check_loop_end(dc, -1);
                         break;
 
                     case 5: /*PITLB*/ /*PDTLB*/
                         tcg_gen_movi_i32(cpu_pc, dc->pc);
-                        gen_helper_ptlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_ptlb(cpu_R[RRR_T],
+                                cpu_env, cpu_R[RRR_S], dtlb);
                         break;
 
                     case 6: /*WITLB*/ /*WDTLB*/
-                        gen_helper_wtlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_wtlb(
+                                cpu_env, cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
                         /* This could change memory mapping, so exit tb */
                         gen_jumpi_check_loop_end(dc, -1);
                         break;
 
                     case 7: /*RITLB1*/ /*RDTLB1*/
-                        gen_helper_rtlb1(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
+                        gen_helper_rtlb1(cpu_R[RRR_T],
+                                cpu_env, cpu_R[RRR_S], dtlb);
                         break;
 
                     default:
@@ -1434,7 +1550,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
             case 10: /*MULUHi*/
             case 11: /*MULSHi*/
-                HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL);
+                HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL_HIGH);
                 {
                     TCGv_i64 r = tcg_temp_new_i64();
                     TCGv_i64 s = tcg_temp_new_i64();
@@ -1521,7 +1637,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 2: /*SEXTu*/
-                HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                HAS_OPTION(XTENSA_OPTION_MISC_OP_SEXT);
                 gen_window_check2(dc, RRR_R, RRR_S);
                 {
                     int shift = 24 - RRR_T;
@@ -1540,7 +1656,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 3: /*CLAMPSu*/
-                HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                HAS_OPTION(XTENSA_OPTION_MISC_OP_CLAMPS);
                 gen_window_check2(dc, RRR_R, RRR_S);
                 {
                     TCGv_i32 tmp1 = tcg_temp_new_i32();
@@ -1568,7 +1684,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             case 5: /*MAXu*/
             case 6: /*MINUu*/
             case 7: /*MAXUu*/
-                HAS_OPTION(XTENSA_OPTION_MISC_OP);
+                HAS_OPTION(XTENSA_OPTION_MISC_OP_MINMAX);
                 gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
                 {
                     static const TCGCond cond[] = {
@@ -1921,7 +2037,7 @@ static void disas_xtensa_insn(DisasContext *dc)
             break;
 
         case 14: /*S32C1Iy*/
-            HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
+            HAS_OPTION(XTENSA_OPTION_CONDITIONAL_STORE);
             gen_window_check2(dc, RRI8_S, RRI8_T);
             {
                 int label = gen_new_label();
@@ -2134,7 +2250,7 @@ static void disas_xtensa_insn(DisasContext *dc)
                     TCGv_i32 s = tcg_const_i32(BRI12_S);
                     TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
                     gen_advance_ccount(dc);
-                    gen_helper_entry(pc, s, imm);
+                    gen_helper_entry(cpu_env, pc, s, imm);
                     tcg_temp_free(imm);
                     tcg_temp_free(s);
                     tcg_temp_free(pc);
@@ -2168,7 +2284,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 
                         tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1);
                         tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc);
-                        gen_wsr_lend(dc, LEND, tmp);
+                        gen_helper_wsr_lend(cpu_env, tmp);
                         tcg_temp_free(tmp);
 
                         if (BRI8_R > 8) {
@@ -2337,14 +2453,17 @@ static void disas_xtensa_insn(DisasContext *dc)
                 {
                     TCGv_i32 tmp = tcg_const_i32(dc->pc);
                     gen_advance_ccount(dc);
-                    gen_helper_retw(tmp, tmp);
+                    gen_helper_retw(tmp, cpu_env, tmp);
                     gen_jump(dc, tmp);
                     tcg_temp_free(tmp);
                 }
                 break;
 
             case 2: /*BREAK.Nn*/
-                TBD();
+                HAS_OPTION(XTENSA_OPTION_DEBUG);
+                if (dc->debug) {
+                    gen_debug_exception(dc, DEBUGCAUSE_BN);
+                }
                 break;
 
             case 3: /*NOP.Nn*/
@@ -2378,11 +2497,11 @@ static void disas_xtensa_insn(DisasContext *dc)
 
 invalid_opcode:
     qemu_log("INVALID(pc = %08x)\n", dc->pc);
-    dc->pc = dc->next_pc;
+    gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
 #undef HAS_OPTION
 }
 
-static void check_breakpoint(CPUState *env, DisasContext *dc)
+static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
 {
     CPUBreakpoint *bp;
 
@@ -2397,8 +2516,21 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
     }
 }
 
+static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
+{
+    unsigned i;
+
+    for (i = 0; i < dc->config->nibreak; ++i) {
+        if ((env->sregs[IBREAKENABLE] & (1 << i)) &&
+                env->sregs[IBREAKA + i] == dc->pc) {
+            gen_debug_exception(dc, DEBUGCAUSE_IB);
+            break;
+        }
+    }
+}
+
 static void gen_intermediate_code_internal(
-        CPUState *env, TranslationBlock *tb, int search_pc)
+        CPUXtensaState *env, TranslationBlock *tb, int search_pc)
 {
     DisasContext dc;
     int insn_count = 0;
@@ -2423,10 +2555,15 @@ static void gen_intermediate_code_internal(
     dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
     dc.ccount_delta = 0;
+    dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
+    dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT;
 
     init_litbase(&dc);
     init_sar_tracker(&dc);
     reset_used_window(&dc);
+    if (dc.icount) {
+        dc.next_icount = tcg_temp_local_new_i32();
+    }
 
     gen_icount_start();
 
@@ -2462,8 +2599,27 @@ static void gen_intermediate_code_internal(
             gen_io_start();
         }
 
+        if (dc.icount) {
+            int label = gen_new_label();
+
+            tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1);
+            tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label);
+            tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]);
+            if (dc.debug) {
+                gen_debug_exception(&dc, DEBUGCAUSE_IC);
+            }
+            gen_set_label(label);
+        }
+
+        if (dc.debug) {
+            gen_ibreak_check(env, &dc);
+        }
+
         disas_xtensa_insn(&dc);
         ++insn_count;
+        if (dc.icount) {
+            tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
+        }
         if (env->singlestep_enabled) {
             tcg_gen_movi_i32(cpu_pc, dc.pc);
             gen_exception(&dc, EXCP_DEBUG);
@@ -2476,6 +2632,9 @@ static void gen_intermediate_code_internal(
 
     reset_litbase(&dc);
     reset_sar_tracker(&dc);
+    if (dc.icount) {
+        tcg_temp_free(dc.next_icount);
+    }
 
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
@@ -2493,17 +2652,17 @@ static void gen_intermediate_code_internal(
     }
 }
 
-void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 0);
 }
 
-void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
+void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb)
 {
     gen_intermediate_code_internal(env, tb, 1);
 }
 
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
         int flags)
 {
     int i, j;
@@ -2541,7 +2700,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     }
 }
 
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
 {
     env->pc = gen_opc_pc[pc_pos];
 }
This page took 0.045298 seconds and 4 git commands to generate.