]> git.proxmox.com Git - qemu.git/blobdiff - target-cris/translate_v10.c
linux-user: Move cpu_clone_regs() and cpu_set_tls() into linux-user
[qemu.git] / target-cris / translate_v10.c
index e6131bbfa0ccfd6acf78ac95cf4d586f79c11061..d6ef084483a1327809b24356e655ac5119a961b3 100644 (file)
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "crisv10-decode.h"
 
 static const char *regnames_v10[] =
 {
-       "$r0", "$r1", "$r2", "$r3",
-       "$r4", "$r5", "$r6", "$r7",
-       "$r8", "$r9", "$r10", "$r11",
-       "$r12", "$r13", "$sp", "$pc",
+    "$r0", "$r1", "$r2", "$r3",
+    "$r4", "$r5", "$r6", "$r7",
+    "$r8", "$r9", "$r10", "$r11",
+    "$r12", "$r13", "$sp", "$pc",
 };
 
 static const char *pregnames_v10[] =
 {
-       "$bz", "$vr", "$p2", "$p3",
-       "$wz", "$ccr", "$p6-prefix", "$mof",
-       "$dz", "$ibr", "$irp", "$srp",
-       "$bar", "$dccr", "$brp", "$usp",
+    "$bz", "$vr", "$p2", "$p3",
+    "$wz", "$ccr", "$p6-prefix", "$mof",
+    "$dz", "$ibr", "$irp", "$srp",
+    "$bar", "$dccr", "$brp", "$usp",
 };
 
 /* We need this table to handle preg-moves with implicit width.  */
 static int preg_sizes_v10[] = {
-       1, /* bz.  */
-       1, /* vr.  */
-       1, /* pid. */
-       1, /* srs. */
-       2, /* wz.  */
-       2, 2, 4,
-       4, 4, 4, 4,
-       4, 4, 4, 4,
+    1, /* bz.  */
+    1, /* vr.  */
+    1, /* pid. */
+    1, /* srs. */
+    2, /* wz.  */
+    2, 2, 4,
+    4, 4, 4, 4,
+    4, 4, 4, 4,
 };
 
 static inline int dec10_size(unsigned int size)
@@ -63,6 +62,65 @@ static inline void cris_illegal_insn(DisasContext *dc)
     t_gen_raise_exception(EXCP_BREAK);
 }
 
+static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val,
+                       unsigned int size, int mem_index)
+{
+    int l1 = gen_new_label();
+    TCGv taddr = tcg_temp_local_new();
+    TCGv tval = tcg_temp_local_new();
+    TCGv t1 = tcg_temp_local_new();
+    dc->postinc = 0;
+    cris_evaluate_flags(dc);
+
+    tcg_gen_mov_tl(taddr, addr);
+    tcg_gen_mov_tl(tval, val);
+
+    /* Store only if F flag isn't set */
+    tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10);
+    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+    if (size == 1) {
+        tcg_gen_qemu_st8(tval, taddr, mem_index);
+    } else if (size == 2) {
+        tcg_gen_qemu_st16(tval, taddr, mem_index);
+    } else {
+        tcg_gen_qemu_st32(tval, taddr, mem_index);
+    }
+    gen_set_label(l1);
+    tcg_gen_shri_tl(t1, t1, 1);  /* shift F to P position */
+    tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/
+    tcg_temp_free(t1);
+    tcg_temp_free(tval);
+    tcg_temp_free(taddr);
+}
+
+static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val,
+                       unsigned int size)
+{
+    int mem_index = cpu_mmu_index(dc->env);
+
+    /* If we get a fault on a delayslot we must keep the jmp state in
+       the cpu-state to be able to re-execute the jmp.  */
+    if (dc->delayed_branch == 1) {
+        cris_store_direct_jmp(dc);
+    }
+
+    /* Conditional writes. We only support the kind were X is known
+       at translation time.  */
+    if (dc->flagx_known && dc->flags_x) {
+        gen_store_v10_conditional(dc, addr, val, size, mem_index);
+        return;
+    }
+
+    if (size == 1) {
+        tcg_gen_qemu_st8(val, addr, mem_index);
+    } else if (size == 2) {
+        tcg_gen_qemu_st16(val, addr, mem_index);
+    } else {
+        tcg_gen_qemu_st32(val, addr, mem_index);
+    }
+}
+
+
 /* Prefix flag and register are used to handle the more complex
    addressing modes.  */
 static void cris_set_prefix(DisasContext *dc)
