qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [4594] CRIS: Restructure the translator to allow for better


From: Edgar E. Iglesias
Subject: [Qemu-devel] [4594] CRIS: Restructure the translator to allow for better code generation .
Date: Tue, 27 May 2008 21:10:57 +0000

Revision: 4594
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4594
Author:   edgar_igl
Date:     2008-05-27 21:10:56 +0000 (Tue, 27 May 2008)

Log Message:
-----------
CRIS: Restructure the translator to allow for better code generation.

Modified Paths:
--------------
    trunk/target-cris/cpu.h
    trunk/target-cris/helper.c
    trunk/target-cris/helper.h
    trunk/target-cris/op_helper.c
    trunk/target-cris/translate.c

Modified: trunk/target-cris/cpu.h
===================================================================
--- trunk/target-cris/cpu.h     2008-05-27 21:05:21 UTC (rev 4593)
+++ trunk/target-cris/cpu.h     2008-05-27 21:10:56 UTC (rev 4594)
@@ -120,8 +120,7 @@
        uint32_t cc_result;
        /* size of the operation, 1 = byte, 2 = word, 4 = dword.  */
        int cc_size;
-       /* Extended arithmetics.  */
-       int cc_x_live;
+       /* X flag at the time of cc snapshot.  */
        int cc_x;
 
        int exception_index;
@@ -130,10 +129,6 @@
        int fault_vector;
        int trap_vector;
 
-       uint32_t debug1;
-       uint32_t debug2;
-       uint32_t debug3;
-
        /* FIXME: add a check in the translator to avoid writing to support
           register sets beyond the 4th. The ISA allows up to 256! but in
           practice there is no core that implements more than 4.
@@ -177,20 +172,14 @@
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_cris_signal_handler(int host_signum, void *pinfo,
                            void *puc);
-void cpu_cris_flush_flags(CPUCRISState *, int);
-
-
 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
                           int is_asi);
 
 enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
     CC_OP_FLAGS,
-    CC_OP_LOGIC,
     CC_OP_CMP,
     CC_OP_MOVE,
-    CC_OP_MOVE_PD,
-    CC_OP_MOVE_SD,
     CC_OP_ADD,
     CC_OP_ADDC,
     CC_OP_MCP,
@@ -213,32 +202,6 @@
     CC_OP_LZ
 };
 
-#define CCF_C 0x01
-#define CCF_V 0x02
-#define CCF_Z 0x04
-#define CCF_N 0x08
-#define CCF_X 0x10
-
-#define CRIS_SSP    0
-#define CRIS_USP    1
-
-void cris_set_irq_level(CPUCRISState *env, int level, uint8_t vector);
-void cris_set_macsr(CPUCRISState *env, uint32_t val);
-void cris_switch_sp(CPUCRISState *env);
-
-void do_cris_semihosting(CPUCRISState *env, int nr);
-
-enum cris_features {
-    CRIS_FEATURE_CF_ISA_MUL,
-};
-
-static inline int cris_feature(CPUCRISState *env, int feature)
-{
-    return (env->features & (1u << feature)) != 0;
-}
-
-void register_cris_insns (CPUCRISState *env);
-
 /* CRIS uses 8k pages.  */
 #define TARGET_PAGE_BITS 13
 #define MMAP_SHIFT TARGET_PAGE_BITS

Modified: trunk/target-cris/helper.c
===================================================================
--- trunk/target-cris/helper.c  2008-05-27 21:05:21 UTC (rev 4593)
+++ trunk/target-cris/helper.c  2008-05-27 21:10:56 UTC (rev 4594)
@@ -42,9 +42,8 @@
                              int mmu_idx, int is_softmmu)
 {
        env->exception_index = 0xaa;
-       env->debug1 = address;
+       env->pregs[PR_EDA] = address;
        cpu_dump_state(env, stderr, fprintf, 0);
-       env->pregs[PR_ERP] = env->pc;
        return 1;
 }
 

Modified: trunk/target-cris/helper.h
===================================================================
--- trunk/target-cris/helper.h  2008-05-27 21:05:21 UTC (rev 4593)
+++ trunk/target-cris/helper.h  2008-05-27 21:10:56 UTC (rev 4594)
@@ -2,7 +2,6 @@
 
 void TCG_HELPER_PROTO helper_raise_exception(uint32_t index);
 void TCG_HELPER_PROTO helper_tlb_flush_pid(uint32_t pid);
-void TCG_HELPER_PROTO helper_tlb_flush(void);
 void TCG_HELPER_PROTO helper_dump(uint32_t a0, uint32_t a1, uint32_t a2);
 void TCG_HELPER_PROTO helper_dummy(void);
 void TCG_HELPER_PROTO helper_rfe(void);
@@ -18,3 +17,4 @@
 void TCG_HELPER_PROTO helper_evaluate_flags_move_4 (void);
 void TCG_HELPER_PROTO helper_evaluate_flags_move_2 (void);
 void TCG_HELPER_PROTO helper_evaluate_flags (void);
+void TCG_HELPER_PROTO helper_top_evaluate_flags(void);

Modified: trunk/target-cris/op_helper.c
===================================================================
--- trunk/target-cris/op_helper.c       2008-05-27 21:05:21 UTC (rev 4593)
+++ trunk/target-cris/op_helper.c       2008-05-27 21:10:56 UTC (rev 4594)
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include "exec.h"
 #include "mmu.h"
+#include "helper.h"
 
 #define MMUSUFFIX _mmu
 
@@ -67,6 +68,9 @@
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
                 cpu_restore_state(tb, env, pc, NULL);
+
+               /* Evaluate flags after retranslation.  */
+                helper_top_evaluate_flags();
             }
         }
         cpu_loop_exit();
@@ -87,13 +91,8 @@
 #endif
 }
 
-void helper_tlb_flush(void)
+void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2)
 {
-       tlb_flush(env, 1);
-}
-
-void helper_dump(uint32_t a0, uint32_t a1)
-{
        (fprintf(logfile, "%s: a0=%x a1=%x\n", __func__, a0, a1)); 
 }
 
@@ -236,13 +235,7 @@
        int x;
 
        /* Extended arithmetics, leave the z flag alone.  */
-       env->debug3 = env->pregs[PR_CCS];
-
-       if (env->cc_x_live)
-               x = env->cc_x;
-       else
-               x = env->pregs[PR_CCS] & X_FLAG;
-
+       x = env->cc_x;
        if ((x || env->cc_op == CC_OP_ADDC)
            && flags & Z_FLAG)
                env->cc_mask &= ~Z_FLAG;
@@ -359,8 +352,24 @@
 
        src = env->cc_src;
        dst = env->cc_dest;
-       res = env->cc_result;
 
+       /* Reconstruct the result.  */
+       switch (env->cc_op)
+       {
+               case CC_OP_SUB:
+                       res = dst - src;
+                       break;
+               case CC_OP_ADD:
+                       res = dst + src;
+                       break;
+               default:
+                       res = env->cc_result;
+                       break;
+       }
+
+       if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
+               src = ~src;
+
        if ((res & 0x80000000L) != 0L)
        {
                flags |= N_FLAG;
@@ -396,11 +405,9 @@
 
 void  helper_evaluate_flags_move_4 (void)
 {
-       uint32_t src;
        uint32_t res;
        uint32_t flags = 0;
 
-       src = env->cc_src;
        res = env->cc_result;
 
        if ((int32_t)res < 0)
@@ -440,6 +447,8 @@
        dst = env->cc_dest;
        res = env->cc_result;
 
+       if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
+               src = ~src;
 
        /* Now, evaluate the flags. This stuff is based on
           Per Zander's CRISv10 simulator.  */
@@ -548,3 +557,55 @@
        }
        evaluate_flags_writeback(flags);
 }