@@ -106,64 +164,63 @@ static unsigned int crisv10_post_memaddr(DisasContext *dc, unsigned int size)
     return insn_len;
 }
 
-static int dec10_prep_move_m(DisasContext *dc, int s_ext, int memsize,
-                           TCGv dst)
+static int dec10_prep_move_m(CPUCRISState *env, DisasContext *dc,
+                             int s_ext, int memsize, TCGv dst)
 {
-        unsigned int rs, rd;
-        uint32_t imm;
-        int is_imm;
-        int insn_len = 0;
-
-        rs = dc->src;
-        rd = dc->dst;
-        is_imm = rs == 15 && !(dc->tb_flags & PFIX_FLAG);
-        LOG_DIS("rs=%d rd=%d is_imm=%d mode=%d pfix=%d\n",
-                  rs, rd, is_imm, dc->mode, dc->tb_flags & PFIX_FLAG);
-
-        /* Load [$rs] onto T1.  */
-        if (is_imm) {
-                if (memsize != 4) {
-                        if (s_ext) {
-                                if (memsize == 1)
-                                        imm = ldsb_code(dc->pc + 2);
-                                else
-                                        imm = ldsw_code(dc->pc + 2);
-                        } else {
-                                if (memsize == 1)
-                                        imm = ldub_code(dc->pc + 2);
-                                else
-                                        imm = lduw_code(dc->pc + 2);
-                        }
-                } else
-                        imm = ldl_code(dc->pc + 2);
-
-                tcg_gen_movi_tl(dst, imm);
-
-                if (dc->mode == CRISV10_MODE_AUTOINC) {
-                    insn_len += memsize;
-                    if (memsize == 1)
-                            insn_len++;
-                    tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len);
-                }
-        } else {
-                TCGv addr;
-
-                addr = tcg_temp_new();
-                cris_flush_cc_state(dc);
-                crisv10_prepare_memaddr(dc, addr, memsize);
-                gen_load(dc, dst, addr, memsize, 0);
-                if (s_ext)
-                        t_gen_sext(dst, dst, memsize);
+    unsigned int rs;
+    uint32_t imm;
+    int is_imm;
+    int insn_len = 0;
+
+    rs = dc->src;
+    is_imm = rs == 15 && !(dc->tb_flags & PFIX_FLAG);
+    LOG_DIS("rs=%d rd=%d is_imm=%d mode=%d pfix=%d\n",
+             rs, dc->dst, is_imm, dc->mode, dc->tb_flags & PFIX_FLAG);
+
+    /* Load [$rs] onto T1.  */
+    if (is_imm) {
+        if (memsize != 4) {
+            if (s_ext) {
+                if (memsize == 1)
+                    imm = cpu_ldsb_code(env, dc->pc + 2);
                 else
-                        t_gen_zext(dst, dst, memsize);
-                insn_len += crisv10_post_memaddr(dc, memsize);
-                tcg_temp_free(addr);
-        }
+                    imm = cpu_ldsw_code(env, dc->pc + 2);
+            } else {
+                if (memsize == 1)
+                    imm = cpu_ldub_code(env, dc->pc + 2);
+                else
+                    imm = cpu_lduw_code(env, dc->pc + 2);
+            }
+        } else
+            imm = cpu_ldl_code(env, dc->pc + 2);
+
+        tcg_gen_movi_tl(dst, imm);
 
-        if (dc->mode == CRISV10_MODE_INDIRECT && (dc->tb_flags & PFIX_FLAG)) {
-            dc->dst = dc->src;
+        if (dc->mode == CRISV10_MODE_AUTOINC) {
+            insn_len += memsize;
+            if (memsize == 1)
+                insn_len++;
+            tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len);
         }
-        return insn_len;
+    } else {
+        TCGv addr;
+
+        addr = tcg_temp_new();
+        cris_flush_cc_state(dc);
+        crisv10_prepare_memaddr(dc, addr, memsize);
+        gen_load(dc, dst, addr, memsize, 0);
+        if (s_ext)
+            t_gen_sext(dst, dst, memsize);
+        else
+            t_gen_zext(dst, dst, memsize);
+        insn_len += crisv10_post_memaddr(dc, memsize);
+        tcg_temp_free(addr);
+    }
+
+    if (dc->mode == CRISV10_MODE_INDIRECT && (dc->tb_flags & PFIX_FLAG)) {
+        dc->dst = dc->src;
+    }
+    return insn_len;
 }
 
 static unsigned int dec10_quick_imm(DisasContext *dc)