+
+void helper_top_evaluate_flags(void)
+{
+       switch (env->cc_op)
+       {
+               case CC_OP_MCP:
+                       helper_evaluate_flags_mcp();
+                       break;
+               case CC_OP_MULS:
+                       helper_evaluate_flags_muls();
+                       break;
+               case CC_OP_MULU:
+                       helper_evaluate_flags_mulu();
+                       break;
+               case CC_OP_MOVE:
+               case CC_OP_AND:
+               case CC_OP_OR:
+               case CC_OP_XOR:
+               case CC_OP_ASR:
+               case CC_OP_LSR:
+               case CC_OP_LSL:
+                       switch (env->cc_size)
+                       {
+                               case 4:
+                                       helper_evaluate_flags_move_4();
+                                       break;
+                               case 2:
+                                       helper_evaluate_flags_move_2();
+                                       break;
+                               default:
+                                       helper_evaluate_flags();
+                                       break;
+                       }
+                       break;
+               case CC_OP_FLAGS:
+                       /* live.  */
+                       break;
+               default:
+               {
+                       switch (env->cc_size)
+                       {
+                               case 4:
+                                       helper_evaluate_flags_alu_4();
+                                       break;
+                               default:
+                                       helper_evaluate_flags();
+                                       break;
+                       }
+               }
+               break;
+       }
+}

Modified: trunk/target-cris/translate.c
===================================================================
--- trunk/target-cris/translate.c       2008-05-27 21:05:21 UTC (rev 4593)
+++ trunk/target-cris/translate.c       2008-05-27 21:10:56 UTC (rev 4594)
@@ -65,6 +65,7 @@
 TCGv cpu_T[2];
 TCGv cpu_R[16];
 TCGv cpu_PR[16];
+TCGv cc_x;
 TCGv cc_src;
 TCGv cc_dest;
 TCGv cc_result;
@@ -93,12 +94,16 @@
        int cc_op;
        int cc_size;
        uint32_t cc_mask;
-       int flags_live; /* Wether or not $ccs is uptodate.  */
-       int flagx_live; /* Wether or not flags_x has the x flag known at
-                          translation time.  */
+
+       int cc_size_uptodate; /* -1 invalid or last written value.  */
+
+       int cc_x_uptodate;  /* 1 - ccs, 2 - known | X_FLAG. 0 not uptodate.  */
+       int flags_uptodate; /* Wether or not $ccs is uptodate.  */
+       int flagx_known; /* Wether or not flags_x has the x flag known at
+                           translation time.  */
        int flags_x;
+
        int clear_x; /* Clear x after this insn?  */
-
        int user; /* user or kernel mode.  */
        int is_jmp;
 
@@ -267,8 +272,8 @@
        tcg_gen_shri_i64(t0, t0, 32);
        tcg_gen_trunc_i64_i32(d2, t0);
 
-       tcg_gen_discard_i64(t0);
-       tcg_gen_discard_i64(t1);
+       tcg_temp_free(t0);
+       tcg_temp_free(t1);
 }
 
 /* 64-bit unsigned muls, lower result in d and upper in d2.  */
@@ -287,8 +292,8 @@
        tcg_gen_shri_i64(t0, t0, 32);
        tcg_gen_trunc_i64_i32(d2, t0);
 
-       tcg_gen_discard_i64(t0);
-       tcg_gen_discard_i64(t1);
+       tcg_temp_free(t0);
+       tcg_temp_free(t1);
 }
 
 /* 32bit branch-free binary search for counting leading zeros.  */
@@ -354,15 +359,16 @@
        tcg_gen_addi_i32(d, n, 2);
        tcg_gen_sub_i32(d, d, m);
 
-       tcg_gen_discard_i32(y);
-       tcg_gen_discard_i32(m);
-       tcg_gen_discard_i32(n);
+       tcg_temp_free(y);
+       tcg_temp_free(m);
+       tcg_temp_free(n);
 }
 
-static void t_gen_btst(TCGv d, TCGv s)
+static void t_gen_btst(TCGv d, TCGv a, TCGv b)
 {
         TCGv sbit;
         TCGv bset;
+        TCGv t0;
        int l1;
 
         /* des ref:
@@ -390,18 +396,19 @@
        l1 = gen_new_label();
         sbit = tcg_temp_new(TCG_TYPE_TL);
         bset = tcg_temp_new(TCG_TYPE_TL);
+        t0 = tcg_temp_new(TCG_TYPE_TL);
 
         /* Compute bset and sbit.  */
-        tcg_gen_andi_tl(sbit, s, 31);
-        tcg_gen_shl_tl(s, tcg_const_tl(1), sbit);
-        tcg_gen_and_tl(bset, d, s);
+        tcg_gen_andi_tl(sbit, b, 31);
+        tcg_gen_shl_tl(t0, tcg_const_tl(1), sbit);
+        tcg_gen_and_tl(bset, a, t0);
         tcg_gen_shr_tl(bset, bset, sbit);
        /* Displace to N_FLAG.  */
         tcg_gen_shli_tl(bset, bset, 3);
 
         tcg_gen_shl_tl(sbit, tcg_const_tl(2), sbit);
         tcg_gen_subi_tl(sbit, sbit, 1);
-        tcg_gen_and_tl(sbit, d, sbit);
+        tcg_gen_and_tl(sbit, a, sbit);
 
         tcg_gen_andi_tl(d, cpu_PR[PR_CCS], ~(X_FLAG | N_FLAG | Z_FLAG));
        /* or in the N_FLAG.  */
@@ -411,11 +418,11 @@
        tcg_gen_ori_tl(d, d, Z_FLAG);
        gen_set_label(l1);
 
-        tcg_gen_discard_tl(sbit);
-        tcg_gen_discard_tl(bset);
+        tcg_temp_free(sbit);
+        tcg_temp_free(bset);
 }
 
-static void t_gen_cris_dstep(TCGv d, TCGv s)
+static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
 {
        int l1;
 
@@ -426,9 +433,9 @@
         * if (d >= s)
         *    d -= s;
         */
-       tcg_gen_shli_tl(d, d, 1);
-       tcg_gen_brcond_tl(TCG_COND_LTU, d, s, l1);
-       tcg_gen_sub_tl(d, d, s);
+       tcg_gen_shli_tl(d, a, 1);
+       tcg_gen_brcond_tl(TCG_COND_LTU, d, b, l1);
+       tcg_gen_sub_tl(d, d, b);
        gen_set_label(l1);
 }
 
@@ -444,32 +451,56 @@
        if (flag)
                tcg_gen_shri_tl(c, c, flag);
        tcg_gen_add_tl(d, d, c);
-       tcg_gen_discard_tl(c);
+       tcg_temp_free(c);
 }
 
-static inline void t_gen_addx_carry(TCGv d)
+static inline void t_gen_addx_carry(DisasContext *dc, TCGv d)
 {
-       TCGv x, c;
+       if (dc->flagx_known) {
+               if (dc->flags_x) {
+                       TCGv c;
+            
+                       c = tcg_temp_new(TCG_TYPE_TL);
+                       t_gen_mov_TN_preg(c, PR_CCS);
+                       /* C flag is already at bit 0.  */
+                       tcg_gen_andi_tl(c, c, C_FLAG);
+                       tcg_gen_add_tl(d, d, c);
+                       tcg_temp_free(c);
+               }
+       } else {
+               TCGv x, c;
 
-       x = tcg_temp_new(TCG_TYPE_TL);
-       c = tcg_temp_new(TCG_TYPE_TL);
-       t_gen_mov_TN_preg(x, PR_CCS);
-       tcg_gen_mov_tl(c, x);
+               x = tcg_temp_new(TCG_TYPE_TL);
+               c = tcg_temp_new(TCG_TYPE_TL);
+               t_gen_mov_TN_preg(x, PR_CCS);
+               tcg_gen_mov_tl(c, x);
 
-       /* Propagate carry into d if X is set. Branch free.  */
-       tcg_gen_andi_tl(c, c, C_FLAG);
-       tcg_gen_andi_tl(x, x, X_FLAG);
-       tcg_gen_shri_tl(x, x, 4);
+               /* Propagate carry into d if X is set. Branch free.  */
+               tcg_gen_andi_tl(c, c, C_FLAG);
+               tcg_gen_andi_tl(x, x, X_FLAG);
+               tcg_gen_shri_tl(x, x, 4);
 
-       tcg_gen_and_tl(x, x, c);
-       tcg_gen_add_tl(d, d, x);        
-       tcg_gen_discard_tl(x);
-       tcg_gen_discard_tl(c);
+               tcg_gen_and_tl(x, x, c);
+               tcg_gen_add_tl(d, d, x);        
+               tcg_temp_free(x);
+               tcg_temp_free(c);
+       }
 }
 
 static inline void t_gen_subx_carry(DisasContext *dc, TCGv d)
 {
-       if (dc->flagx_live) {
+       if (dc->flagx_known) {
+               if (dc->flags_x) {
+                       TCGv c;
+            
+                       c = tcg_temp_new(TCG_TYPE_TL);
+                       t_gen_mov_TN_preg(c, PR_CCS);
+                       /* C flag is already at bit 0.  */
+                       tcg_gen_andi_tl(c, c, C_FLAG);
+                       tcg_gen_sub_tl(d, d, c);
+                       tcg_temp_free(c);
+               }
+       } else {
                TCGv x, c;
 
                x = tcg_temp_new(TCG_TYPE_TL);
@@ -484,18 +515,8 @@
 
                tcg_gen_and_tl(x, x, c);
                tcg_gen_sub_tl(d, d, x);
-               tcg_gen_discard_tl(x);
-               tcg_gen_discard_tl(c);
-       } else {
-               if (dc->flags_x) {
-                       TCGv c;
-               
-                       c = tcg_temp_new(TCG_TYPE_TL);
-                       /* C flag is already at bit 0.  */
-                       tcg_gen_andi_tl(c, c, C_FLAG);
-                       tcg_gen_add_tl(d, d, c);
-                       tcg_gen_discard_tl(c);
-               }
+               tcg_temp_free(x);
+               tcg_temp_free(c);
        }
 }
 
@@ -515,8 +536,8 @@
        tcg_gen_shri_tl(t, org_s, 8);
        tcg_gen_andi_tl(t, t, 0x00ff00ff);
        tcg_gen_or_tl(d, d, t);
-       tcg_gen_discard_tl(t);
-       tcg_gen_discard_tl(org_s);
+       tcg_temp_free(t);
+       tcg_temp_free(org_s);
 }
 
 /* Swap the halfwords of the s operand.  */
@@ -529,7 +550,7 @@
        tcg_gen_shli_tl(d, t, 16);
        tcg_gen_shri_tl(t, t, 16);
        tcg_gen_or_tl(d, d, t);
-       tcg_gen_discard_tl(t);
+       tcg_temp_free(t);
 }
 
 /* Reverse the within each byte.
@@ -576,8 +597,8 @@
                tcg_gen_andi_tl(t, t,  bitrev[i].mask);
                tcg_gen_or_tl(d, d, t);
        }
-       tcg_gen_discard_tl(t);
-       tcg_gen_discard_tl(org_s);
+       tcg_temp_free(t);
+       tcg_temp_free(org_s);
 }
 
 static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
@@ -595,7 +616,7 @@
        tcg_gen_mov_tl(env_pc, pc_true);
        gen_set_label(l1);
 
-       tcg_gen_discard_tl(btaken);
+       tcg_temp_free(btaken);
 }
 
 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
@@ -627,21 +648,25 @@
 
 static inline void cris_clear_x_flag(DisasContext *dc)
 {
-       if (!dc->flagx_live 
-           || (dc->flagx_live && dc->flags_x)
-           || dc->cc_op == CC_OP_FLAGS)
-               tcg_gen_andi_i32(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG);
-       dc->flagx_live = 1;
+       dc->flagx_known = 1;
        dc->flags_x = 0;
 }
 
-static void cris_evaluate_flags(DisasContext *dc)
+static void cris_flush_cc_state(DisasContext *dc)
 {
-       if (!dc->flags_live) {
-               tcg_gen_movi_tl(cc_op, dc->cc_op);
+       if (dc->cc_size_uptodate != dc->cc_size) {
                tcg_gen_movi_tl(cc_size, dc->cc_size);
-               tcg_gen_movi_tl(cc_mask, dc->cc_mask);
+               dc->cc_size_uptodate = dc->cc_size;
+       }
+       tcg_gen_movi_tl(cc_op, dc->cc_op);
+       tcg_gen_movi_tl(cc_mask, dc->cc_mask);
+}
 
+static void cris_evaluate_flags(DisasContext *dc)
+{
+       if (!dc->flags_uptodate) {
+               cris_flush_cc_state(dc);
+
                switch (dc->cc_op)
                {
                        case CC_OP_MCP:
@@ -654,6 +679,12 @@
                                tcg_gen_helper_0_0(helper_evaluate_flags_mulu);
                                break;
                        case CC_OP_MOVE:
+                       case CC_OP_AND:
+                       case CC_OP_OR:
+                       case CC_OP_XOR:
+                       case CC_OP_ASR:
+                       case CC_OP_LSR:
+                       case CC_OP_LSL:
                                switch (dc->cc_size)
                                {
                                        case 4:
@@ -684,7 +715,7 @@
                        }
                        break;
                }
-               dc->flags_live = 1;
+               dc->flags_uptodate = 1;
        }
 }
 
@@ -705,132 +736,144 @@
        if (mask == 0)
                dc->update_cc = 0;
        else
-               dc->flags_live = 0;
+               dc->flags_uptodate = 0;
 }
 
 static void cris_update_cc_op(DisasContext *dc, int op, int size)
 {
        dc->cc_op = op;
        dc->cc_size = size;
-       dc->flags_live = 0;
+       dc->flags_uptodate = 0;
 }
 
-/* op is the operation.
-   T0, T1 are the operands.
-   dst is the destination reg.
-*/
-static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
+static inline void cris_update_cc_x(DisasContext *dc)
 {
-       int writeback = 1;
+       /* Save the x flag state at the time of the cc snapshot.  */
+       if (dc->flagx_known) {
+               if (dc->cc_x_uptodate == (2 | dc->flags_x))
+                       return;
+               tcg_gen_movi_tl(cc_x, dc->flags_x);
+               dc->cc_x_uptodate = 2 | dc->flags_x;
+       }
+       else {
+               tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG);
+               dc->cc_x_uptodate = 1;
+       }
+}
+
+/* Update cc prior to executing ALU op. Needs source operands untouched.  */
+static void cris_pre_alu_update_cc(DisasContext *dc, int op, 
+                                  TCGv dst, TCGv src, int size)
+{
        if (dc->update_cc) {
                cris_update_cc_op(dc, op, size);
-               if (op != CC_OP_MOVE)
-                       tcg_gen_mov_tl(cc_dest, cpu_T[0]);
+               tcg_gen_mov_tl(cc_src, src);
 
-               /* FIXME: This shouldn't be needed. But we don't pass the
-                  tests without it. Investigate.  */
-               t_gen_mov_env_TN(cc_x_live, tcg_const_tl(dc->flagx_live));
-               t_gen_mov_env_TN(cc_x, tcg_const_tl(dc->flags_x));
+               if (op != CC_OP_MOVE
+                   && op != CC_OP_AND
+                   && op != CC_OP_OR
+                   && op != CC_OP_XOR
+                   && op != CC_OP_ASR
+                   && op != CC_OP_LSR
+                   && op != CC_OP_LSL)
+                       tcg_gen_mov_tl(cc_dest, dst);
+
+               cris_update_cc_x(dc);
        }
+}
 