@@ -232,7 +289,7 @@ static unsigned int dec10_quick_imm(DisasContext *dc)
             } else {
                 /* BTST */
                 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-                gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst],
+                gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst],
                            tcg_const_tl(imm), cpu_PR[PR_CCS]);
             }
             break;
@@ -264,9 +321,6 @@ static unsigned int dec10_quick_imm(DisasContext *dc)
             break;
 
         case CRISV10_QIMM_BCC_R0:
-            if (!dc->ir) {
-                cpu_abort(dc->env, "opcode zero\n");
-            }
         case CRISV10_QIMM_BCC_R1:
         case CRISV10_QIMM_BCC_R2:
         case CRISV10_QIMM_BCC_R3:
@@ -286,7 +340,7 @@ static unsigned int dec10_quick_imm(DisasContext *dc)
         default:
             LOG_DIS("pc=%x mode=%x quickimm %d r%d r%d\n",
                      dc->pc, dc->mode, dc->opcode, dc->src, dc->dst);
-            assert(0);
+            cpu_abort(dc->env, "Unhandled quickimm\n");
             break;
     }
     return 2;
@@ -318,7 +372,8 @@ static unsigned int dec10_setclrf(DisasContext *dc)
     if (set) {
         tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
     } else {
-        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
+        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS],
+                        ~(flags|F_FLAG_V10|P_FLAG_V10));
     }
 
     dc->flags_uptodate = 1;
@@ -439,20 +494,18 @@ static void dec10_reg_mov_pr(DisasContext *dc)
 
 static void dec10_reg_abs(DisasContext *dc)
 {
-       TCGv t0;
+    TCGv t0;
 
-       LOG_DIS("abs $r%u, $r%u\n",
-                   dc->src, dc->dst);
+    LOG_DIS("abs $r%u, $r%u\n", dc->src, dc->dst);
 
-       assert(dc->dst != 15);
-       t0 = tcg_temp_new();
-       tcg_gen_sari_tl(t0, cpu_R[dc->src], 31);
-       tcg_gen_xor_tl(cpu_R[dc->dst], cpu_R[dc->src], t0);
-       tcg_gen_sub_tl(t0, cpu_R[dc->dst], t0);
+    assert(dc->dst != 15);
+    t0 = tcg_temp_new();
+    tcg_gen_sari_tl(t0, cpu_R[dc->src], 31);
+    tcg_gen_xor_tl(cpu_R[dc->dst], cpu_R[dc->src], t0);
+    tcg_gen_sub_tl(t0, cpu_R[dc->dst], t0);
 
-       cris_alu(dc, CC_OP_MOVE,
-                   cpu_R[dc->dst], cpu_R[dc->dst], t0, 4);
-       tcg_temp_free(t0);
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t0, 4);
+    tcg_temp_free(t0);
 }
 
 static void dec10_reg_swap(DisasContext *dc)
@@ -478,25 +531,24 @@ static void dec10_reg_swap(DisasContext *dc)
 
 static void dec10_reg_scc(DisasContext *dc)
 {
-        int cond = dc->dst;
+    int cond = dc->dst;
 
-        LOG_DIS("s%s $r%u\n",
-                    cc_name(cond), dc->src);
+    LOG_DIS("s%s $r%u\n", cc_name(cond), dc->src);
 
-        if (cond != CC_A)
-        {
-                int l1;
+    if (cond != CC_A)
+    {
+        int l1;
 
-                gen_tst_cc (dc, cpu_R[dc->src], cond);
-                l1 = gen_new_label();
-                tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->src], 0, l1);
-                tcg_gen_movi_tl(cpu_R[dc->src], 1);
-                gen_set_label(l1);
-        }
-        else
-                tcg_gen_movi_tl(cpu_R[dc->src], 1);
+        gen_tst_cc (dc, cpu_R[dc->src], cond);
+        l1 = gen_new_label();
+        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->src], 0, l1);
+        tcg_gen_movi_tl(cpu_R[dc->src], 1);
+        gen_set_label(l1);
+    } else {
+        tcg_gen_movi_tl(cpu_R[dc->src], 1);
+    }
 
-        cris_cc_mask(dc, 0);
+    cris_cc_mask(dc, 0);
 }
 
 static unsigned int dec10_reg(DisasContext *dc)
@@ -598,7 +650,9 @@ static unsigned int dec10_reg(DisasContext *dc)
                     case 4: tmp = 2; break;
                     case 2: tmp = 1; break;
                     case 1: tmp = 0; break;