+/* Update cc after executing ALU op. needs the result.  */
+static inline void cris_update_result(DisasContext *dc, TCGv res)
+{
+       if (dc->update_cc) {
+               if (dc->cc_size == 4 && 
+                   (dc->cc_op == CC_OP_SUB
+                    || dc->cc_op == CC_OP_ADD))
+                       return;
+               tcg_gen_mov_tl(cc_result, res);
+       }
+}
+
+/* Returns one if the write back stage should execute.  */
+static void cris_alu_op_exec(DisasContext *dc, int op, 
+                              TCGv dst, TCGv a, TCGv b, int size)
+{
        /* Emit the ALU insns.  */
        switch (op)
        {
                case CC_OP_ADD:
-                       tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
+                       tcg_gen_add_tl(dst, a, b);
                        /* Extended arithmetics.  */
-                       t_gen_addx_carry(cpu_T[0]);
+                       t_gen_addx_carry(dc, dst);
                        break;
                case CC_OP_ADDC:
-                       tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                       t_gen_add_flag(cpu_T[0], 0); /* C_FLAG.  */
+                       tcg_gen_add_tl(dst, a, b);
+                       t_gen_add_flag(dst, 0); /* C_FLAG.  */
                        break;
                case CC_OP_MCP:
-                       tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                       t_gen_add_flag(cpu_T[0], 8); /* R_FLAG.  */
+                       tcg_gen_add_tl(dst, a, b);
+                       t_gen_add_flag(dst, 8); /* R_FLAG.  */
                        break;
                case CC_OP_SUB:
-                       tcg_gen_neg_tl(cpu_T[1], cpu_T[1]);
-                       tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                       tcg_gen_neg_tl(cpu_T[1], cpu_T[1]);
-                       /* CRIS flag evaluation needs ~src.  */
-                       tcg_gen_not_tl(cpu_T[1], cpu_T[1]);
-
+                       tcg_gen_sub_tl(dst, a, b);
                        /* Extended arithmetics.  */
-                       t_gen_subx_carry(dc, cpu_T[0]);
+                       t_gen_subx_carry(dc, dst);
                        break;
                case CC_OP_MOVE:
-                       tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
+                       tcg_gen_mov_tl(dst, b);
                        break;
                case CC_OP_OR:
-                       tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
+                       tcg_gen_or_tl(dst, a, b);
                        break;
                case CC_OP_AND:
-                       tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
+                       tcg_gen_and_tl(dst, a, b);
                        break;
                case CC_OP_XOR:
-                       tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
+                       tcg_gen_xor_tl(dst, a, b);
                        break;
                case CC_OP_LSL:
-                       t_gen_lsl(cpu_T[0], cpu_T[0], cpu_T[1]);
+                       t_gen_lsl(dst, a, b);
                        break;
                case CC_OP_LSR:
-                       t_gen_lsr(cpu_T[0], cpu_T[0], cpu_T[1]);
+                       t_gen_lsr(dst, a, b);
                        break;
                case CC_OP_ASR:
-                       t_gen_asr(cpu_T[0], cpu_T[0], cpu_T[1]);
+                       t_gen_asr(dst, a, b);
                        break;
                case CC_OP_NEG:
-                       tcg_gen_neg_tl(cpu_T[0], cpu_T[1]);
+                       tcg_gen_neg_tl(dst, b);
                        /* Extended arithmetics.  */
-                       t_gen_subx_carry(dc, cpu_T[0]);
+                       t_gen_subx_carry(dc, dst);
                        break;
                case CC_OP_LZ:
-                       t_gen_lz_i32(cpu_T[0], cpu_T[1]);
+                       t_gen_lz_i32(dst, b);
                        break;
                case CC_OP_BTST:
-                       t_gen_btst(cpu_T[0], cpu_T[1]);
-                       writeback = 0;
+                       t_gen_btst(dst, a, b);
                        break;
                case CC_OP_MULS:
-               {
-                       TCGv mof;
-                       mof = tcg_temp_new(TCG_TYPE_TL);
-                       t_gen_muls(cpu_T[0], mof, cpu_T[0], cpu_T[1]);
-                       t_gen_mov_preg_TN(dc, PR_MOF, mof);
-                       tcg_gen_discard_tl(mof);
-               }
-               break;
+                       t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
+                       break;
                case CC_OP_MULU:
-               {
-                       TCGv mof;
-                       mof = tcg_temp_new(TCG_TYPE_TL);
-                       t_gen_mulu(cpu_T[0], mof, cpu_T[0], cpu_T[1]);
-                       t_gen_mov_preg_TN(dc, PR_MOF, mof);
-                       tcg_gen_discard_tl(mof);
-               }
-               break;
+                       t_gen_mulu(dst, cpu_PR[PR_MOF], a, b);
+                       break;
                case CC_OP_DSTEP:
-                       t_gen_cris_dstep(cpu_T[0], cpu_T[1]);
+                       t_gen_cris_dstep(dst, a, b);
                        break;
                case CC_OP_BOUND:
                {
                        int l1;
                        l1 = gen_new_label();
-                       tcg_gen_brcond_tl(TCG_COND_LEU, 
-                                         cpu_T[0], cpu_T[1], l1);
-                       tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
+                       tcg_gen_mov_tl(dst, a);
+                       tcg_gen_brcond_tl(TCG_COND_LEU, a, b, l1);
+                       tcg_gen_mov_tl(dst, b);
                        gen_set_label(l1);
                }
                break;
                case CC_OP_CMP:
-                       tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                       /* CRIS flag evaluation needs ~src.  */
-                       tcg_gen_not_tl(cpu_T[1], cpu_T[1]);
-
+                       tcg_gen_sub_tl(dst, a, b);
                        /* Extended arithmetics.  */
-                       t_gen_subx_carry(dc, cpu_T[0]);
-                       writeback = 0;
+                       t_gen_subx_carry(dc, dst);
                        break;
                default:
                        fprintf (logfile, "illegal ALU op.\n");
@@ -838,40 +881,58 @@
                        break;
        }
 
-       if (dc->update_cc)
-               tcg_gen_mov_tl(cc_src, cpu_T[1]);
-
        if (size == 1)
-               tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
+               tcg_gen_andi_tl(dst, dst, 0xff);
        else if (size == 2)
-               tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
+               tcg_gen_andi_tl(dst, dst, 0xffff);
+}
 
+static void cris_alu(DisasContext *dc, int op,
+                              TCGv d, TCGv op_a, TCGv op_b, int size)
+{
+       TCGv tmp;
+       int writeback;
+
+       writeback = 1;
+       tmp = cpu_T[0];
+       if (op == CC_OP_CMP)
+               writeback = 0;
+       else if (size == 4) {
+               tmp = d;
+               writeback = 0;
+       }
+
+       cris_pre_alu_update_cc(dc, op, op_a, op_b, size);
+       cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);
+       cris_update_result(dc, tmp);
+
        /* Writeback.  */
        if (writeback) {
-               if (size == 4)
-                       tcg_gen_mov_tl(cpu_R[rd], cpu_T[0]);
-               else {
-                       if (size == 1)
-                               tcg_gen_andi_tl(cpu_R[rd], cpu_R[rd], ~0xff);
-                       else
-                               tcg_gen_andi_tl(cpu_R[rd], cpu_R[rd], ~0xffff);
-                       tcg_gen_or_tl(cpu_R[rd], cpu_R[rd], cpu_T[0]);
-               }
+               if (size == 1)
+                       tcg_gen_andi_tl(d, d, ~0xff);
+               else
+                       tcg_gen_andi_tl(d, d, ~0xffff);
+               tcg_gen_or_tl(d, d, tmp);
        }
-       if (dc->update_cc)
-               tcg_gen_mov_tl(cc_result, cpu_T[0]);
 }
 
 static int arith_cc(DisasContext *dc)
 {
        if (dc->update_cc) {
                switch (dc->cc_op) {
+                       case CC_OP_ADDC: return 1;
                        case CC_OP_ADD: return 1;
                        case CC_OP_SUB: return 1;
+                       case CC_OP_DSTEP: return 1;
                        case CC_OP_LSL: return 1;
                        case CC_OP_LSR: return 1;
                        case CC_OP_ASR: return 1;
                        case CC_OP_CMP: return 1;
+                       case CC_OP_NEG: return 1;
+                       case CC_OP_OR: return 1;
+                       case CC_OP_XOR: return 1;
+                       case CC_OP_MULU: return 1;
+                       case CC_OP_MULS: return 1;
                        default:
                                return 0;
                }
@@ -893,7 +954,7 @@
         * When this function is done, T0 should be non-zero if the condition
         * code is true.
         */
-       arith_opt = arith_cc(dc) && !dc->flags_live;
+       arith_opt = arith_cc(dc) && !dc->flags_uptodate;
        switch (cond) {
                case CC_EQ:
                        if (arith_opt) {
@@ -982,7 +1043,7 @@
                                tcg_gen_and_tl(cpu_T[0], tmp, cpu_T[0]);
                                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], Z_FLAG);
 
-                               tcg_gen_discard_tl(tmp);
+                               tcg_temp_free(tmp);
                        }
                        break;
                case CC_GE:
@@ -1022,8 +1083,8 @@
                                tcg_gen_and_tl(cpu_T[0], z, n);
                                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2);
 
-                               tcg_gen_discard_tl(n);
-                               tcg_gen_discard_tl(z);
+                               tcg_temp_free(n);
+                               tcg_temp_free(z);
                        }
                        break;
                case CC_LE:
@@ -1043,8 +1104,8 @@
                                tcg_gen_or_tl(cpu_T[0], z, n);
                                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2);
 
-                               tcg_gen_discard_tl(n);
-                               tcg_gen_discard_tl(z);
+                               tcg_temp_free(n);
+                               tcg_temp_free(z);
                        }
                        break;
                case CC_P:
@@ -1089,7 +1150,6 @@
 {
        int mem_index = cpu_mmu_index(dc->env);
 
-       cris_evaluate_flags(dc);
        if (size == 1) {
                if (sign)
                        tcg_gen_qemu_ld8s(dst, addr, mem_index);
@@ -1103,7 +1163,7 @@
                        tcg_gen_qemu_ld16u(dst, addr, mem_index);
        }
        else {
-               tcg_gen_qemu_ld32s(dst, addr, mem_index);
+               tcg_gen_qemu_ld32u(dst, addr, mem_index);
        }
 }
 
@@ -1112,8 +1172,6 @@
 {
        int mem_index = cpu_mmu_index(dc->env);
 
-       cris_evaluate_flags(dc);
-
        /* Remember, operands are flipped. CRIS has reversed order.  */
        if (size == 1)
                tcg_gen_qemu_st8(val, addr, mem_index);
@@ -1129,7 +1187,7 @@
                tcg_gen_ext8s_i32(d, s);
        else if (size == 2)
                tcg_gen_ext16s_i32(d, s);
-       else
+       else if(d != s)
                tcg_gen_mov_tl(d, s);
 }
 
@@ -1139,7 +1197,7 @@
                tcg_gen_ext8u_i32(d, s);
        else if (size == 2)
                tcg_gen_ext16u_i32(d, s);
-       else
+       else if (d != s)
                tcg_gen_mov_tl(d, s);
 }
 
@@ -1158,12 +1216,12 @@
 }
 #endif
 
-static unsigned int memsize_z(DisasContext *dc)
+static inline unsigned int memsize_z(DisasContext *dc)
 {
        return dc->zsize + 1;
 }
 
-static unsigned int memsize_zz(DisasContext *dc)
+static inline unsigned int memsize_zz(DisasContext *dc)
 {
        switch (dc->zzsize)
        {
@@ -1180,13 +1238,13 @@
                tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size);
 }
 
-static void dec_prep_move_r(DisasContext *dc, int rs, int rd,
-                           int size, int s_ext)
+static inline void dec_prep_move_r(DisasContext *dc, int rs, int rd,
+                           int size, int s_ext, TCGv dst)
 {
        if (s_ext)
-               t_gen_sext(cpu_T[1], cpu_R[rs], size);
+               t_gen_sext(dst, cpu_R[rs], size);
        else
-               t_gen_zext(cpu_T[1], cpu_R[rs], size);
+               t_gen_zext(dst, cpu_R[rs], size);
 }
 
 /* Prepare T0 and T1 for a register alu operation.
@@ -1195,7 +1253,7 @@
 static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
                          int size, int s_ext)
 {
-       dec_prep_move_r(dc, rs, rd, size, s_ext);
+       dec_prep_move_r(dc, rs, rd, size, s_ext, cpu_T[1]);
 
        if (s_ext)
                t_gen_sext(cpu_T[0], cpu_R[rd], size);
@@ -1203,7 +1261,8 @@
                t_gen_zext(cpu_T[0], cpu_R[rd], size);
 }
 
-static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize)
+static int dec_prep_move_m(DisasContext *dc, int s_ext, int memsize,
+                          TCGv dst)
 {
        unsigned int rs, rd;
        uint32_t imm;
@@ -1237,14 +1296,15 @@
                        
                DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n",
                             imm, rd, s_ext, memsize));
-               tcg_gen_movi_tl(cpu_T[1], imm);
+               tcg_gen_movi_tl(dst, imm);
                dc->postinc = 0;
        } else {
-               gen_load(dc, cpu_T[1], cpu_R[rs], memsize, 0);
+               cris_flush_cc_state(dc);
+               gen_load(dc, dst, cpu_R[rs], memsize, 0);
                if (s_ext)
-                       t_gen_sext(cpu_T[1], cpu_T[1], memsize);
+                       t_gen_sext(dst, dst, memsize);
                else
-                       t_gen_zext(cpu_T[1], cpu_T[1], memsize);
+                       t_gen_zext(dst, dst, memsize);
        }
        return insn_len;
 }
@@ -1256,7 +1316,7 @@
 {
        int insn_len;
 
-       insn_len = dec_prep_move_m(dc, s_ext, memsize);
+       insn_len = dec_prep_move_m(dc, s_ext, memsize, cpu_T[1]);
 
        /* put dest in T0.  */
        tcg_gen_mov_tl(cpu_T[0], cpu_R[dc->op2]);
@@ -1317,10 +1377,9 @@
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
 
        cris_cc_mask(dc, CC_MASK_NZVC);
-       /* Fetch register operand,  */
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], dc->op1);
-       crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
        return 2;
 }
 static unsigned int dec_moveq(DisasContext *dc)
@@ -1341,10 +1400,8 @@
        DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZVC);
-       /* Fetch register operand,  */
-       tcg_gen_mov_tl(cpu_T[0], cpu_R[dc->op2]);
-       tcg_gen_movi_tl(cpu_T[1], dc->op1);
-       crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+       cris_alu(dc, CC_OP_SUB,
+                   cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
        return 2;
 }
 static unsigned int dec_cmpq(DisasContext *dc)
@@ -1355,9 +1412,9 @@
 
        DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZVC);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], imm);
-       crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_CMP,
+                   cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
        return 2;
 }
 static unsigned int dec_andq(DisasContext *dc)
@@ -1368,9 +1425,9 @@
 
        DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], imm);
-       crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_AND,
+                   cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
        return 2;
 }
 static unsigned int dec_orq(DisasContext *dc)
@@ -1380,9 +1437,9 @@
        imm = sign_extend(dc->op1, 5);
        DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], imm);
-       crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_OR,
+                   cpu_R[dc->op2], cpu_R[dc->op2], tcg_const_tl(imm), 4);
        return 2;
 }
 static unsigned int dec_btstq(DisasContext *dc)
@@ -1391,13 +1448,13 @@
        DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZ);
+
        t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], dc->op1);
-       crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
-
+       cris_alu(dc, CC_OP_BTST,
+                   cpu_T[0], cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
        cris_update_cc_op(dc, CC_OP_FLAGS, 4);
        t_gen_mov_preg_TN(dc, PR_CCS, cpu_T[0]);
-       dc->flags_live = 1;
+       dc->flags_uptodate = 1;
        return 2;
 }
 static unsigned int dec_asrq(DisasContext *dc)
@@ -1405,9 +1462,10 @@
        dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
        DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], dc->op1);
-       crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_ASR,
+                   cpu_R[dc->op2],
+                   cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
        return 2;
 }
 static unsigned int dec_lslq(DisasContext *dc)
@@ -1416,9 +1474,10 @@
        DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZ);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], dc->op1);
-       crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_LSL,
+                   cpu_R[dc->op2],
+                   cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
        return 2;
 }
 static unsigned int dec_lsrq(DisasContext *dc)