-                    default: assert(0); break;
+                    default:
+                        cpu_abort(dc->env, "Unhandled BIAP");
+                        break;
                 }
 
                 t = tcg_temp_new();
@@ -615,7 +669,7 @@ static unsigned int dec10_reg(DisasContext *dc)
             default:
                 LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
                          dc->opcode, dc->src, dc->dst);
-                assert(0);
+                cpu_abort(dc->env, "Unhandled opcode");
                 break;
         }
     } else {
@@ -669,7 +723,7 @@ static unsigned int dec10_reg(DisasContext *dc)
                 LOG_DIS("btst $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                 cris_cc_mask(dc, CC_MASK_NZVC);
                 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-                gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst],
+                gen_helper_btst(cpu_PR[PR_CCS], cpu_env, cpu_R[dc->dst],
                            cpu_R[dc->src], cpu_PR[PR_CCS]);
                 break;
             case CRISV10_REG_DSTEP:
@@ -691,14 +745,15 @@ static unsigned int dec10_reg(DisasContext *dc)
             default:
                 LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
                          dc->opcode, dc->src, dc->dst);
-                assert(0);
+                cpu_abort(dc->env, "Unhandled opcode");
                 break;
         }
     }
     return insn_len;
 }
 
-static unsigned int dec10_ind_move_m_r(DisasContext *dc, unsigned int size)
+static unsigned int dec10_ind_move_m_r(CPUCRISState *env, DisasContext *dc,
+                                       unsigned int size)
 {
     unsigned int insn_len = 2;
     TCGv t;
@@ -708,7 +763,7 @@ static unsigned int dec10_ind_move_m_r(DisasContext *dc, unsigned int size)
 
     cris_cc_mask(dc, CC_MASK_NZVC);
     t = tcg_temp_new();
-    insn_len += dec10_prep_move_m(dc, 0, size, t);
+    insn_len += dec10_prep_move_m(env, dc, 0, size, t);
     cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, size);
     if (dc->dst == 15) {
         tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
@@ -729,13 +784,13 @@ static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size)
     LOG_DIS("move.%d $r%d, [$r%d]\n", dc->size, dc->src, dc->dst);
     addr = tcg_temp_new();
     crisv10_prepare_memaddr(dc, addr, size);
-    gen_store(dc, addr, cpu_R[dc->dst], size);
+    gen_store_v10(dc, addr, cpu_R[dc->dst], size);
     insn_len += crisv10_post_memaddr(dc, size);
 
     return insn_len;
 }
 
-static unsigned int dec10_ind_move_m_pr(DisasContext *dc)
+static unsigned int dec10_ind_move_m_pr(CPUCRISState *env, DisasContext *dc)
 {
     unsigned int insn_len = 2, rd = dc->dst;
     TCGv t, addr;
@@ -745,7 +800,7 @@ static unsigned int dec10_ind_move_m_pr(DisasContext *dc)
 
     addr = tcg_temp_new();
     t = tcg_temp_new();
-    insn_len += dec10_prep_move_m(dc, 0, 4, t);
+    insn_len += dec10_prep_move_m(env, dc, 0, 4, t);
     if (rd == 15) {
         tcg_gen_mov_tl(env_btarget, t);
         cris_prepare_jmp(dc, JMP_INDIRECT);
@@ -773,10 +828,10 @@ static unsigned int dec10_ind_move_pr_m(DisasContext *dc)
         t0 = tcg_temp_new();
         cris_evaluate_flags(dc);
         tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG);
-        gen_store(dc, addr, t0, size);
+        gen_store_v10(dc, addr, t0, size);
         tcg_temp_free(t0);
     } else {
-        gen_store(dc, addr, cpu_PR[dc->dst], size);
+        gen_store_v10(dc, addr, cpu_PR[dc->dst], size);
     }
     t0 = tcg_temp_new();
     insn_len += crisv10_post_memaddr(dc, size);
@@ -799,9 +854,9 @@ static void dec10_movem_r_m(DisasContext *dc)
     tcg_gen_mov_tl(t0, addr);
     for (i = dc->dst; i >= 0; i--) {
         if ((pfix && dc->mode == CRISV10_MODE_AUTOINC) && dc->src == i) {
-            gen_store(dc, addr, t0, 4);
+            gen_store_v10(dc, addr, t0, 4);
         } else {
-            gen_store(dc, addr, cpu_R[i], 4);
+            gen_store_v10(dc, addr, cpu_R[i], 4);
         }
         tcg_gen_addi_tl(addr, addr, 4);
     }
@@ -838,7 +893,6 @@ static void dec10_movem_m_r(DisasContext *dc)
         tcg_gen_mov_tl(cpu_R[dc->src], t0);
     }
 
-
     if (!pfix && dc->mode == CRISV10_MODE_AUTOINC) {
         tcg_gen_mov_tl(cpu_R[dc->src], addr);
     }
@@ -846,14 +900,15 @@ static void dec10_movem_m_r(DisasContext *dc)
     tcg_temp_free(t0);
 }
 
-static int dec10_ind_alu(DisasContext *dc, int op, unsigned int size)
+static int dec10_ind_alu(CPUCRISState *env, DisasContext *dc,
+                         int op, unsigned int size)
 {
     int insn_len = 0;
     int rd = dc->dst;
     TCGv t[2];
 
     cris_alu_m_alloc_temps(t);
-    insn_len += dec10_prep_move_m(dc, 0, size, t[0]);
+    insn_len += dec10_prep_move_m(env, dc, 0, size, t[0]);
     cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t[0], size);
     if (dc->dst == 15) {
         tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
@@ -867,14 +922,15 @@ static int dec10_ind_alu(DisasContext *dc, int op, unsigned int size)
     return insn_len;
 }
 
-static int dec10_ind_bound(DisasContext *dc, unsigned int size)
+static int dec10_ind_bound(CPUCRISState *env, DisasContext *dc,
+                           unsigned int size)
 {
     int insn_len = 0;
     int rd = dc->dst;
     TCGv t;
 
     t = tcg_temp_local_new();
-    insn_len += dec10_prep_move_m(dc, 0, size, t);
+    insn_len += dec10_prep_move_m(env, dc, 0, size, t);
     cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[rd], t, 4);
     if (dc->dst == 15) {
         tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
@@ -887,7 +943,7 @@ static int dec10_ind_bound(DisasContext *dc, unsigned int size)
     return insn_len;
 }
 
-static int dec10_alux_m(DisasContext *dc, int op)
+static int dec10_alux_m(CPUCRISState *env, DisasContext *dc, int op)
 {
     unsigned int size = (dc->size & 1) ? 2 : 1;
     unsigned int sx = !!(dc->size & 2);
@@ -900,7 +956,7 @@ static int dec10_alux_m(DisasContext *dc, int op)
     t = tcg_temp_new();
 
     cris_cc_mask(dc, CC_MASK_NZVC);
-    insn_len += dec10_prep_move_m(dc, sx, size, t);
+    insn_len += dec10_prep_move_m(env, dc, sx, size, t);
     cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t, 4);
     if (dc->dst == 15) {
         tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
@@ -913,7 +969,7 @@ static int dec10_alux_m(DisasContext *dc, int op)
     return insn_len;
 }
 
-static int dec10_dip(DisasContext *dc)
+static int dec10_dip(CPUCRISState *env, DisasContext *dc)
 {
     int insn_len = 2;
     uint32_t imm;
@@ -921,7 +977,7 @@ static int dec10_dip(DisasContext *dc)
     LOG_DIS("dip pc=%x opcode=%d r%d r%d\n",
               dc->pc, dc->opcode, dc->src, dc->dst);
     if (dc->src == 15) {
-        imm = ldl_code(dc->pc + 2);
+        imm = cpu_ldl_code(env, dc->pc + 2);
         tcg_gen_movi_tl(cpu_PR[PR_PREFIX], imm);
         if (dc->postinc)
             insn_len += 4;
@@ -936,7 +992,7 @@ static int dec10_dip(DisasContext *dc)
     return insn_len;
 }
 
-static int dec10_bdap_m(DisasContext *dc, int size)
+static int dec10_bdap_m(CPUCRISState *env, DisasContext *dc, int size)
 {
     int insn_len = 2;
     int rd = dc->dst;
@@ -950,7 +1006,7 @@ static int dec10_bdap_m(DisasContext *dc, int size)
     if (!dc->postinc && (dc->ir & (1 << 11))) {
         int simm = dc->ir & 0xff;
 
-       // assert(0);
+        /* cpu_abort(dc->env, "Unhandled opcode"); */
         /* sign extended.  */
         simm = (int8_t)simm;
 
@@ -960,14 +1016,14 @@ static int dec10_bdap_m(DisasContext *dc, int size)
         return insn_len;
     }
 #endif
-    /* Now the rest of the modes are truely indirect.  */
-    insn_len += dec10_prep_move_m(dc, 1, size, cpu_PR[PR_PREFIX]);
+    /* Now the rest of the modes are truly indirect.  */
+    insn_len += dec10_prep_move_m(env, dc, 1, size, cpu_PR[PR_PREFIX]);
     tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_PR[PR_PREFIX], cpu_R[rd]);
     cris_set_prefix(dc);
     return insn_len;
 }
 