@@ -1427,9 +1486,10 @@
        DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZ);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       tcg_gen_movi_tl(cpu_T[1], dc->op1);
-       crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_LSR,
+                   cpu_R[dc->op2],
+                   cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
        return 2;
 }
 
@@ -1441,8 +1501,19 @@
                    memsize_char(size), dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZ);
-       dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, size);
+       if (size == 4) {
+               dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
+               cris_cc_mask(dc, CC_MASK_NZ);
+               cris_update_cc_op(dc, CC_OP_MOVE, 4);
+               cris_update_cc_x(dc);
+               cris_update_result(dc, cpu_R[dc->op2]);
+       }
+       else {
+               dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_T[1]);
+               cris_alu(dc, CC_OP_MOVE,
+                        cpu_R[dc->op2],
+                        cpu_R[dc->op2], cpu_T[1], size);
+       }
        return 2;
 }
 
@@ -1480,7 +1551,10 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_AND, dc->op2, size);
+
+       cris_alu(dc, CC_OP_AND,
+                   cpu_R[dc->op2],
+                   cpu_R[dc->op2], cpu_T[1], size);
        return 2;
 }
 
@@ -1490,7 +1564,8 @@
                    dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
-       crisv32_alu_op(dc, CC_OP_LZ, dc->op2, 4);
+       cris_alu(dc, CC_OP_LZ,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        return 2;
 }
 
@@ -1503,7 +1578,9 @@
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
        tcg_gen_andi_tl(cpu_T[1], cpu_T[1], 63);
-       crisv32_alu_op(dc, CC_OP_LSL, dc->op2, size);
+
+       cris_alu(dc, CC_OP_LSL,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1516,7 +1593,9 @@
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
        tcg_gen_andi_tl(cpu_T[1], cpu_T[1], 63);
-       crisv32_alu_op(dc, CC_OP_LSR, dc->op2, size);
+
+       cris_alu(dc, CC_OP_LSR,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1529,7 +1608,9 @@
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
        tcg_gen_andi_tl(cpu_T[1], cpu_T[1], 63);
-       crisv32_alu_op(dc, CC_OP_ASR, dc->op2, size);
+
+       cris_alu(dc, CC_OP_ASR,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1541,8 +1622,9 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZV);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
-       t_gen_sext(cpu_T[0], cpu_T[0], size);
-       crisv32_alu_op(dc, CC_OP_MULS, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_MULS,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        return 2;
 }
 
@@ -1554,8 +1636,9 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZV);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       t_gen_zext(cpu_T[0], cpu_T[0], size);
-       crisv32_alu_op(dc, CC_OP_MULU, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_MULU,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        return 2;
 }
 
@@ -1564,9 +1647,8 @@
 {
        DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
-       t_gen_mov_TN_reg(cpu_T[1], dc->op1);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       crisv32_alu_op(dc, CC_OP_DSTEP, dc->op2, 4);
+       cris_alu(dc, CC_OP_DSTEP,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
        return 2;
 }
 
@@ -1578,7 +1660,9 @@
        BUG_ON(size != 4); /* xor is dword.  */
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_XOR, dc->op2, 4);
+
+       cris_alu(dc, CC_OP_XOR,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        return 2;
 }
 
@@ -1588,11 +1672,9 @@
        DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n",
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
-       /* TODO: needs optmimization.  */
-       dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       /* rd should be 4.  */
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
+       dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_T[1]);
+       cris_alu(dc, CC_OP_BOUND,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        return 2;
 }
 
@@ -1603,7 +1685,9 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZVC);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_CMP, dc->op2, size);
+
+       cris_alu(dc, CC_OP_CMP,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1614,14 +1698,15 @@
        DIS(fprintf (logfile, "abs $r%u, $r%u\n",
                    dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
-       dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0);
+       dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0, cpu_T[1]);
 
        /* TODO: consider a branch free approach.  */
        l1 = gen_new_label();
        tcg_gen_brcondi_tl(TCG_COND_GE, cpu_T[1], 0, l1);
        tcg_gen_neg_tl(cpu_T[1], cpu_T[1]);
        gen_set_label(l1);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+       cris_alu(dc, CC_OP_MOVE,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        return 2;
 }
 
@@ -1632,7 +1717,9 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZVC);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_ADD, dc->op2, size);
+
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1643,7 +1730,8 @@
        cris_evaluate_flags(dc);
        cris_cc_mask(dc, CC_MASK_NZVC);
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
-       crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
+       cris_alu(dc, CC_OP_ADDC,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        return 2;
 }
 
@@ -1653,9 +1741,8 @@
                     dc->op2, dc->op1));
        cris_evaluate_flags(dc);
        cris_cc_mask(dc, CC_MASK_RNZV);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op1);
-       t_gen_mov_TN_preg(cpu_T[1], dc->op2);
-       crisv32_alu_op(dc, CC_OP_MCP, dc->op1, 4);
+       cris_alu(dc, CC_OP_MCP,
+                   cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
        return 2;
 }
 
@@ -1693,8 +1780,9 @@
                t_gen_swapb(cpu_T[0], cpu_T[0]);
        if (dc->op2 & 1)
                t_gen_swapr(cpu_T[0], cpu_T[0]);
-       tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
+       cris_alu(dc, CC_OP_MOVE,
+                   cpu_R[dc->op1], cpu_R[dc->op1], cpu_T[0], 4);
+
        return 2;
 }
 
@@ -1705,7 +1793,9 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_OR, dc->op2, size);
+
+       cris_alu(dc, CC_OP_OR,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1714,10 +1804,8 @@
        DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
                    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
        cris_cc_mask(dc, 0);
-       dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
-       t_gen_lsl(cpu_T[0], cpu_T[0], tcg_const_tl(dc->zzsize));
-       tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-       t_gen_mov_reg_TN(dc->op1, cpu_T[0]);
+       tcg_gen_shl_tl(cpu_T[0], cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
+       tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], cpu_T[0]);
        return 2;
 }
 
@@ -1726,11 +1814,8 @@
        DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
                  memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
        cris_cc_mask(dc, 0);
-       dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
-       t_gen_lsl(cpu_T[0], cpu_T[0], tcg_const_tl(dc->zzsize));
-       
-       tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-       t_gen_mov_reg_TN(R_ACR, cpu_T[0]);
+       tcg_gen_shl_tl(cpu_T[0], cpu_R[dc->op2], tcg_const_tl(dc->zzsize));
+       tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], cpu_T[0]);
        return 2;
 }
 
@@ -1741,7 +1826,9 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZVC);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_NEG, dc->op2, size);
+
+       cris_alu(dc, CC_OP_NEG,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1751,11 +1838,12 @@
                    dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZ);
        dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
-       crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
 
+       cris_alu(dc, CC_OP_BTST,
+                   cpu_T[0], cpu_T[0], cpu_T[1], 4);
        cris_update_cc_op(dc, CC_OP_FLAGS, 4);
        t_gen_mov_preg_TN(dc, PR_CCS, cpu_T[0]);
-       dc->flags_live = 1;
+       dc->flags_uptodate = 1;
        return 2;
 }
 
@@ -1766,7 +1854,8 @@
                    memsize_char(size), dc->op1, dc->op2));
        cris_cc_mask(dc, CC_MASK_NZVC);
        dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_SUB, dc->op2, size);
+       cris_alu(dc, CC_OP_SUB,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], size);
        return 2;
 }
 
@@ -1779,8 +1868,9 @@
                    dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZ);
-       dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+       dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_T[1]);
+       cris_alu(dc, CC_OP_MOVE,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        return 2;
 }
 
@@ -1795,8 +1885,9 @@
        cris_cc_mask(dc, CC_MASK_NZ);
        t_gen_mov_TN_reg(cpu_T[0], dc->op1);
        /* Size can only be qi or hi.  */
-       t_gen_sext(cpu_T[1], cpu_T[0], size);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+       t_gen_sext(cpu_T[1], cpu_R[dc->op1], size);
+       cris_alu(dc, CC_OP_MOVE,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        return 2;
 }
 
@@ -1809,11 +1900,10 @@
                    dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZVC);
-       t_gen_mov_TN_reg(cpu_T[1], dc->op1);
        /* Size can only be qi or hi.  */
-       t_gen_zext(cpu_T[1], cpu_T[1], size);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+       t_gen_zext(cpu_T[1], cpu_R[dc->op1], size);
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        return 2;
 }
 
@@ -1826,12 +1916,10 @@
                    dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZVC);
-       t_gen_mov_TN_reg(cpu_T[1], dc->op1);
        /* Size can only be qi or hi.  */
-       t_gen_sext(cpu_T[1], cpu_T[1], size);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-
-       crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+       t_gen_sext(cpu_T[1], cpu_R[dc->op1], size);
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        return 2;
 }
 
@@ -1844,11 +1932,10 @@
                    dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZVC);
-       t_gen_mov_TN_reg(cpu_T[1], dc->op1);
        /* Size can only be qi or hi.  */
-       t_gen_zext(cpu_T[1], cpu_T[1], size);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+       t_gen_zext(cpu_T[1], cpu_R[dc->op1], size);
+       cris_alu(dc, CC_OP_SUB,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        return 2;
 }
 
@@ -1861,11 +1948,10 @@
                    dc->op1, dc->op2));
 
        cris_cc_mask(dc, CC_MASK_NZVC);
-       t_gen_mov_TN_reg(cpu_T[1], dc->op1);
        /* Size can only be qi or hi.  */
-       t_gen_sext(cpu_T[1], cpu_T[1], size);
-       t_gen_mov_TN_reg(cpu_T[0], dc->op2);
-       crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+       t_gen_sext(cpu_T[1], cpu_R[dc->op1], size);
+       cris_alu(dc, CC_OP_SUB,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        return 2;
 }
 
@@ -1879,6 +1965,7 @@
        DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags));
        if (set && flags == 0) {
                DIS(fprintf (logfile, "nop\n"));
+               return 2;
        } else if (!set && (flags & 0x20)) {
                DIS(fprintf (logfile, "di\n"));
        }
@@ -1889,13 +1976,16 @@
        }
 
        if (set && (flags & X_FLAG)) {
-               dc->flagx_live = 1;
-               dc->flags_x = 1;
+               dc->flagx_known = 1;
+               dc->flags_x = X_FLAG;
+       } else {
+               dc->flagx_known = 0;
        }
 
        /* Simply decode the flags.  */
        cris_evaluate_flags (dc);
        cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+       cris_update_cc_x(dc);
        tcg_gen_movi_tl(cc_op, dc->cc_op);
 
        if (set) {
@@ -1910,7 +2000,7 @@
        else
                tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
 
-       dc->flags_live = 1;
+       dc->flags_uptodate = 1;
        dc->clear_x = 0;
        return 2;
 }
@@ -1953,7 +2043,7 @@
        t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]);
        if (dc->op2 == PR_CCS) {
                cris_update_cc_op(dc, CC_OP_FLAGS, 4);
-               dc->flags_live = 1;
+               dc->flags_uptodate = 1;
        }
        return 2;
 }
@@ -1970,7 +2060,9 @@
                t_gen_mov_TN_preg(cpu_T[1], dc->op2);
        } else
                t_gen_mov_TN_preg(cpu_T[1], dc->op2);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, preg_sizes[dc->op2]);
+       cris_alu(dc, CC_OP_MOVE, 
+                   cpu_R[dc->op1], cpu_R[dc->op1], cpu_T[1],
+                   preg_sizes[dc->op2]);
        return 2;
 }
 
@@ -1983,9 +2075,19 @@
                    dc->op1, dc->postinc ? "+]" : "]",
                    dc->op2));
 
-       insn_len = dec_prep_move_m(dc, 0, memsize);
-       cris_cc_mask(dc, CC_MASK_NZ);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, memsize);
+       if (memsize == 4) {
+               insn_len = dec_prep_move_m(dc, 0, 4, cpu_R[dc->op2]);
+               cris_cc_mask(dc, CC_MASK_NZ);
+               cris_update_cc_op(dc, CC_OP_MOVE, 4);
+               cris_update_cc_x(dc);
+               cris_update_result(dc, cpu_R[dc->op2]);
+       }
+       else {
+               insn_len = dec_prep_move_m(dc, 0, memsize, cpu_T[1]);
+               cris_cc_mask(dc, CC_MASK_NZ);
+               cris_alu(dc, CC_OP_MOVE,
+                           cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], memsize);
+       }
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2002,7 +2104,8 @@
        /* sign extend.  */
        insn_len = dec_prep_alu_m(dc, 1, memsize);
        cris_cc_mask(dc, CC_MASK_NZ);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+       cris_alu(dc, CC_OP_MOVE,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2019,7 +2122,8 @@
        /* sign extend.  */
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2036,7 +2140,8 @@
        /* sign extend.  */
        insn_len = dec_prep_alu_m(dc, 1, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2053,7 +2158,8 @@
        /* sign extend.  */
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+       cris_alu(dc, CC_OP_SUB,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2070,7 +2176,8 @@
        /* sign extend.  */
        insn_len = dec_prep_alu_m(dc, 1, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+       cris_alu(dc, CC_OP_SUB,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2087,7 +2194,8 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZ);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+       cris_alu(dc, CC_OP_MOVE,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2103,7 +2211,8 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
+       cris_alu(dc, CC_OP_CMP,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2119,7 +2228,9 @@
 
        insn_len = dec_prep_alu_m(dc, 1, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
+       cris_alu(dc, CC_OP_CMP,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1],
+                   memsize_zz(dc));
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2135,7 +2246,9 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
+       cris_alu(dc, CC_OP_CMP,
+                   cpu_R[dc->op2], cpu_R[dc->op2], cpu_T[1],
+                   memsize_zz(dc));
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2155,9 +2268,9 @@
        cris_cc_mask(dc, CC_MASK_NZ);
        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
 
-       tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
-       tcg_gen_movi_tl(cpu_T[1], 0);
-       crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
+       cris_alu(dc, CC_OP_CMP,
+                   cpu_R[dc->op2], cpu_T[1], tcg_const_tl(0),
+                   memsize_zz(dc));
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2173,7 +2286,9 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZ);
-       crisv32_alu_op(dc, CC_OP_AND, dc->op2, memsize_zz(dc));
+       cris_alu(dc, CC_OP_AND,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1],
+                   memsize_zz(dc));
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2189,7 +2304,9 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_ADD, dc->op2, memsize_zz(dc));
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1],
+                   memsize_zz(dc));
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2205,7 +2322,8 @@
 
        insn_len = dec_prep_alu_m(dc, 1, memsize);
        cris_cc_mask(dc, 0);
-       crisv32_alu_op(dc, CC_OP_ADD, R_ACR, 4);
+       cris_alu(dc, CC_OP_ADD,
+                   cpu_R[R_ACR], cpu_T[0], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2221,7 +2339,8 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZ);
-       crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
+       cris_alu(dc, CC_OP_BOUND,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2236,7 +2355,8 @@
        cris_evaluate_flags(dc);
        insn_len = dec_prep_alu_m(dc, 0, 4);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
+       cris_alu(dc, CC_OP_ADDC,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], 4);
        do_postinc(dc, 4);
        return insn_len;
 }
@@ -2252,7 +2372,8 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZVC);
-       crisv32_alu_op(dc, CC_OP_SUB, dc->op2, memsize);
+       cris_alu(dc, CC_OP_SUB,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], memsize);
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2268,7 +2389,8 @@
 
        insn_len = dec_prep_alu_m(dc, 0, memsize);
        cris_cc_mask(dc, CC_MASK_NZ);
-       crisv32_alu_op(dc, CC_OP_OR, dc->op2, memsize_zz(dc));
+       cris_alu(dc, CC_OP_OR,
+                   cpu_R[dc->op2], cpu_T[0], cpu_T[1], memsize_zz(dc));
        do_postinc(dc, memsize);
        return insn_len;
 }
@@ -2316,6 +2438,7 @@
        if (dc->op2 == PR_CCS)
                cris_evaluate_flags(dc);
        t_gen_mov_TN_preg(cpu_T[1], dc->op2);