-static unsigned int dec10_ind(DisasContext *dc)
+static unsigned int dec10_ind(CPUCRISState *env, DisasContext *dc)
 {
     unsigned int insn_len = 2;
     unsigned int size = dec10_size(dc->size);
@@ -978,7 +1034,7 @@ static unsigned int dec10_ind(DisasContext *dc)
     if (dc->size != 3) {
         switch (dc->opcode) {
             case CRISV10_IND_MOVE_M_R:
-                return dec10_ind_move_m_r(dc, size);
+                return dec10_ind_move_m_r(env, dc, size);
                 break;
             case CRISV10_IND_MOVE_R_M:
                 return dec10_ind_move_r_m(dc, size);
@@ -986,7 +1042,7 @@ static unsigned int dec10_ind(DisasContext *dc)
             case CRISV10_IND_CMP:
                 LOG_DIS("cmp size=%d op=%d %d\n",  size, dc->src, dc->dst);
                 cris_cc_mask(dc, CC_MASK_NZVC);
-                insn_len += dec10_ind_alu(dc, CC_OP_CMP, size);
+                insn_len += dec10_ind_alu(env, dc, CC_OP_CMP, size);
                 break;
             case CRISV10_IND_TEST:
                 LOG_DIS("test size=%d op=%d %d\n",  size, dc->src, dc->dst);
@@ -994,7 +1050,7 @@ static unsigned int dec10_ind(DisasContext *dc)
                 cris_evaluate_flags(dc);
                 cris_cc_mask(dc, CC_MASK_NZVC);
                 cris_alu_m_alloc_temps(t);
-                insn_len += dec10_prep_move_m(dc, 0, size, t[0]);
+                insn_len += dec10_prep_move_m(env, dc, 0, size, t[0]);
                 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
                 cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst],
                          t[0], tcg_const_tl(0), size);
@@ -1003,39 +1059,39 @@ static unsigned int dec10_ind(DisasContext *dc)
             case CRISV10_IND_ADD:
                 LOG_DIS("add size=%d op=%d %d\n",  size, dc->src, dc->dst);
                 cris_cc_mask(dc, CC_MASK_NZVC);
-                insn_len += dec10_ind_alu(dc, CC_OP_ADD, size);
+                insn_len += dec10_ind_alu(env, dc, CC_OP_ADD, size);
                 break;
             case CRISV10_IND_SUB:
                 LOG_DIS("sub size=%d op=%d %d\n",  size, dc->src, dc->dst);
                 cris_cc_mask(dc, CC_MASK_NZVC);
-                insn_len += dec10_ind_alu(dc, CC_OP_SUB, size);
+                insn_len += dec10_ind_alu(env, dc, CC_OP_SUB, size);
                 break;
             case CRISV10_IND_BOUND:
                 LOG_DIS("bound size=%d op=%d %d\n",  size, dc->src, dc->dst);
                 cris_cc_mask(dc, CC_MASK_NZVC);
-                insn_len += dec10_ind_bound(dc, size);
+                insn_len += dec10_ind_bound(env, dc, size);
                 break;
             case CRISV10_IND_AND:
                 LOG_DIS("and size=%d op=%d %d\n",  size, dc->src, dc->dst);
                 cris_cc_mask(dc, CC_MASK_NZVC);
-                insn_len += dec10_ind_alu(dc, CC_OP_AND, size);
+                insn_len += dec10_ind_alu(env, dc, CC_OP_AND, size);
                 break;
             case CRISV10_IND_OR:
                 LOG_DIS("or size=%d op=%d %d\n",  size, dc->src, dc->dst);
                 cris_cc_mask(dc, CC_MASK_NZVC);
-                insn_len += dec10_ind_alu(dc, CC_OP_OR, size);
+                insn_len += dec10_ind_alu(env, dc, CC_OP_OR, size);
                 break;
             case CRISV10_IND_MOVX:
-                insn_len = dec10_alux_m(dc, CC_OP_MOVE);
+                insn_len = dec10_alux_m(env, dc, CC_OP_MOVE);
                 break;
             case CRISV10_IND_ADDX:
-                insn_len = dec10_alux_m(dc, CC_OP_ADD);
+                insn_len = dec10_alux_m(env, dc, CC_OP_ADD);
                 break;
             case CRISV10_IND_SUBX:
-                insn_len = dec10_alux_m(dc, CC_OP_SUB);
+                insn_len = dec10_alux_m(env, dc, CC_OP_SUB);
                 break;
             case CRISV10_IND_CMPX:
-                insn_len = dec10_alux_m(dc, CC_OP_CMP);
+                insn_len = dec10_alux_m(env, dc, CC_OP_CMP);
                 break;
             case CRISV10_IND_MUL:
                 /* This is a reg insn coded in the mem indir space.  */
@@ -1044,12 +1100,12 @@ static unsigned int dec10_ind(DisasContext *dc)
                 dec10_reg_mul(dc, size, dc->ir & (1 << 10));
                 break;
             case CRISV10_IND_BDAP_M:
-                insn_len = dec10_bdap_m(dc, size);
+                insn_len = dec10_bdap_m(env, dc, size);
                 break;
             default:
                 LOG_DIS("pc=%x var-ind.%d %d r%d r%d\n",
                           dc->pc, size, dc->opcode, dc->src, dc->dst);
-                assert(0);
+                cpu_abort(dc->env, "Unhandled opcode");
                 break;
         }
         return insn_len;
@@ -1057,28 +1113,29 @@ static unsigned int dec10_ind(DisasContext *dc)
 
     switch (dc->opcode) {
         case CRISV10_IND_MOVE_M_SPR:
-            insn_len = dec10_ind_move_m_pr(dc);
+            insn_len = dec10_ind_move_m_pr(env, dc);
             break;
         case CRISV10_IND_MOVE_SPR_M:
             insn_len = dec10_ind_move_pr_m(dc);
             break;
         case CRISV10_IND_JUMP_M:
             if (dc->src == 15) {
-                LOG_DIS("jump.%d %d r%d r%d\n", size,
+                LOG_DIS("jump.%d %d r%d r%d direct\n", size,
                          dc->opcode, dc->src, dc->dst);
-                imm = ldl_code(dc->pc + 2);
+                imm = cpu_ldl_code(env, dc->pc + 2);
                 if (dc->mode == CRISV10_MODE_AUTOINC)
                     insn_len += size;
 
                 t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len));
-                tcg_gen_movi_tl(env_btarget, imm);
-                cris_prepare_jmp(dc, JMP_INDIRECT);
+                dc->jmp_pc = imm;
+                cris_prepare_jmp(dc, JMP_DIRECT);
                 dc->delayed_branch--; /* v10 has no dslot here.  */
             } else {
                 if (dc->dst == 14) {
                     LOG_DIS("break %d\n", dc->src);
                     cris_evaluate_flags(dc);
                     tcg_gen_movi_tl(env_pc, dc->pc + 2);
+                    t_gen_mov_env_TN(trap_vector, tcg_const_tl(dc->src + 2));
                     t_gen_raise_exception(EXCP_BREAK);
                     dc->is_jmp = DISAS_UPDATE;
                     return insn_len;
@@ -1114,24 +1171,24 @@ static unsigned int dec10_ind(DisasContext *dc)
             dc->delayed_branch--; /* v10 has no dslot here.  */
             break;
         case CRISV10_IND_MOVX:
-            insn_len = dec10_alux_m(dc, CC_OP_MOVE);
+            insn_len = dec10_alux_m(env, dc, CC_OP_MOVE);
             break;
         case CRISV10_IND_ADDX:
-            insn_len = dec10_alux_m(dc, CC_OP_ADD);
+            insn_len = dec10_alux_m(env, dc, CC_OP_ADD);
             break;
         case CRISV10_IND_SUBX:
-            insn_len = dec10_alux_m(dc, CC_OP_SUB);
+            insn_len = dec10_alux_m(env, dc, CC_OP_SUB);
             break;
         case CRISV10_IND_CMPX:
-            insn_len = dec10_alux_m(dc, CC_OP_CMP);
+            insn_len = dec10_alux_m(env, dc, CC_OP_CMP);
             break;
         case CRISV10_IND_DIP:
-            insn_len = dec10_dip(dc);
+            insn_len = dec10_dip(env, dc);
             break;
         case CRISV10_IND_BCC_M:
 
             cris_cc_mask(dc, 0);
-            imm = ldsw_code(dc->pc + 2);
+            imm = cpu_ldsw_code(env, dc->pc + 2);
             simm = (int16_t)imm;
             simm += 4;
 
@@ -1141,14 +1198,14 @@ static unsigned int dec10_ind(DisasContext *dc)
             break;
         default:
             LOG_DIS("ERROR pc=%x opcode=%d\n", dc->pc, dc->opcode);
-            assert(0);
+            cpu_abort(dc->env, "Unhandled opcode");
             break;
     }
 
     return insn_len;
 }
 