+       cris_flush_cc_state(dc);
        gen_store(dc, cpu_R[dc->op1], cpu_T[1], memsize);
 
        cris_cc_mask(dc, 0);
@@ -2333,6 +2456,7 @@
                    dc->postinc ? "+]" : "]", dc->op2));
 
        /* fetch the address into T0 and T1.  */
+       cris_flush_cc_state(dc);
        for (i = 0; i <= dc->op2; i++) {
                tmp[i] = tcg_temp_new(TCG_TYPE_TL);
                /* Perform the load onto regnum i. Always dword wide.  */
@@ -2342,7 +2466,7 @@
 
        for (i = 0; i <= dc->op2; i++) {
                tcg_gen_mov_tl(cpu_R[i], tmp[i]);
-               tcg_gen_discard_tl(tmp[i]);
+               tcg_temp_free(tmp[i]);
        }
 
        /* writeback the updated pointer value.  */
@@ -2356,20 +2480,27 @@
 
 static unsigned int dec_movem_rm(DisasContext *dc)
 {
+       TCGv tmp;
        int i;
 
        DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
                     dc->postinc ? "+]" : "]"));
 
+       cris_flush_cc_state(dc);
+
+       tmp = tcg_temp_new(TCG_TYPE_TL);
+       tcg_gen_movi_tl(tmp, 4);
+       tcg_gen_mov_tl(cpu_T[0], cpu_R[dc->op1]);
        for (i = 0; i <= dc->op2; i++) {
                /* Displace addr.  */
-               tcg_gen_addi_tl(cpu_T[0], cpu_R[dc->op1], i * 4);
                /* Perform the store.  */
                gen_store(dc, cpu_T[0], cpu_R[i], 4);
+               tcg_gen_add_tl(cpu_T[0], cpu_T[0], tmp);
        }
        if (dc->postinc)
-               tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], i * 4);
+               tcg_gen_mov_tl(cpu_R[dc->op1], cpu_T[0]);
        cris_cc_mask(dc, 0);
+       tcg_temp_free(tmp);
        return 2;
 }
 
@@ -2383,6 +2514,7 @@
                     memsize, dc->op2, dc->op1));
 
        /* prepare store.  */
+       cris_flush_cc_state(dc);
        gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
 
        if (dc->postinc)
@@ -2396,8 +2528,7 @@
        DIS(fprintf (logfile, "lapcq %x, $r%u\n",
                    dc->pc + dc->op1*2, dc->op2));
        cris_cc_mask(dc, 0);
-       tcg_gen_movi_tl(cpu_T[1], dc->pc + dc->op1 * 2);
-       crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+       tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
        return 2;
 }
 
@@ -2443,8 +2574,7 @@
        tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
        if (dc->op2 > 15)
                abort();
-       tcg_gen_movi_tl(cpu_T[0], dc->pc + 4);
-       tcg_gen_mov_tl(cpu_PR[dc->op2], cpu_T[0]);
+       t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4));
 
        cris_prepare_dyn_jmp(dc);
        return 2;
@@ -2827,12 +2957,15 @@
        dc->ppc = pc_start;
        dc->pc = pc_start;
        dc->singlestep_enabled = env->singlestep_enabled;
-       dc->flags_live = 1;
-       dc->flagx_live = 0;
-       dc->flags_x = 0;
+       dc->flags_uptodate = 1;
+       dc->flagx_known = 1;
+       dc->flags_x = tb->flags & X_FLAG;
+       dc->cc_x_uptodate = 0;
        dc->cc_mask = 0;
        dc->update_cc = 0;
+
        cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+       dc->cc_size_uptodate = -1;
 
        /* Decode TB flags.  */
        dc->user = tb->flags & U_FLAG;
@@ -2841,7 +2974,7 @@
        if (loglevel & CPU_LOG_TB_IN_ASM) {
                fprintf(logfile,
                        "srch=%d pc=%x %x bt=%x ds=%lld ccs=%x\n"
-                       "pid=%x usp=%x dbg=%x %x %x\n"
+                       "pid=%x usp=%x\n"
                        "%x.%x.%x.%x\n"
                        "%x.%x.%x.%x\n"
                        "%x.%x.%x.%x\n"
@@ -2850,7 +2983,6 @@
                        env->btarget, tb->flags & 7,
                        env->pregs[PR_CCS], 
                        env->pregs[PR_PID], env->pregs[PR_USP],
-                       env->debug1, env->debug2, env->debug3,
                        env->regs[0], env->regs[1], env->regs[2], env->regs[3],
                        env->regs[4], env->regs[5], env->regs[6], env->regs[7],
                        env->regs[8], env->regs[9],
@@ -2890,6 +3022,8 @@
                }
 
                dc->clear_x = 1;
+               if (unlikely(loglevel & CPU_LOG_TB_OP))
+                       tcg_gen_debug_insn_start(dc->pc);
                insn_len = cris_decoder(dc);
                dc->ppc = dc->pc;
                dc->pc += insn_len;
@@ -2996,13 +3130,12 @@
                return;
 
        cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
-                   "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n"
-                   "debug=%x %x %x\n",
+                   "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
                    env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
                    env->cc_op,
-                   env->cc_src, env->cc_dest, env->cc_result, env->cc_mask,
-                   env->debug1, env->debug2, env->debug3);
+                   env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
 
+
        for (i = 0; i < 16; i++) {
                cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
                if ((i + 1) % 4 == 0)
@@ -3049,38 +3182,40 @@
        cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
 #endif
 
-       cc_src = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
+       cc_x = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+                                 offsetof(CPUState, cc_x), "cc_x");
+       cc_src = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
                                    offsetof(CPUState, cc_src), "cc_src");
-       cc_dest = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
-                                    offsetof(CPUState, cc_dest), 
+       cc_dest = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+                                    offsetof(CPUState, cc_dest),
                                     "cc_dest");
-       cc_result = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
-                                      offsetof(CPUState, cc_result), 
+       cc_result = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+                                      offsetof(CPUState, cc_result),
                                       "cc_result");
-       cc_op = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
+       cc_op = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
                                   offsetof(CPUState, cc_op), "cc_op");
-       cc_size = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
-                                    offsetof(CPUState, cc_size), 
+       cc_size = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+                                    offsetof(CPUState, cc_size),
                                     "cc_size");
-       cc_mask = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
+       cc_mask = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
                                     offsetof(CPUState, cc_mask),
                                     "cc_mask");
 
        env_pc = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
-                                    offsetof(CPUState, pc),
-                                    "pc");
-       env_btarget = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
-                                    offsetof(CPUState, btarget),
-                                    "btarget");
+                                   offsetof(CPUState, pc),
+                                   "pc");
+       env_btarget = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+                                        offsetof(CPUState, btarget),
+                                        "btarget");
 
        for (i = 0; i < 16; i++) {
-               cpu_R[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
-                                             offsetof(CPUState, regs[i]), 
+               cpu_R[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+                                             offsetof(CPUState, regs[i]),
                                              regnames[i]);
        }
        for (i = 0; i < 16; i++) {
-               cpu_PR[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, 
-                                              offsetof(CPUState, pregs[i]), 
+               cpu_PR[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0,
+                                              offsetof(CPUState, pregs[i]),
                                               pregnames[i]);
        }
 
@@ -3089,7 +3224,6 @@
        TCG_HELPER(helper_dump);
        TCG_HELPER(helper_dummy);
 
-       TCG_HELPER(helper_tlb_flush);
        TCG_HELPER(helper_tlb_flush_pid);
        TCG_HELPER(helper_movl_sreg_reg);
        TCG_HELPER(helper_movl_reg_sreg);
@@ -3102,6 +3236,7 @@
        TCG_HELPER(helper_evaluate_flags_move_4);
        TCG_HELPER(helper_evaluate_flags_move_2);
        TCG_HELPER(helper_evaluate_flags);
+       TCG_HELPER(helper_top_evaluate_flags);
 
        cpu_reset(env);
        return env;






reply via email to

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