-static unsigned int crisv10_decoder(DisasContext *dc)
+static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc)
 {
     unsigned int insn_len = 2;
 
@@ -1156,7 +1213,7 @@ static unsigned int crisv10_decoder(DisasContext *dc)
         tcg_gen_debug_insn_start(dc->pc);
 
     /* Load a halfword onto the instruction register.  */
-    dc->ir = lduw_code(dc->pc);
+    dc->ir = cpu_lduw_code(env, dc->pc);
 
     /* Now decode it.  */
     dc->opcode   = EXTRACT_FIELD(dc->ir, 6, 9);
@@ -1181,63 +1238,66 @@ static unsigned int crisv10_decoder(DisasContext *dc)
             break;
         case CRISV10_MODE_AUTOINC:
         case CRISV10_MODE_INDIRECT:
-            insn_len = dec10_ind(dc);
+            insn_len = dec10_ind(env, dc);
             break;
     }
 
     if (dc->clear_prefix && dc->tb_flags & PFIX_FLAG) {
         dc->tb_flags &= ~PFIX_FLAG;
         tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~PFIX_FLAG);
-        dc->cpustate_changed = 1;
+        if (dc->tb_flags != dc->tb->flags) {
+            dc->cpustate_changed = 1;
+        }
     }
 
+    /* CRISv10 locks out interrupts on dslots.  */
+    if (dc->delayed_branch == 2) {
+        cris_lock_irq(dc);
+    }
     return insn_len;
 }
 
-static CPUCRISState *cpu_crisv10_init (CPUState *env)
+void cris_initialize_crisv10_tcg(void)
 {
        int i;
 
        cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
        cc_x = tcg_global_mem_new(TCG_AREG0,
-                                 offsetof(CPUState, cc_x), "cc_x");
+                                 offsetof(CPUCRISState, cc_x), "cc_x");
        cc_src = tcg_global_mem_new(TCG_AREG0,
-                                   offsetof(CPUState, cc_src), "cc_src");
+                                   offsetof(CPUCRISState, cc_src), "cc_src");
        cc_dest = tcg_global_mem_new(TCG_AREG0,
-                                    offsetof(CPUState, cc_dest),
+                                    offsetof(CPUCRISState, cc_dest),
                                     "cc_dest");
        cc_result = tcg_global_mem_new(TCG_AREG0,
-                                      offsetof(CPUState, cc_result),
+                                      offsetof(CPUCRISState, cc_result),
                                       "cc_result");
        cc_op = tcg_global_mem_new(TCG_AREG0,
-                                  offsetof(CPUState, cc_op), "cc_op");
+                                  offsetof(CPUCRISState, cc_op), "cc_op");
        cc_size = tcg_global_mem_new(TCG_AREG0,
-                                    offsetof(CPUState, cc_size),
+                                    offsetof(CPUCRISState, cc_size),
                                     "cc_size");
        cc_mask = tcg_global_mem_new(TCG_AREG0,
-                                    offsetof(CPUState, cc_mask),
+                                    offsetof(CPUCRISState, cc_mask),
                                     "cc_mask");
 
        env_pc = tcg_global_mem_new(TCG_AREG0, 
-                                   offsetof(CPUState, pc),
+                                   offsetof(CPUCRISState, pc),
                                    "pc");
        env_btarget = tcg_global_mem_new(TCG_AREG0,
-                                        offsetof(CPUState, btarget),
+                                        offsetof(CPUCRISState, btarget),
                                         "btarget");
        env_btaken = tcg_global_mem_new(TCG_AREG0,
-                                        offsetof(CPUState, btaken),
+                                        offsetof(CPUCRISState, btaken),
                                         "btaken");
        for (i = 0; i < 16; i++) {
                cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
-                                             offsetof(CPUState, regs[i]),
+                                             offsetof(CPUCRISState, regs[i]),
                                              regnames_v10[i]);
        }
        for (i = 0; i < 16; i++) {
                cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
-                                              offsetof(CPUState, pregs[i]),
+                                              offsetof(CPUCRISState, pregs[i]),
                                               pregnames_v10[i]);
        }
-
-       return env;
 }
-