Merge remote branch 'mst/for_anthony' into staging
diff --git a/cpu-exec.c b/cpu-exec.c
index 0256edf..ab6defc 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -210,8 +210,7 @@
 
 int cpu_exec(CPUState *env1)
 {
-#define DECLARE_HOST_REGS 1
-#include "hostregs_helper.h"
+    host_reg_t saved_env_reg;
     int ret, interrupt_request;
     TranslationBlock *tb;
     uint8_t *tc_ptr;
@@ -222,9 +221,12 @@
 
     cpu_single_env = env1;
 
-    /* first we save global registers */
-#define SAVE_HOST_REGS 1
-#include "hostregs_helper.h"
+    /* the access to env below is actually saving the global register's
+       value, so that files not including target-xyz/exec.h are free to
+       use it.  */
+    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
+    saved_env_reg = (host_reg_t) env;
+    asm("");
     env = env1;
 
 #if defined(TARGET_I386)
@@ -497,7 +499,8 @@
                     }
 #elif defined(TARGET_CRIS)
                     if (interrupt_request & CPU_INTERRUPT_HARD
-                        && (env->pregs[PR_CCS] & I_FLAG)) {
+                        && (env->pregs[PR_CCS] & I_FLAG)
+                        && !env->locked_irq) {
                         env->exception_index = EXCP_IRQ;
                         do_interrupt(env);
                         next_tb = 0;
@@ -668,7 +671,8 @@
 #endif
 
     /* restore global registers */
-#include "hostregs_helper.h"
+    asm("");
+    env = (void *) saved_env_reg;
 
     /* fail safe : never use cpu_single_env outside cpu_exec() */
     cpu_single_env = NULL;
diff --git a/hostregs_helper.h b/hostregs_helper.h
deleted file mode 100644
index 3a0bece..0000000
--- a/hostregs_helper.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  Save/restore host registers.
- *
- *  Copyright (c) 2007 CodeSourcery
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-/* The GCC global register variable extension is used to reserve some
-   host registers for use by generated code.  However only the core parts of
-   the translation engine are compiled with these settings.  We must manually
-   save/restore these registers when called from regular code.
-   It is not sufficient to save/restore T0 et. al. as these may be declared
-   with a datatype smaller than the actual register.  */
-
-#if defined(DECLARE_HOST_REGS)
-
-#define DO_REG(REG)					\
-    register host_reg_t reg_AREG##REG asm(AREG##REG);	\
-    volatile host_reg_t saved_AREG##REG;
-
-#elif defined(SAVE_HOST_REGS)
-
-#define DO_REG(REG)					\
-    __asm__ __volatile__ ("" : "=r" (reg_AREG##REG));	\
-    saved_AREG##REG = reg_AREG##REG;
-
-#else
-
-#define DO_REG(REG)                                     \
-    reg_AREG##REG = saved_AREG##REG;		        \
-    __asm__ __volatile__ ("" : : "r" (reg_AREG##REG));
-
-#endif
-
-#ifdef AREG0
-DO_REG(0)
-#endif
-
-#ifdef AREG1
-DO_REG(1)
-#endif
-
-#ifdef AREG2
-DO_REG(2)
-#endif
-
-#undef SAVE_HOST_REGS
-#undef DECLARE_HOST_REGS
-#undef DO_REG
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 46d5b0e..ebfcd41 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -359,9 +359,14 @@
      *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
      */
     pci_set_word(dev->config + PCI_COMMAND,
-                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-    dev->config[PCI_LATENCY_TIMER] = 0x10;
-    dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
+                 PCI_COMMAND_MEMORY);
+    pci_set_word(dev->config + PCI_STATUS,
+                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
+                 PCI_STATUS_DEVSEL_MEDIUM);
+    pci_set_byte(dev->config + PCI_REVISION_ID, 0x11);
+    pci_set_byte(dev->config + PCI_HEADER_TYPE,
+                 pci_get_byte(dev->config + PCI_HEADER_TYPE) |
+                 PCI_HEADER_TYPE_MULTI_FUNCTION);
 }
 
 PCIBus *pci_apb_init(target_phys_addr_t special_base,
@@ -463,15 +468,14 @@
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
-    d->config[0x04] = 0x06; // command = bus master, pci mem
-    d->config[0x05] = 0x00;
-    d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    d->config[0x07] = 0x03; // status = medium devsel
-    d->config[0x08] = 0x00; // revision
-    d->config[0x09] = 0x00; // programming i/f
+    pci_set_word(d->config + PCI_COMMAND,
+                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+    pci_set_word(d->config + PCI_STATUS,
+                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
+                 PCI_STATUS_DEVSEL_MEDIUM);
     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+    pci_set_byte(d->config + PCI_HEADER_TYPE,
+                 PCI_HEADER_TYPE_NORMAL);
     return 0;
 }
 
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 8d059f1..fb4973b 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -81,9 +81,8 @@
     /* PCI2PCI bridge same values as PearPC - check this */
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_DEC);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_DEC_21154);
-    d->config[0x08] = 0x02; // revision
+    pci_set_byte(d->config + PCI_REVISION_ID, 0x02);
     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
-    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_BRIDGE; // header_type
     return 0;
 }
 
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 6e991e0..3ceb851 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -3,6 +3,9 @@
  *
  * Copyright (c) 2006 Fabrice Bellard
  *
+ * Modifications:
+ *  2010-Feb-14 Artyom Tarasenko : reworked irq generation
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -125,13 +128,19 @@
 {
     DMAState *s = opaque;
     if (level) {
-        DPRINTF("Raise IRQ\n");
         s->dmaregs[0] |= DMA_INTR;
-        qemu_irq_raise(s->irq);
+        if (s->dmaregs[0] & DMA_INTREN) {
+            DPRINTF("Raise IRQ\n");
+            qemu_irq_raise(s->irq);
+        }
     } else {
-        s->dmaregs[0] &= ~DMA_INTR;
-        DPRINTF("Lower IRQ\n");
-        qemu_irq_lower(s->irq);
+        if (s->dmaregs[0] & DMA_INTR) {
+            s->dmaregs[0] &= ~DMA_INTR;
+            if (s->dmaregs[0] & DMA_INTREN) {
+                DPRINTF("Lower IRQ\n");
+                qemu_irq_lower(s->irq);
+            }
+        }
     }
 }
 
@@ -142,8 +151,6 @@
     DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
             s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
     sparc_iommu_memory_read(s->iommu, s->dmaregs[1], buf, len);
-    DPRINTF("Raise IRQ\n");
-    s->dmaregs[0] |= DMA_INTR;
     s->dmaregs[1] += len;
 }
 
@@ -154,8 +161,6 @@
     DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
             s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
     sparc_iommu_memory_write(s->iommu, s->dmaregs[1], buf, len);
-    DPRINTF("Raise IRQ\n");
-    s->dmaregs[0] |= DMA_INTR;
     s->dmaregs[1] += len;
 }
 
@@ -181,9 +186,16 @@
             s->dmaregs[saddr], val);
     switch (saddr) {
     case 0:
-        if (!(val & DMA_INTREN)) {
-            DPRINTF("Lower IRQ\n");
-            qemu_irq_lower(s->irq);
+        if (val & DMA_INTREN) {
+            if (val & DMA_INTR) {
+                DPRINTF("Raise IRQ\n");
+                qemu_irq_raise(s->irq);
+            }
+        } else {
+            if (s->dmaregs[0] & (DMA_INTR | DMA_INTREN)) {
+                DPRINTF("Lower IRQ\n");
+                qemu_irq_lower(s->irq);
+            }
         }
         if (val & DMA_RESET) {
             qemu_irq_raise(s->dev_reset);
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 6090dcc..d77053b 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1252,8 +1252,10 @@
 
     int cmd = (int)tswap32(tflag);
 #ifdef FUTEX_PRIVATE_FLAG
-    if (cmd == FUTEX_PRIVATE_FLAG)
+    if (cmd & FUTEX_PRIVATE_FLAG) {
         gemu_log("FUTEX_PRIVATE_FLAG|");
+        cmd &= ~FUTEX_PRIVATE_FLAG;
+    }
 #endif
     print_op(FUTEX_WAIT)
     print_op(FUTEX_WAKE)
diff --git a/net.c b/net.c
index 8e951ca..029b0d7 100644
--- a/net.c
+++ b/net.c
@@ -812,9 +812,6 @@
     }
 
     nd->used = 1;
-    if (vlan) {
-        nd->vlan->nb_guest_devs++;
-    }
     nb_nics++;
 
     return idx;
@@ -1128,20 +1125,6 @@
     return -1;
 }
 
-void net_client_uninit(NICInfo *nd)
-{
-    if (nd->vlan) {
-        nd->vlan->nb_guest_devs--;
-    }
-    nb_nics--;
-
-    qemu_free(nd->model);
-    qemu_free(nd->name);
-    qemu_free(nd->devaddr);
-
-    nd->used = 0;
-}
-
 static int net_host_check_device(const char *device)
 {
     int i;
@@ -1227,16 +1210,23 @@
 void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
+    VLANClientState *vc;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        VLANClientState *vc;
-
         monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
 
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
             monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
         }
     }
+    monitor_printf(mon, "Devices not on any VLAN:\n");
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        monitor_printf(mon, "  %s: %s", vc->name, vc->info_str);
+        if (vc->peer) {
+            monitor_printf(mon, " peer=%s", vc->peer->name);
+        }
+        monitor_printf(mon, "\n");
+    }
 }
 
 void do_set_link(Monitor *mon, const QDict *qdict)
@@ -1253,6 +1243,7 @@
             }
         }
     }
+    vc = qemu_find_netdev(name);
 done:
 
     if (!vc) {
@@ -1289,20 +1280,41 @@
     }
 }
 
-static void net_check_clients(void)
+void net_check_clients(void)
 {
     VLANState *vlan;
+    VLANClientState *vc;
+    int has_nic, has_host_dev;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
-            continue;
-        if (vlan->nb_guest_devs == 0)
+        QTAILQ_FOREACH(vc, &vlan->clients, next) {
+            switch (vc->info->type) {
+            case NET_CLIENT_TYPE_NIC:
+                has_nic = 1;
+                break;
+            case NET_CLIENT_TYPE_SLIRP:
+            case NET_CLIENT_TYPE_TAP:
+            case NET_CLIENT_TYPE_SOCKET:
+            case NET_CLIENT_TYPE_VDE:
+                has_host_dev = 1;
+                break;
+            default: ;
+            }
+        }
+        if (has_host_dev && !has_nic)
             fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id);
-        if (vlan->nb_host_devs == 0)
+        if (has_nic && !has_host_dev)
             fprintf(stderr,
                     "Warning: vlan %d is not connected to host network\n",
                     vlan->id);
     }
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (!vc->peer) {
+            fprintf(stderr, "Warning: %s %s has no peer\n",
+                    vc->info->type == NET_CLIENT_TYPE_NIC ? "nic" : "netdev",
+                    vc->name);
+        }
+    }
 }
 
 static int net_init_client(QemuOpts *opts, void *dummy)
@@ -1337,8 +1349,6 @@
         return -1;
     }
 
-    net_check_clients();
-
     return 0;
 }
 
diff --git a/net.h b/net.h
index 116bb80..33a1eaf 100644
--- a/net.h
+++ b/net.h
@@ -79,7 +79,6 @@
     int id;
     QTAILQ_HEAD(, VLANClientState) clients;
     QTAILQ_ENTRY(VLANState) next;
-    unsigned int nb_guest_devs, nb_host_devs;
     NetQueue *send_queue;
 };
 
@@ -163,9 +162,9 @@
 extern const char *legacy_bootp_filename;
 
 int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
-void net_client_uninit(NICInfo *nd);
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
+void net_check_clients(void);
 void net_cleanup(void);
 void net_set_boot_mask(int boot_mask);
 void net_host_device_add(Monitor *mon, const QDict *qdict);
diff --git a/net/slirp.c b/net/slirp.c
index 361899b..317cca7 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -738,10 +738,6 @@
         qemu_free(config);
     }
 
-    if (ret != -1 && vlan) {
-        vlan->nb_host_devs++;
-    }
-
     qemu_free(vnet);
 
     return ret;
diff --git a/net/socket.c b/net/socket.c
index 5533737..442a9c7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -569,9 +569,5 @@
         return -1;
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
diff --git a/net/tap-win32.c b/net/tap-win32.c
index b717c17..8370c80 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -714,10 +714,6 @@
         return -1;
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
 
diff --git a/net/tap.c b/net/tap.c
index d3492de..7a7320c 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -449,9 +449,5 @@
         }
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
diff --git a/net/vde.c b/net/vde.c
index 42b4633..0b46fa6 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -127,9 +127,5 @@
         return -1;
     }
 
-    if (vlan) {
-        vlan->nb_host_devs++;
-    }
-
     return 0;
 }
diff --git a/qemu-common.h b/qemu-common.h
index 192991f..fc32d8d 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -11,6 +11,8 @@
 #define QEMU_WARN_UNUSED_RESULT
 #endif
 
+#define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
+
 /* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that
    cannot include the following headers without conflicts. This condition has
    to be removed once dyngen is gone. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 27001e8..6f40084 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -824,11 +824,10 @@
     env->spsr = cpsr_read(env);
     /* Clear IT bits.  */
     env->condexec_bits = 0;
-    /* Switch to the new mode, and switch to Arm mode.  */
-    /* ??? Thumb interrupt handlers not implemented.  */
+    /* Switch to the new mode, and to the correct instruction set.  */
     env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
     env->uncached_cpsr |= mask;
-    env->thumb = 0;
+    env->thumb = (env->cp15.c1_sys & (1 << 30)) != 0;
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 786c329..8b3b12d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8001,8 +8001,16 @@
                         gen_bx(s, tmp);
                         break;
                     case 5: /* Exception return.  */
-                        /* Unpredictable in user mode.  */
-                        goto illegal_op;
+                        if (IS_USER(s)) {
+                            goto illegal_op;
+                        }
+                        if (rn != 14 || rd != 15) {
+                            goto illegal_op;
+                        }
+                        tmp = load_reg(s, rn);
+                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
+                        gen_exception_return(s, tmp);
+                        break;
                     case 6: /* mrs cpsr.  */
                         tmp = new_tmp();
                         if (IS_M(env)) {
@@ -8898,7 +8906,7 @@
                     shift = CPSR_A | CPSR_I | CPSR_F;
                 else
                     shift = 0;
-                gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
+                gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
             }
             break;
 
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 0626cd8..8ff86d9 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -49,6 +49,7 @@
 #define PR_WZ  4
 #define PR_EXS 5
 #define PR_EDA 6
+#define PR_PREFIX 6    /* On CRISv10 P6 is reserved, we use it as prefix.  */
 #define PR_MOF 7
 #define PR_DZ  8
 #define PR_EBP 9
@@ -62,6 +63,7 @@
 /* CPU flags.  */
 #define Q_FLAG 0x80000000
 #define M_FLAG 0x40000000
+#define PFIX_FLAG 0x800      /* CRISv10 Only.  */
 #define S_FLAG 0x200
 #define R_FLAG 0x100
 #define P_FLAG 0x80
@@ -121,6 +123,8 @@
 	/* X flag at the time of cc snapshot.  */
 	int cc_x;
 
+	/* CRIS has certain insns that lockout interrupts.  */
+	int locked_irq;
 	int interrupt_vector;
 	int fault_vector;
 	int trap_vector;
@@ -180,6 +184,7 @@
     CC_OP_MULS,
     CC_OP_MULU,
     CC_OP_DSTEP,
+    CC_OP_MSTEP,
     CC_OP_BOUND,
 
     CC_OP_OR,
@@ -253,7 +258,11 @@
     *pc = env->pc;
     *cs_base = 0;
     *flags = env->dslot |
-            (env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG | X_FLAG));
+            (env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG
+				     | X_FLAG | PFIX_FLAG));
 }
 
+#define cpu_list cris_cpu_list
+void cris_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
+
 #endif
diff --git a/target-cris/crisv10-decode.h b/target-cris/crisv10-decode.h
new file mode 100644
index 0000000..0d6f3de
--- /dev/null
+++ b/target-cris/crisv10-decode.h
@@ -0,0 +1,108 @@
+/*
+ *  CRISv10 insn decoding macros.
+ *
+ *  Copyright (c) 2010 AXIS Communications AB
+ *  Written by Edgar E. Iglesias.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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
+ */
+
+#define CRISV10_MODE_QIMMEDIATE  0
+#define CRISV10_MODE_REG         1
+#define CRISV10_MODE_INDIRECT    2
+#define CRISV10_MODE_AUTOINC     3
+
+/* Quick Immediate.  */
+#define CRISV10_QIMM_BCC_R0      0
+#define CRISV10_QIMM_BCC_R1      1
+#define CRISV10_QIMM_BCC_R2      2
+#define CRISV10_QIMM_BCC_R3      3
+
+#define CRISV10_QIMM_BDAP_R0     4
+#define CRISV10_QIMM_BDAP_R1     5
+#define CRISV10_QIMM_BDAP_R2     6
+#define CRISV10_QIMM_BDAP_R3     7
+
+#define CRISV10_QIMM_ADDQ        8
+#define CRISV10_QIMM_MOVEQ       9
+#define CRISV10_QIMM_SUBQ       10
+#define CRISV10_QIMM_CMPQ       11
+#define CRISV10_QIMM_ANDQ       12
+#define CRISV10_QIMM_ORQ        13
+#define CRISV10_QIMM_ASHQ       14
+#define CRISV10_QIMM_LSHQ       15
+
+
+#define CRISV10_REG_ADDX         0
+#define CRISV10_REG_MOVX         1
+#define CRISV10_REG_SUBX         2
+#define CRISV10_REG_LSL          3
+#define CRISV10_REG_ADDI         4
+#define CRISV10_REG_BIAP         5
+#define CRISV10_REG_NEG          6
+#define CRISV10_REG_BOUND        7
+#define CRISV10_REG_ADD          8
+#define CRISV10_REG_MOVE_R       9
+#define CRISV10_REG_MOVE_SPR_R   9
+#define CRISV10_REG_MOVE_R_SPR   8
+#define CRISV10_REG_SUB         10
+#define CRISV10_REG_CMP         11
+#define CRISV10_REG_AND         12
+#define CRISV10_REG_OR          13
+#define CRISV10_REG_ASR         14
+#define CRISV10_REG_LSR         15
+
+#define CRISV10_REG_BTST         3
+#define CRISV10_REG_SCC          4
+#define CRISV10_REG_SETF         6
+#define CRISV10_REG_CLEARF       7
+#define CRISV10_REG_BIAP         5
+#define CRISV10_REG_ABS         10
+#define CRISV10_REG_DSTEP       11
+#define CRISV10_REG_LZ          12
+#define CRISV10_REG_NOT         13
+#define CRISV10_REG_SWAP        13
+#define CRISV10_REG_XOR         14
+#define CRISV10_REG_MSTEP       15
+
+/* Indirect, var size.  */
+#define CRISV10_IND_TEST        14
+#define CRISV10_IND_MUL          4
+#define CRISV10_IND_BDAP_M       5
+#define CRISV10_IND_ADD          8
+#define CRISV10_IND_MOVE_M_R     9
+
+
+/* indirect fixed size.  */
+#define CRISV10_IND_ADDX         0
+#define CRISV10_IND_MOVX         1
+#define CRISV10_IND_SUBX         2
+#define CRISV10_IND_CMPX         3
+#define CRISV10_IND_JUMP_M       4
+#define CRISV10_IND_DIP          5
+#define CRISV10_IND_JUMP_R       6
+#define CRISV10_IND_BOUND        7
+#define CRISV10_IND_BCC_M        7
+#define CRISV10_IND_MOVE_M_SPR   8
+#define CRISV10_IND_MOVE_SPR_M   9
+#define CRISV10_IND_SUB         10
+#define CRISV10_IND_CMP         11
+#define CRISV10_IND_AND         12
+#define CRISV10_IND_OR          13
+#define CRISV10_IND_MOVE_R_M    15
+
+#define CRISV10_IND_MOVEM_M_R    14
+#define CRISV10_IND_MOVEM_R_M    15
+
diff --git a/target-cris/helper.c b/target-cris/helper.c
index ff4f2fe..a17a9f0 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -87,10 +87,10 @@
 	if (miss)
 	{
 		if (env->exception_index == EXCP_BUSFAULT)
-			cpu_abort(env, 
+			cpu_abort(env,
 				  "CRIS: Illegal recursive bus fault."
-				  "addr=%x rw=%d\n",
-				  address, rw);
+				 "addr=%x rw=%d\n",
+				 address, rw);
 
 		env->pregs[PR_EDA] = address;
 		env->exception_index = EXCP_BUSFAULT;
@@ -116,10 +116,68 @@
 	return r;
 }
 
+static void do_interruptv10(CPUState *env)
+{
+	int ex_vec = -1;
+
+	D_LOG( "exception index=%d interrupt_req=%d\n",
+		   env->exception_index,
+		   env->interrupt_request);
+
+	assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
+	switch (env->exception_index)
+	{
+		case EXCP_BREAK:
+			/* These exceptions are genereated by the core itself.
+			   ERP should point to the insn following the brk.  */
+			ex_vec = env->trap_vector;
+			env->pregs[PR_ERP] = env->pc;
+			break;
+
+		case EXCP_NMI:
+			/* NMI is hardwired to vector zero.  */
+			ex_vec = 0;
+			env->pregs[PR_CCS] &= ~M_FLAG;
+			env->pregs[PR_NRP] = env->pc;
+			break;
+
+		case EXCP_BUSFAULT:
+			assert(0);
+			break;
+
+		default:
+			/* The interrupt controller gives us the vector.  */
+			ex_vec = env->interrupt_vector;
+			/* Normal interrupts are taken between
+			   TB's.  env->pc is valid here.  */
+			env->pregs[PR_ERP] = env->pc;
+			break;
+	}
+
+	if (env->pregs[PR_CCS] & U_FLAG) {
+		/* Swap stack pointers.  */
+		env->pregs[PR_USP] = env->regs[R_SP];
+		env->regs[R_SP] = env->ksp;
+	}
+
+	/* Now that we are in kernel mode, load the handlers address.  */
+	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
+	env->locked_irq = 1;
+
+	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
+		      __func__, env->pc, ex_vec, 
+		      env->pregs[PR_CCS],
+		      env->pregs[PR_PID], 
+		      env->pregs[PR_ERP]);
+}
+
 void do_interrupt(CPUState *env)
 {
 	int ex_vec = -1;
 
+	if (env->pregs[PR_VR] < 32)
+		return do_interruptv10(env);
+
 	D_LOG( "exception index=%d interrupt_req=%d\n",
 		   env->exception_index,
 		   env->interrupt_request);
@@ -184,8 +242,8 @@
 	/* Now that we are in kernel mode, load the handlers address.  */
 	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
 
-	D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
-		   __func__, env->pc, ex_vec, 
+	D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
+		   __func__, env->pc, ex_vec,
 		   env->pregs[PR_CCS],
 		   env->pregs[PR_PID], 
 		   env->pregs[PR_ERP]);
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index b44b932..a60da94 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -276,6 +276,8 @@
 
 	/* Clear the X, N and Z flags.  */
 	ccs = ccs & ~(X_FLAG | N_FLAG | Z_FLAG);
+	if (env->pregs[PR_VR] < 32)
+		ccs &= ~(V_FLAG | C_FLAG);
 	/* Set the N and Z flags accordingly.  */
 	ccs |= (bset << 3) | (fz << 2);
 	return ccs;
diff --git a/target-cris/translate.c b/target-cris/translate.c
index a236b44..f8baa88 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -86,6 +86,7 @@
 	target_ulong pc, ppc;
 
 	/* Decoder.  */
+	unsigned int (*decoder)(struct DisasContext *dc);
 	uint32_t ir;
 	uint32_t opcode;
 	unsigned int op1;
@@ -94,6 +95,11 @@
 	unsigned int mode;
 	unsigned int postinc;
 
+	unsigned int size;
+	unsigned int src;
+	unsigned int dst;
+	unsigned int cond;
+
 	int update_cc;
 	int cc_op;
 	int cc_size;
@@ -108,6 +114,8 @@
 	int flags_x;
 
 	int clear_x; /* Clear x after this insn?  */
+	int clear_prefix; /* Clear prefix after this insn?  */
+	int clear_locked_irq; /* Clear the irq lockout.  */
 	int cpustate_changed;
 	unsigned int tb_flags; /* tb dependent flags.  */
 	int is_jmp;
@@ -219,6 +227,12 @@
 	}
 }
 
+static void cris_lock_irq(DisasContext *dc)
+{
+	dc->clear_locked_irq = 0;
+	t_gen_mov_env_TN(locked_irq, tcg_const_tl(1));
+}
+
 static inline void t_gen_raise_exception(uint32_t index)
 {
         TCGv_i32 tmp = tcg_const_i32(index);
@@ -332,6 +346,24 @@
 	gen_set_label(l1);
 }
 
+static void t_gen_cris_mstep(TCGv d, TCGv a, TCGv b, TCGv ccs)
+{
+	TCGv t;
+
+	/* 
+	 * d <<= 1
+	 * if (n)
+	 *    d += s;
+	 */
+	t = tcg_temp_new();
+	tcg_gen_shli_tl(d, a, 1);
+	tcg_gen_shli_tl(t, ccs, 31 - 3);
+	tcg_gen_sari_tl(t, t, 31);
+	tcg_gen_and_tl(t, t, b);
+	tcg_gen_add_tl(d, d, t);
+	tcg_temp_free(t);
+}
+
 /* Extended arithmetics on CRIS.  */
 static inline void t_gen_add_flag(TCGv d, int flag)
 {
@@ -634,7 +666,7 @@
 		if (dc->flags_x)
 			tcg_gen_ori_tl(cpu_PR[PR_CCS], 
 				       cpu_PR[PR_CCS], X_FLAG);
-		else
+		else if (dc->cc_op == CC_OP_FLAGS)
 			tcg_gen_andi_tl(cpu_PR[PR_CCS], 
 					cpu_PR[PR_CCS], ~X_FLAG);
         }
@@ -774,6 +806,9 @@
 		case CC_OP_DSTEP:
 			t_gen_cris_dstep(dst, a, b);
 			break;
+		case CC_OP_MSTEP:
+			t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]);
+			break;
 		case CC_OP_BOUND:
 		{
 			int l1;
@@ -878,7 +913,8 @@
 	move_opt = (dc->cc_op == CC_OP_MOVE);
 	switch (cond) {
 		case CC_EQ:
-			if (arith_opt || move_opt) {
+			if ((arith_opt || move_opt)
+			    && dc->cc_x_uptodate != (2 | X_FLAG)) {
 				/* If cc_result is zero, T0 should be 
 				   non-zero otherwise T0 should be zero.  */
 				int l1;
@@ -896,9 +932,10 @@
 			}
 			break;
 		case CC_NE:
-			if (arith_opt || move_opt)
+			if ((arith_opt || move_opt)
+			    && dc->cc_x_uptodate != (2 | X_FLAG)) {
 				tcg_gen_mov_tl(cc, cc_result);
-			else {
+	 		} else {
 				cris_evaluate_flags(dc);
 				tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
 						Z_FLAG);
@@ -1381,7 +1418,7 @@
 	imm = sign_extend(dc->op1, 5);
 	LOG_DIS("moveq %d, $r%u\n", imm, dc->op2);
 
-	tcg_gen_mov_tl(cpu_R[dc->op2], tcg_const_tl(imm));
+	tcg_gen_movi_tl(cpu_R[dc->op2], imm);
 	return 2;
 }
 static unsigned int dec_subq(DisasContext *dc)
@@ -2058,16 +2095,17 @@
 			dc->flags_x = 0;
 	}
 
-	/* Break the TB if the P flag changes.  */
-	if (flags & P_FLAG) {
-		if ((set && !(dc->tb_flags & P_FLAG))
-		    || (!set && (dc->tb_flags & P_FLAG))) {
-			tcg_gen_movi_tl(env_pc, dc->pc + 2);
-			dc->is_jmp = DISAS_UPDATE;
-			dc->cpustate_changed = 1;
-		}
+	/* Break the TB if any of the SPI flag changes.  */
+	if (flags & (P_FLAG | S_FLAG)) {
+		tcg_gen_movi_tl(env_pc, dc->pc + 2);
+		dc->is_jmp = DISAS_UPDATE;
+		dc->cpustate_changed = 1;
 	}
-	if (flags & S_FLAG) {
+
+	/* For the I flag, only act on posedge.  */
+	if ((flags & I_FLAG)) {
+		tcg_gen_movi_tl(env_pc, dc->pc + 2);
+		dc->is_jmp = DISAS_UPDATE;
 		dc->cpustate_changed = 1;
 	}
 
@@ -2143,17 +2181,22 @@
 static unsigned int dec_move_pr(DisasContext *dc)
 {
 	TCGv t0;
-	LOG_DIS("move $p%u, $r%u\n", dc->op1, dc->op2);
+	LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
 	cris_cc_mask(dc, 0);
 
 	if (dc->op2 == PR_CCS)
 		cris_evaluate_flags(dc);
 
-	t0 = tcg_temp_new();
-	t_gen_mov_TN_preg(t0, dc->op2);
-	cris_alu(dc, CC_OP_MOVE,
-		 cpu_R[dc->op1], cpu_R[dc->op1], t0, preg_sizes[dc->op2]);
-	tcg_temp_free(t0);
+        if (dc->op2 == PR_DZ) {
+		tcg_gen_movi_tl(cpu_R[dc->op1], 0);
+        } else {
+		t0 = tcg_temp_new();
+		t_gen_mov_TN_preg(t0, dc->op2);
+		cris_alu(dc, CC_OP_MOVE,
+			 cpu_R[dc->op1], cpu_R[dc->op1], t0,
+			 preg_sizes[dc->op2]);
+		tcg_temp_free(t0);
+	}
 	return 2;
 }
 
@@ -2723,7 +2766,7 @@
 
 	pc = dc->pc;
 	pc += imm;
-	t_gen_mov_reg_TN(rd, tcg_const_tl(pc));
+	tcg_gen_movi_tl(cpu_R[rd], pc);
 	return 6;
 }
 
@@ -3026,8 +3069,7 @@
 	{{0, 0}, dec_null}
 };
 
-static inline unsigned int
-cris_decoder(DisasContext *dc)
+static unsigned int crisv32_decoder(DisasContext *dc)
 {
 	unsigned int insn_len = 2;
 	int i;
@@ -3090,6 +3132,7 @@
 	}
 }
 
+#include "translate_v10.c"
 
 /*
  * Delay slots on QEMU/CRIS.
@@ -3132,7 +3175,7 @@
 {
 	uint16_t *gen_opc_end;
    	uint32_t pc_start;
-	unsigned int insn_len;
+	unsigned int insn_len, orig_flags;
 	int j, lj;
 	struct DisasContext ctx;
 	struct DisasContext *dc = &ctx;
@@ -3143,6 +3186,11 @@
 
 	qemu_log_try_set_file(stderr);
 
+	if (env->pregs[PR_VR] == 32)
+		dc->decoder = crisv32_decoder;
+	else
+		dc->decoder = crisv10_decoder;
+
 	/* Odd PC indicates that branch is rexecuting due to exception in the
 	 * delayslot, like in real hw.
 	 */
@@ -3162,12 +3210,15 @@
 	dc->cc_x_uptodate = 0;
 	dc->cc_mask = 0;
 	dc->update_cc = 0;
+	dc->clear_prefix = 0;
+	dc->clear_locked_irq = 1;
 
 	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
 	dc->cc_size_uptodate = -1;
 
 	/* Decode TB flags.  */
-	dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
+	orig_flags = dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
+					| X_FLAG | PFIX_FLAG);
 	dc->delayed_branch = !!(tb->flags & 7);
 	if (dc->delayed_branch)
 		dc->jmp = JMP_INDIRECT;
@@ -3233,7 +3284,7 @@
                     gen_io_start();
 		dc->clear_x = 1;
 
-		insn_len = cris_decoder(dc);		
+		insn_len = dc->decoder(dc);
 		dc->ppc = dc->pc;
 		dc->pc += insn_len;
 		if (dc->clear_x)
@@ -3271,6 +3322,13 @@
 		 && (dc->pc < next_page_start)
                  && num_insns < max_insns);
 
+	if (dc->tb_flags != orig_flags) {
+		dc->cpustate_changed = 1;
+	}
+
+	if (dc->clear_locked_irq)
+		t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
+
 	npc = dc->pc;
 	if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
 		npc = dc->jmp_pc;
@@ -3330,7 +3388,8 @@
 #ifdef DEBUG_DISAS
 #if !DISAS_CRIS
 	if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
-		log_target_disas(pc_start, dc->pc - pc_start, 0);
+		log_target_disas(pc_start, dc->pc - pc_start,
+                                 dc->env->pregs[PR_VR]);
 		qemu_log("\nisize=%d osize=%zd\n",
 			dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
 	}
@@ -3390,6 +3449,39 @@
 
 }
 
+struct
+{
+    uint32_t vr;
+    const char *name;
+} cris_cores[] = {
+	{8, "crisv8"},
+	{9, "crisv9"},
+	{10, "crisv10"},
+	{11, "crisv11"},
+	{32, "crisv32"},
+};
+
+void cris_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+{
+    unsigned int i;
+
+    (*cpu_fprintf)(f, "Available CPUs:\n");
+    for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
+        (*cpu_fprintf)(f, "  %s\n", cris_cores[i].name);
+    }
+}
+
+static uint32_t vr_by_name(const char *name)
+{
+    unsigned int i;
+    for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
+        if (strcmp(name, cris_cores[i].name) == 0) {
+            return cris_cores[i].vr;
+        }
+    }
+    return 32;
+}
+
 CPUCRISState *cpu_cris_init (const char *cpu_model)
 {
 	CPUCRISState *env;
@@ -3398,6 +3490,7 @@
 
 	env = qemu_mallocz(sizeof(CPUCRISState));
 
+	env->pregs[PR_VR] = vr_by_name(cpu_model);
 	cpu_exec_init(env);
 	cpu_reset(env);
 	qemu_init_vcpu(env);
@@ -3407,6 +3500,15 @@
 
 	tcg_initialized = 1;
 
+#define GEN_HELPER 2
+#include "helper.h"
+
+	if (env->pregs[PR_VR] < 32) {
+		cpu_crisv10_init(env);
+		return env; 
+	}
+
+
 	cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 	cc_x = tcg_global_mem_new(TCG_AREG0,
 				  offsetof(CPUState, cc_x), "cc_x");
@@ -3447,26 +3549,26 @@
 					       pregnames[i]);
 	}
 
-#define GEN_HELPER 2
-#include "helper.h"
-
 	return env;
 }
 
 void cpu_reset (CPUCRISState *env)
 {
+	uint32_t vr;
+
 	if (qemu_loglevel_mask(CPU_LOG_RESET)) {
 		qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
 		log_cpu_state(env, 0);
 	}
 
+	vr = env->pregs[PR_VR];
 	memset(env, 0, offsetof(CPUCRISState, breakpoints));
+	env->pregs[PR_VR] = vr;
 	tlb_flush(env, 1);
 
-	env->pregs[PR_VR] = 32;
 #if defined(CONFIG_USER_ONLY)
 	/* start in user mode with interrupts enabled.  */
-	env->pregs[PR_CCS] |= U_FLAG | I_FLAG;
+	env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG;
 #else
 	cris_mmu_init(env);
 	env->pregs[PR_CCS] = 0;
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
new file mode 100644
index 0000000..9a29c51
--- /dev/null
+++ b/target-cris/translate_v10.c
@@ -0,0 +1,1239 @@
+/*
+ *  CRISv10 emulation for qemu: main translation routines.
+ *
+ *  Copyright (c) 2010 AXIS Communications AB
+ *  Written by Edgar E. Iglesias.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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
+ */
+
+#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",
+};
+
+static const char *pregnames_v10[] =
+{
+    "$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,
+};
+
+static inline int dec10_size(unsigned int size)
+{
+    size++;
+    if (size == 3)
+        size++;
+    return size;
+}
+
+static inline void cris_illegal_insn(DisasContext *dc)
+{
+    qemu_log("illegal insn at pc=%x\n", dc->pc);
+    t_gen_raise_exception(EXCP_BREAK);
+}
+
+/* Prefix flag and register are used to handle the more complex
+   addressing modes.  */
+static void cris_set_prefix(DisasContext *dc)
+{
+    dc->clear_prefix = 0;
+    dc->tb_flags |= PFIX_FLAG;
+    tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], PFIX_FLAG);
+
+    /* prefix insns dont clear the x flag.  */
+    dc->clear_x = 0;
+    cris_lock_irq(dc);
+}
+
+static void crisv10_prepare_memaddr(DisasContext *dc,
+                                    TCGv addr, unsigned int size)
+{
+    if (dc->tb_flags & PFIX_FLAG) {
+        tcg_gen_mov_tl(addr, cpu_PR[PR_PREFIX]);
+    } else {
+        tcg_gen_mov_tl(addr, cpu_R[dc->src]);
+    }
+}
+
+static unsigned int crisv10_post_memaddr(DisasContext *dc, unsigned int size)
+{
+    unsigned int insn_len = 0;
+
+    if (dc->tb_flags & PFIX_FLAG) {
+        if (dc->mode == CRISV10_MODE_AUTOINC) {
+            tcg_gen_mov_tl(cpu_R[dc->src], cpu_PR[PR_PREFIX]);
+        }
+    } else {
+        if (dc->mode == CRISV10_MODE_AUTOINC) {
+            if (dc->src == 15) {
+                insn_len += size & ~1;
+            } else {
+                tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], size);
+            }
+        }
+    }
+    return insn_len;
+}
+
+static int dec10_prep_move_m(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);
+        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)
+{
+    int32_t imm, simm;
+    int op;
+
+    /* sign extend.  */
+    imm = dc->ir & ((1 << 6) - 1);
+    simm = (int8_t) (imm << 2);
+    simm >>= 2;
+    switch (dc->opcode) {
+        case CRISV10_QIMM_BDAP_R0:
+        case CRISV10_QIMM_BDAP_R1:
+        case CRISV10_QIMM_BDAP_R2:
+        case CRISV10_QIMM_BDAP_R3:
+            simm = (int8_t)dc->ir;
+            LOG_DIS("bdap %d $r%d\n", simm, dc->dst);
+            LOG_DIS("pc=%x mode=%x quickimm %d r%d r%d\n",
+                     dc->pc, dc->mode, dc->opcode, dc->src, dc->dst);
+            cris_set_prefix(dc);
+            if (dc->dst == 15) {
+                tcg_gen_movi_tl(cpu_PR[PR_PREFIX], dc->pc + 2 + simm);
+            } else {
+                tcg_gen_addi_tl(cpu_PR[PR_PREFIX], cpu_R[dc->dst], simm);
+            }
+            break;
+
+        case CRISV10_QIMM_MOVEQ:
+            LOG_DIS("moveq %d, $r%d\n", simm, dc->dst);
+
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst],
+                     cpu_R[dc->dst], tcg_const_tl(simm), 4);
+            break;
+        case CRISV10_QIMM_CMPQ:
+            LOG_DIS("cmpq %d, $r%d\n", simm, dc->dst);
+
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst],
+                     cpu_R[dc->dst], tcg_const_tl(simm), 4);
+            break;
+        case CRISV10_QIMM_ADDQ:
+            LOG_DIS("addq %d, $r%d\n", imm, dc->dst);
+
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            cris_alu(dc, CC_OP_ADD, cpu_R[dc->dst],
+                     cpu_R[dc->dst], tcg_const_tl(imm), 4);
+            break;
+        case CRISV10_QIMM_ANDQ:
+            LOG_DIS("andq %d, $r%d\n", simm, dc->dst);
+
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            cris_alu(dc, CC_OP_AND, cpu_R[dc->dst],
+                     cpu_R[dc->dst], tcg_const_tl(simm), 4);
+            break;
+        case CRISV10_QIMM_ASHQ:
+            LOG_DIS("ashq %d, $r%d\n", simm, dc->dst);
+
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            op = imm & (1 << 5);
+            imm &= 0x1f;
+            if (op) {
+                cris_alu(dc, CC_OP_ASR, cpu_R[dc->dst],
+                          cpu_R[dc->dst], tcg_const_tl(imm), 4);
+            } else {
+                /* BTST */
+                cris_update_cc_op(dc, CC_OP_FLAGS, 4);
+                gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst],
+                           tcg_const_tl(imm), cpu_PR[PR_CCS]);
+            }
+            break;
+        case CRISV10_QIMM_LSHQ:
+            LOG_DIS("lshq %d, $r%d\n", simm, dc->dst);
+
+            op = CC_OP_LSL;
+            if (imm & (1 << 5)) {
+                op = CC_OP_LSR; 
+            }
+            imm &= 0x1f;
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            cris_alu(dc, op, cpu_R[dc->dst],
+                     cpu_R[dc->dst], tcg_const_tl(imm), 4);
+            break;
+        case CRISV10_QIMM_SUBQ:
+            LOG_DIS("subq %d, $r%d\n", imm, dc->dst);
+
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            cris_alu(dc, CC_OP_SUB, cpu_R[dc->dst],
+                     cpu_R[dc->dst], tcg_const_tl(imm), 4);
+            break;
+        case CRISV10_QIMM_ORQ:
+            LOG_DIS("andq %d, $r%d\n", simm, dc->dst);
+
+            cris_cc_mask(dc, CC_MASK_NZVC);
+            cris_alu(dc, CC_OP_OR, cpu_R[dc->dst],
+                     cpu_R[dc->dst], tcg_const_tl(simm), 4);
+            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:
+            imm = dc->ir & 0xff;
+            /* bit 0 is a sign bit.  */
+            if (imm & 1) {
+                imm |= 0xffffff00;   /* sign extend.  */
+                imm &= ~1;           /* get rid of the sign bit.  */
+            }
+            imm += 2;
+            LOG_DIS("b%s %d\n", cc_name(dc->cond), imm);
+
+            cris_cc_mask(dc, 0);
+            cris_prepare_cc_branch(dc, imm, dc->cond); 
+            break;
+
+        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);
+            break;
+    }
+    return 2;
+}
+
+static unsigned int dec10_setclrf(DisasContext *dc)
+{
+    uint32_t flags;
+    unsigned int set = ~dc->opcode & 1;
+
+    flags = EXTRACT_FIELD(dc->ir, 0, 3)
+            | (EXTRACT_FIELD(dc->ir, 12, 15) << 4);
+    LOG_DIS("%s set=%d flags=%x\n", __func__, set, flags);
+
+
+    if (flags & X_FLAG) {
+        dc->flagx_known = 1;
+        if (set)
+            dc->flags_x = X_FLAG;
+        else
+            dc->flags_x = 0;
+    }
+
+    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) {
+        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);
+    }
+
+    dc->flags_uptodate = 1;
+    dc->clear_x = 0;
+    cris_lock_irq(dc);
+    return 2;
+}
+
+static inline void dec10_reg_prep_sext(DisasContext *dc, int size, int sext,
+				       TCGv dd, TCGv ds, TCGv sd, TCGv ss)
+{
+    if (sext) {
+        t_gen_sext(dd, sd, size);
+        t_gen_sext(ds, ss, size);
+    } else {
+        t_gen_zext(dd, sd, size);
+        t_gen_zext(ds, ss, size);
+    }
+}
+
+static void dec10_reg_alu(DisasContext *dc, int op, int size, int sext)
+{
+    TCGv t[2];
+
+    t[0] = tcg_temp_new();
+    t[1] = tcg_temp_new();
+    dec10_reg_prep_sext(dc, size, sext,
+                        t[0], t[1], cpu_R[dc->dst], cpu_R[dc->src]);
+
+    if (op == CC_OP_LSL || op == CC_OP_LSR || op == CC_OP_ASR) {
+        tcg_gen_andi_tl(t[1], t[1], 63);
+    }
+
+    assert(dc->dst != 15);
+    cris_alu(dc, op, cpu_R[dc->dst], t[0], t[1], size);
+    tcg_temp_free(t[0]);
+    tcg_temp_free(t[1]);
+}
+
+static void dec10_reg_bound(DisasContext *dc, int size)
+{
+    TCGv t;
+
+    t = tcg_temp_local_new();
+    t_gen_zext(t, cpu_R[dc->src], size);
+    cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[dc->dst], t, 4);
+    tcg_temp_free(t);
+}
+
+static void dec10_reg_mul(DisasContext *dc, int size, int sext)
+{
+    int op = sext ? CC_OP_MULS : CC_OP_MULU;
+    TCGv t[2];
+
+    t[0] = tcg_temp_new();
+    t[1] = tcg_temp_new();
+    dec10_reg_prep_sext(dc, size, sext,
+                        t[0], t[1], cpu_R[dc->dst], cpu_R[dc->src]);
+
+    cris_alu(dc, op, cpu_R[dc->dst], t[0], t[1], 4);
+
+    tcg_temp_free(t[0]);
+    tcg_temp_free(t[1]);
+}
+
+
+static void dec10_reg_movs(DisasContext *dc)
+{
+    int size = (dc->size & 1) + 1;
+    TCGv t;
+
+    LOG_DIS("movx.%d $r%d, $r%d\n", size, dc->src, dc->dst);
+    cris_cc_mask(dc, CC_MASK_NZVC);
+
+    t = tcg_temp_new();
+    if (dc->ir & 32)
+        t_gen_sext(t, cpu_R[dc->src], size);
+    else
+        t_gen_zext(t, cpu_R[dc->src], size);
+
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, 4);
+    tcg_temp_free(t);
+}
+
+static void dec10_reg_alux(DisasContext *dc, int op)
+{
+    int size = (dc->size & 1) + 1;
+    TCGv t;
+
+    LOG_DIS("movx.%d $r%d, $r%d\n", size, dc->src, dc->dst);
+    cris_cc_mask(dc, CC_MASK_NZVC);
+
+    t = tcg_temp_new();
+    if (dc->ir & 32)
+        t_gen_sext(t, cpu_R[dc->src], size);
+    else
+        t_gen_zext(t, cpu_R[dc->src], size);
+
+    cris_alu(dc, op, cpu_R[dc->dst], cpu_R[dc->dst], t, 4);
+    tcg_temp_free(t);
+}
+
+static void dec10_reg_mov_pr(DisasContext *dc)
+{
+    LOG_DIS("move p%d r%d sz=%d\n", dc->dst, dc->src, preg_sizes_v10[dc->dst]);
+    cris_lock_irq(dc);
+    if (dc->src == 15) {
+        tcg_gen_mov_tl(env_btarget, cpu_PR[dc->dst]);
+        cris_prepare_jmp(dc, JMP_INDIRECT);
+        return;
+    }
+    if (dc->dst == PR_CCS) {
+        cris_evaluate_flags(dc); 
+    }
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->src],
+                 cpu_R[dc->src], cpu_PR[dc->dst], preg_sizes_v10[dc->dst]);
+}
+
+static void dec10_reg_abs(DisasContext *dc)
+{
+    TCGv t0;
+
+    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);
+
+    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)
+{
+    TCGv t0;
+
+    LOG_DIS("not $r%d, $r%d\n", dc->src, dc->dst);
+
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    t0 = tcg_temp_new();
+    t_gen_mov_TN_reg(t0, dc->src);
+    if (dc->dst & 8)
+        tcg_gen_not_tl(t0, t0);
+    if (dc->dst & 4)
+        t_gen_swapw(t0, t0);
+    if (dc->dst & 2)
+        t_gen_swapb(t0, t0);
+    if (dc->dst & 1)
+        t_gen_swapr(t0, t0);
+    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->src], cpu_R[dc->src], t0, 4);
+    tcg_temp_free(t0);
+}
+
+static void dec10_reg_scc(DisasContext *dc)
+{
+    int cond = dc->dst;
+
+    LOG_DIS("s%s $r%u\n", cc_name(cond), dc->src);
+
+    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);
+    }
+
+    cris_cc_mask(dc, 0);
+}
+
+static unsigned int dec10_reg(DisasContext *dc)
+{
+    TCGv t;
+    unsigned int insn_len = 2;
+    unsigned int size = dec10_size(dc->size);
+    unsigned int tmp;
+
+    if (dc->size != 3) {
+        switch (dc->opcode) {
+            case CRISV10_REG_MOVE_R:
+                LOG_DIS("move.%d $r%d, $r%d\n", dc->size, dc->src, dc->dst);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_MOVE, size, 0);
+                if (dc->dst == 15) {
+                    tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
+                    cris_prepare_jmp(dc, JMP_INDIRECT);
+                    dc->delayed_branch = 1;
+                }
+                break;
+            case CRISV10_REG_MOVX:
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_movs(dc);
+                break;
+            case CRISV10_REG_ADDX:
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alux(dc, CC_OP_ADD);
+                break;
+            case CRISV10_REG_SUBX:
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alux(dc, CC_OP_SUB);
+                break;
+            case CRISV10_REG_ADD:
+                LOG_DIS("add $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_ADD, size, 0);
+                break;
+            case CRISV10_REG_SUB:
+                LOG_DIS("sub $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_SUB, size, 0);
+                break;
+            case CRISV10_REG_CMP:
+                LOG_DIS("cmp $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_CMP, size, 0);
+                break;
+            case CRISV10_REG_BOUND:
+                LOG_DIS("bound $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_bound(dc, size);
+                break;
+            case CRISV10_REG_AND:
+                LOG_DIS("and $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_AND, size, 0);
+                break;
+            case CRISV10_REG_ADDI:
+                if (dc->src == 15) {
+                    /* nop.  */
+                    return 2;
+                }
+                t = tcg_temp_new();
+                LOG_DIS("addi r%d r%d size=%d\n", dc->src, dc->dst, dc->size);
+                tcg_gen_shli_tl(t, cpu_R[dc->dst], dc->size & 3);
+                tcg_gen_add_tl(cpu_R[dc->src], cpu_R[dc->src], t);
+                tcg_temp_free(t);
+                break;
+            case CRISV10_REG_LSL:
+                LOG_DIS("lsl $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_LSL, size, 0);
+                break;
+            case CRISV10_REG_LSR:
+                LOG_DIS("lsr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_LSR, size, 0);
+                break;
+            case CRISV10_REG_ASR:
+                LOG_DIS("asr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_ASR, size, 1);
+                break;
+            case CRISV10_REG_OR:
+                LOG_DIS("or $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_OR, size, 0);
+                break;
+            case CRISV10_REG_NEG:
+                LOG_DIS("neg $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_NEG, size, 0);
+                break;
+            case CRISV10_REG_BIAP:
+                LOG_DIS("BIAP pc=%x reg %d r%d r%d size=%d\n", dc->pc,
+                         dc->opcode, dc->src, dc->dst, size);
+                switch (size) {
+                    case 4: tmp = 2; break;
+                    case 2: tmp = 1; break;
+                    case 1: tmp = 0; break;
+                    default: assert(0); break;
+                }
+
+                t = tcg_temp_new();
+                tcg_gen_shli_tl(t, cpu_R[dc->dst], tmp);
+                if (dc->src == 15) {
+                    tcg_gen_addi_tl(cpu_PR[PR_PREFIX], t, ((dc->pc +2)| 1) + 1);
+                } else {
+                    tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_R[dc->src], t);
+                }
+                tcg_temp_free(t);
+                cris_set_prefix(dc);
+                break;
+
+            default:
+                LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
+                         dc->opcode, dc->src, dc->dst);
+                assert(0);
+                break;
+        }
+    } else {
+        switch (dc->opcode) {
+            case CRISV10_REG_MOVX:
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_movs(dc);
+                break;
+            case CRISV10_REG_ADDX:
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alux(dc, CC_OP_ADD);
+                break;
+            case CRISV10_REG_SUBX:
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alux(dc, CC_OP_SUB);
+                break;
+            case CRISV10_REG_MOVE_SPR_R:
+                cris_evaluate_flags(dc);
+                cris_cc_mask(dc, 0);
+                dec10_reg_mov_pr(dc);
+                break;
+            case CRISV10_REG_MOVE_R_SPR:
+                LOG_DIS("move r%d p%d\n", dc->src, dc->dst);
+                cris_evaluate_flags(dc);
+                if (dc->src != 11) /* fast for srp.  */
+                    dc->cpustate_changed = 1;
+                t_gen_mov_preg_TN(dc, dc->dst, cpu_R[dc->src]);
+                break;
+            case CRISV10_REG_SETF:
+            case CRISV10_REG_CLEARF:
+                dec10_setclrf(dc);
+                break;
+            case CRISV10_REG_SWAP:
+                dec10_reg_swap(dc);
+                break;
+            case CRISV10_REG_ABS:
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_abs(dc);
+                break;
+            case CRISV10_REG_LZ:
+                LOG_DIS("lz $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_LZ, 4, 0);
+                break;
+            case CRISV10_REG_XOR:
+                LOG_DIS("xor $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_alu(dc, CC_OP_XOR, 4, 0);
+                break;
+            case CRISV10_REG_BTST:
+                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],
+                           cpu_R[dc->src], cpu_PR[PR_CCS]);
+                break;
+            case CRISV10_REG_DSTEP:
+                LOG_DIS("dstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                cris_alu(dc, CC_OP_DSTEP, cpu_R[dc->dst],
+                            cpu_R[dc->dst], cpu_R[dc->src], 4);
+                break;
+            case CRISV10_REG_MSTEP:
+                LOG_DIS("mstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
+                cris_evaluate_flags(dc);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                cris_alu(dc, CC_OP_MSTEP, cpu_R[dc->dst],
+                            cpu_R[dc->dst], cpu_R[dc->src], 4);
+                break;
+            case CRISV10_REG_SCC:
+                dec10_reg_scc(dc);
+                break;
+            default:
+                LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
+                         dc->opcode, dc->src, dc->dst);
+                assert(0);
+                break;
+        }
+    }
+    return insn_len;
+}
+
+static unsigned int dec10_ind_move_m_r(DisasContext *dc, unsigned int size)
+{
+    unsigned int insn_len = 2;
+    TCGv t;
+
+    LOG_DIS("%s: move.%d [$r%d], $r%d\n", __func__,
+             size, dc->src, dc->dst);
+
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    t = tcg_temp_new();
+    insn_len += dec10_prep_move_m(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]);
+        cris_prepare_jmp(dc, JMP_INDIRECT);
+        dc->delayed_branch = 1;
+        return insn_len;
+    }
+
+    tcg_temp_free(t);
+    return insn_len;
+}
+
+static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size)
+{
+    unsigned int insn_len = 2;
+    TCGv addr;
+
+    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);
+    insn_len += crisv10_post_memaddr(dc, size);
+
+    return insn_len;
+}
+
+static unsigned int dec10_ind_move_m_pr(DisasContext *dc)
+{
+    unsigned int insn_len = 2, rd = dc->dst;
+    TCGv t, addr;
+
+    LOG_DIS("move.%d $p%d, [$r%d]\n", dc->size, dc->dst, dc->src);
+    cris_lock_irq(dc);
+
+    addr = tcg_temp_new();
+    t = tcg_temp_new();
+    insn_len += dec10_prep_move_m(dc, 0, 4, t);
+    if (rd == 15) {
+        tcg_gen_mov_tl(env_btarget, t);
+        cris_prepare_jmp(dc, JMP_INDIRECT);
+        dc->delayed_branch = 1;
+        return insn_len;
+    }
+
+    tcg_gen_mov_tl(cpu_PR[rd], t);
+    dc->cpustate_changed = 1;
+    tcg_temp_free(addr);
+    tcg_temp_free(t);
+    return insn_len;
+}
+
+static unsigned int dec10_ind_move_pr_m(DisasContext *dc)
+{
+    unsigned int insn_len = 2, size = preg_sizes_v10[dc->dst];
+    TCGv addr, t0;
+
+    LOG_DIS("move.%d $p%d, [$r%d]\n", dc->size, dc->dst, dc->src);
+
+    addr = tcg_temp_new();
+    crisv10_prepare_memaddr(dc, addr, size);
+    if (dc->dst == PR_CCS) {
+        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);
+        tcg_temp_free(t0);
+    } else {
+        gen_store(dc, addr, cpu_PR[dc->dst], size);
+    }
+    t0 = tcg_temp_new();
+    insn_len += crisv10_post_memaddr(dc, size);
+    cris_lock_irq(dc);
+
+    return insn_len;
+}
+
+static void dec10_movem_r_m(DisasContext *dc)
+{
+    int i, pfix = dc->tb_flags & PFIX_FLAG;
+    TCGv addr, t0;
+
+    LOG_DIS("%s r%d, [r%d] pi=%d ir=%x\n", __func__,
+              dc->dst, dc->src, dc->postinc, dc->ir);
+
+    addr = tcg_temp_new();
+    t0 = tcg_temp_new();
+    crisv10_prepare_memaddr(dc, addr, 4);
+    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);
+        } else {
+            gen_store(dc, addr, cpu_R[i], 4);
+        }
+        tcg_gen_addi_tl(addr, addr, 4);
+    }
+
+    if (pfix && dc->mode == CRISV10_MODE_AUTOINC) {
+        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);
+    }
+    tcg_temp_free(addr);
+    tcg_temp_free(t0);
+}
+
+static void dec10_movem_m_r(DisasContext *dc)
+{
+    int i, pfix = dc->tb_flags & PFIX_FLAG;
+    TCGv addr, t0;
+
+    LOG_DIS("%s [r%d], r%d pi=%d ir=%x\n", __func__,
+              dc->src, dc->dst, dc->postinc, dc->ir);
+
+    addr = tcg_temp_new();
+    t0 = tcg_temp_new();
+    crisv10_prepare_memaddr(dc, addr, 4);
+    tcg_gen_mov_tl(t0, addr);
+    for (i = dc->dst; i >= 0; i--) {
+        gen_load(dc, cpu_R[i], addr, 4, 0);
+        tcg_gen_addi_tl(addr, addr, 4);
+    }
+
+    if (pfix && dc->mode == CRISV10_MODE_AUTOINC) {
+        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);
+    }
+    tcg_temp_free(addr);
+    tcg_temp_free(t0);
+}
+
+static int dec10_ind_alu(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]);
+    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]);
+        cris_prepare_jmp(dc, JMP_INDIRECT);
+        dc->delayed_branch = 1;
+        return insn_len;
+    }
+
+    cris_alu_m_free_temps(t);
+
+    return insn_len;
+}
+
+static int dec10_ind_bound(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);
+    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]);
+        cris_prepare_jmp(dc, JMP_INDIRECT);
+        dc->delayed_branch = 1;
+        return insn_len;
+    }
+
+    tcg_temp_free(t);
+    return insn_len;
+}
+
+static int dec10_alux_m(DisasContext *dc, int op)
+{
+    unsigned int size = (dc->size & 1) ? 2 : 1;
+    unsigned int sx = !!(dc->size & 2);
+    int insn_len = 2;
+    int rd = dc->dst;
+    TCGv t;
+
+    LOG_DIS("addx size=%d sx=%d op=%d %d\n", size, sx, dc->src, dc->dst);
+
+    t = tcg_temp_new();
+
+    cris_cc_mask(dc, CC_MASK_NZVC);
+    insn_len += dec10_prep_move_m(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]);
+        cris_prepare_jmp(dc, JMP_INDIRECT);
+        dc->delayed_branch = 1;
+        return insn_len;
+    }
+
+    tcg_temp_free(t);
+    return insn_len;
+}
+
+static int dec10_dip(DisasContext *dc)
+{
+    int insn_len = 2;
+    uint32_t imm;
+
+    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);
+        tcg_gen_movi_tl(cpu_PR[PR_PREFIX], imm);
+        if (dc->postinc)
+            insn_len += 4;
+        tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len - 2);
+    } else {
+        gen_load(dc, cpu_PR[PR_PREFIX], cpu_R[dc->src], 4, 0);
+        if (dc->postinc)
+            tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], 4);
+    }
+
+    cris_set_prefix(dc);
+    return insn_len;
+}
+
+static int dec10_bdap_m(DisasContext *dc, int size)
+{
+    int insn_len = 2;
+    int rd = dc->dst;
+
+    LOG_DIS("bdap_m pc=%x opcode=%d r%d r%d sz=%d\n",
+              dc->pc, dc->opcode, dc->src, dc->dst, size);
+
+    assert(dc->dst != 15);
+#if 0
+    /* 8bit embedded offset?  */
+    if (!dc->postinc && (dc->ir & (1 << 11))) {
+        int simm = dc->ir & 0xff;
+
+       // assert(0);
+        /* sign extended.  */
+        simm = (int8_t)simm;
+
+        tcg_gen_addi_tl(cpu_PR[PR_PREFIX], cpu_R[dc->dst], simm);
+
+        cris_set_prefix(dc);
+        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]);
+    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)
+{
+    unsigned int insn_len = 2;
+    unsigned int size = dec10_size(dc->size);
+    uint32_t imm;
+    int32_t simm;
+    TCGv t[2];
+
+    if (dc->size != 3) {
+        switch (dc->opcode) {
+            case CRISV10_IND_MOVE_M_R:
+                return dec10_ind_move_m_r(dc, size);
+                break;
+            case CRISV10_IND_MOVE_R_M:
+                return dec10_ind_move_r_m(dc, size);
+                break;
+            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);
+                break;
+            case CRISV10_IND_TEST:
+                LOG_DIS("test size=%d op=%d %d\n",  size, dc->src, dc->dst);
+
+                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]);
+                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);
+                cris_alu_m_free_temps(t);
+                break;
+            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);
+                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);
+                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);
+                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);
+                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);
+                break;
+            case CRISV10_IND_MOVX:
+                insn_len = dec10_alux_m(dc, CC_OP_MOVE);
+                break;
+            case CRISV10_IND_ADDX:
+                insn_len = dec10_alux_m(dc, CC_OP_ADD);
+                break;
+            case CRISV10_IND_SUBX:
+                insn_len = dec10_alux_m(dc, CC_OP_SUB);
+                break;
+            case CRISV10_IND_CMPX:
+                insn_len = dec10_alux_m(dc, CC_OP_CMP);
+                break;
+            case CRISV10_IND_MUL:
+                /* This is a reg insn coded in the mem indir space.  */
+                LOG_DIS("mul pc=%x opcode=%d\n", dc->pc, dc->opcode);
+                cris_cc_mask(dc, CC_MASK_NZVC);
+                dec10_reg_mul(dc, size, dc->ir & (1 << 10));
+                break;
+            case CRISV10_IND_BDAP_M:
+                insn_len = dec10_bdap_m(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);
+                break;
+        }
+        return insn_len;
+    }
+
+    switch (dc->opcode) {
+        case CRISV10_IND_MOVE_M_SPR:
+            insn_len = dec10_ind_move_m_pr(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,
+                         dc->opcode, dc->src, dc->dst);
+                imm = ldl_code(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->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_raise_exception(EXCP_BREAK);
+                    dc->is_jmp = DISAS_UPDATE;
+                    return insn_len;
+                }
+                LOG_DIS("%d: jump.%d %d r%d r%d\n", __LINE__, size,
+                         dc->opcode, dc->src, dc->dst);
+                t[0] = tcg_temp_new();
+                t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len));
+                crisv10_prepare_memaddr(dc, t[0], size);
+                gen_load(dc, env_btarget, t[0], 4, 0);
+                insn_len += crisv10_post_memaddr(dc, size);
+                cris_prepare_jmp(dc, JMP_INDIRECT);
+                dc->delayed_branch--; /* v10 has no dslot here.  */
+                tcg_temp_free(t[0]);
+            }
+            break;
+
+        case CRISV10_IND_MOVEM_R_M:
+            LOG_DIS("movem_r_m pc=%x opcode=%d r%d r%d\n",
+                        dc->pc, dc->opcode, dc->dst, dc->src);
+            dec10_movem_r_m(dc);
+            break;
+        case CRISV10_IND_MOVEM_M_R:
+            LOG_DIS("movem_m_r pc=%x opcode=%d\n", dc->pc, dc->opcode);
+            dec10_movem_m_r(dc);
+            break;
+        case CRISV10_IND_JUMP_R:
+            LOG_DIS("jmp pc=%x opcode=%d r%d r%d\n",
+                        dc->pc, dc->opcode, dc->dst, dc->src);
+            tcg_gen_mov_tl(env_btarget, cpu_R[dc->src]);
+            t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len));
+            cris_prepare_jmp(dc, JMP_INDIRECT);
+            dc->delayed_branch--; /* v10 has no dslot here.  */
+            break;
+        case CRISV10_IND_MOVX:
+            insn_len = dec10_alux_m(dc, CC_OP_MOVE);
+            break;
+        case CRISV10_IND_ADDX:
+            insn_len = dec10_alux_m(dc, CC_OP_ADD);
+            break;
+        case CRISV10_IND_SUBX:
+            insn_len = dec10_alux_m(dc, CC_OP_SUB);
+            break;
+        case CRISV10_IND_CMPX:
+            insn_len = dec10_alux_m(dc, CC_OP_CMP);
+            break;
+        case CRISV10_IND_DIP:
+            insn_len = dec10_dip(dc);
+            break;
+        case CRISV10_IND_BCC_M:
+
+            cris_cc_mask(dc, 0);
+            imm = ldsw_code(dc->pc + 2);
+            simm = (int16_t)imm;
+            simm += 4;
+
+            LOG_DIS("bcc_m: b%s %x\n", cc_name(dc->cond), dc->pc + simm);
+            cris_prepare_cc_branch(dc, simm, dc->cond);
+            insn_len = 4;
+            break;
+        default:
+            LOG_DIS("ERROR pc=%x opcode=%d\n", dc->pc, dc->opcode);
+            assert(0);
+            break;
+    }
+
+    return insn_len;
+}
+
+static unsigned int crisv10_decoder(DisasContext *dc)
+{
+    unsigned int insn_len = 2;
+
+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
+        tcg_gen_debug_insn_start(dc->pc);
+
+    /* Load a halfword onto the instruction register.  */
+    dc->ir = lduw_code(dc->pc);
+
+    /* Now decode it.  */
+    dc->opcode   = EXTRACT_FIELD(dc->ir, 6, 9);
+    dc->mode     = EXTRACT_FIELD(dc->ir, 10, 11);
+    dc->src      = EXTRACT_FIELD(dc->ir, 0, 3);
+    dc->size     = EXTRACT_FIELD(dc->ir, 4, 5);
+    dc->cond = dc->dst = EXTRACT_FIELD(dc->ir, 12, 15);
+    dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);
+
+    dc->clear_prefix = 1;
+
+    /* FIXME: What if this insn insn't 2 in length??  */
+    if (dc->src == 15 || dc->dst == 15)
+        tcg_gen_movi_tl(cpu_R[15], dc->pc + 2);
+
+    switch (dc->mode) {
+        case CRISV10_MODE_QIMMEDIATE:
+            insn_len = dec10_quick_imm(dc);
+            break;
+        case CRISV10_MODE_REG:
+            insn_len = dec10_reg(dc);
+            break;
+        case CRISV10_MODE_AUTOINC:
+        case CRISV10_MODE_INDIRECT:
+            insn_len = dec10_ind(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;
+    }
+
+    return insn_len;
+}
+
+static CPUCRISState *cpu_crisv10_init (CPUState *env)
+{
+	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");
+	cc_src = tcg_global_mem_new(TCG_AREG0,
+				    offsetof(CPUState, cc_src), "cc_src");
+	cc_dest = tcg_global_mem_new(TCG_AREG0,
+				     offsetof(CPUState, cc_dest),
+				     "cc_dest");
+	cc_result = tcg_global_mem_new(TCG_AREG0,
+				       offsetof(CPUState, cc_result),
+				       "cc_result");
+	cc_op = tcg_global_mem_new(TCG_AREG0,
+				   offsetof(CPUState, cc_op), "cc_op");
+	cc_size = tcg_global_mem_new(TCG_AREG0,
+				     offsetof(CPUState, cc_size),
+				     "cc_size");
+	cc_mask = tcg_global_mem_new(TCG_AREG0,
+				     offsetof(CPUState, cc_mask),
+				     "cc_mask");
+
+	env_pc = tcg_global_mem_new(TCG_AREG0, 
+				    offsetof(CPUState, pc),
+				    "pc");
+	env_btarget = tcg_global_mem_new(TCG_AREG0,
+					 offsetof(CPUState, btarget),
+					 "btarget");
+	env_btaken = tcg_global_mem_new(TCG_AREG0,
+					 offsetof(CPUState, btaken),
+					 "btaken");
+	for (i = 0; i < 16; i++) {
+		cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
+					      offsetof(CPUState, regs[i]),
+					      regnames_v10[i]);
+	}
+	for (i = 0; i < 16; i++) {
+		cpu_PR[i] = tcg_global_mem_new(TCG_AREG0,
+					       offsetof(CPUState, pregs[i]),
+					       pregnames_v10[i]);
+	}
+
+	return env;
+}
+
diff --git a/target-m68k/exec.h b/target-m68k/exec.h
index 1267bb6..ece9aa0 100644
--- a/target-m68k/exec.h
+++ b/target-m68k/exec.h
@@ -20,10 +20,6 @@
 #include "dyngen-exec.h"
 
 register struct CPUM68KState *env asm(AREG0);
-/* This is only used for tb lookup.  */
-register uint32_t T0 asm(AREG1);
-/* ??? We don't use T1, but common code expects it to exist  */
-#define T1 env->t1
 
 #include "cpu.h"
 #include "exec-all.h"
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index dd7a598..5b4347a 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -194,6 +194,7 @@
 #define INSN_RS2(x) (x)
 #define INSN_ASI(x) ((x) << 5)
 
+#define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff))
 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
 #define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
 #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
@@ -217,6 +218,9 @@
 #define COND_VC    0xf
 #define BA         (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))
 
+#define MOVCC_ICC  (1 << 18)
+#define MOVCC_XCC  (1 << 18 | 1 << 12)
+
 #define ARITH_ADD  (INSN_OP(2) | INSN_OP3(0x00))
 #define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
 #define ARITH_AND  (INSN_OP(2) | INSN_OP3(0x01))
@@ -233,6 +237,7 @@
 #define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
 #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
 #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))
+#define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c))
 
 #define SHIFT_SLL  (INSN_OP(2) | INSN_OP3(0x25))
 #define SHIFT_SRL  (INSN_OP(2) | INSN_OP3(0x26))
@@ -580,6 +585,109 @@
 }
 #endif
 
+static void tcg_out_setcond_i32(TCGContext *s, int cond, TCGArg ret,
+                                TCGArg c1, TCGArg c2, int c2const)
+{
+    TCGArg t;
+
+    /* For 32-bit comparisons, we can play games with ADDX/SUBX.  */
+    switch (cond) {
+    case TCG_COND_EQ:
+    case TCG_COND_NE:
+        if (c2 != 0) {
+            tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR);
+        }
+        c1 = TCG_REG_G0, c2 = ret, c2const = 0;
+        cond = (cond == TCG_COND_EQ ? TCG_COND_LEU : TCG_COND_LTU);
+	break;
+
+    case TCG_COND_GTU:
+    case TCG_COND_GEU:
+        if (c2const && c2 != 0) {
+            tcg_out_movi_imm13(s, TCG_REG_I5, c2);
+            c2 = TCG_REG_I5;
+        }
+        t = c1, c1 = c2, c2 = t, c2const = 0;
+        cond = tcg_swap_cond(cond);
+        break;
+
+    case TCG_COND_LTU:
+    case TCG_COND_LEU:
+        break;
+
+    default:
+        tcg_out_cmp(s, c1, c2, c2const);
+#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
+        tcg_out_movi_imm13(s, ret, 0);
+        tcg_out32 (s, ARITH_MOVCC | INSN_RD(ret)
+                   | INSN_RS1(tcg_cond_to_bcond[cond])
+                   | MOVCC_ICC | INSN_IMM11(1));
+#else
+        t = gen_new_label();
+        tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), t);
+        tcg_out_movi_imm13(s, ret, 1);
+        tcg_out_movi_imm13(s, ret, 0);
+        tcg_out_label(s, t, (tcg_target_long)s->code_ptr);
+#endif
+        return;
+    }
+
+    tcg_out_cmp(s, c1, c2, c2const);
+    if (cond == TCG_COND_LTU) {
+        tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDX);
+    } else {
+        tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBX);
+    }
+}
+
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_setcond_i64(TCGContext *s, int cond, TCGArg ret,
+                                TCGArg c1, TCGArg c2, int c2const)
+{
+    tcg_out_cmp(s, c1, c2, c2const);
+    tcg_out_movi_imm13(s, ret, 0);
+    tcg_out32 (s, ARITH_MOVCC | INSN_RD(ret)
+               | INSN_RS1(tcg_cond_to_bcond[cond])
+               | MOVCC_XCC | INSN_IMM11(1));
+}
+#else
+static void tcg_out_setcond2_i32(TCGContext *s, int cond, TCGArg ret,
+                                 TCGArg al, TCGArg ah,
+                                 TCGArg bl, int blconst,
+                                 TCGArg bh, int bhconst)
+{
+    int lab;
+
+    switch (cond) {
+    case TCG_COND_EQ:
+        tcg_out_setcond_i32(s, TCG_COND_EQ, TCG_REG_I5, al, bl, blconst);
+        tcg_out_setcond_i32(s, TCG_COND_EQ, ret, ah, bh, bhconst);
+        tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_AND);
+        break;
+
+    case TCG_COND_NE:
+        tcg_out_setcond_i32(s, TCG_COND_NE, TCG_REG_I5, al, al, blconst);
+        tcg_out_setcond_i32(s, TCG_COND_NE, ret, ah, bh, bhconst);
+        tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_OR);
+        break;
+
+    default:
+        lab = gen_new_label();
+
+        tcg_out_cmp(s, ah, bh, bhconst);
+        tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), lab);
+        tcg_out_movi_imm13(s, ret, 1);
+        tcg_out_branch_i32(s, INSN_COND(COND_NE, 1), lab);
+        tcg_out_movi_imm13(s, ret, 0);
+
+        tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), ret, al, bl, blconst);
+
+        tcg_out_label(s, lab, (tcg_target_long)s->code_ptr);
+        break;
+    }
+}
+#endif
+
 /* Generate global QEMU prologue and epilogue code */
 void tcg_target_qemu_prologue(TCGContext *s)
 {
@@ -1146,12 +1254,22 @@
         tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
                            args[3]);
         break;
+    case INDEX_op_setcond_i32:
+        tcg_out_setcond_i32(s, args[3], args[0], args[1],
+                            args[2], const_args[2]);
+        break;
+
 #if TCG_TARGET_REG_BITS == 32
     case INDEX_op_brcond2_i32:
         tcg_out_brcond2_i32(s, args[4], args[0], args[1],
                             args[2], const_args[2],
                             args[3], const_args[3], args[5]);
         break;
+    case INDEX_op_setcond2_i32:
+        tcg_out_setcond2_i32(s, args[5], args[0], args[1], args[2],
+                             args[3], const_args[3],
+                             args[4], const_args[4]);
+        break;
     case INDEX_op_add2_i32:
         tcg_out_arithc(s, args[0], args[2], args[4], const_args[4],
                        ARITH_ADDCC);
@@ -1257,6 +1375,11 @@
         tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
                            args[3]);
         break;
+    case INDEX_op_setcond_i64:
+        tcg_out_setcond_i64(s, args[3], args[0], args[1],
+                            args[2], const_args[2]);
+        break;
+
     case INDEX_op_qemu_ld64:
         tcg_out_qemu_ld(s, args, 3);
         break;
@@ -1309,8 +1432,11 @@
     { INDEX_op_sar_i32, { "r", "r", "rJ" } },
 
     { INDEX_op_brcond_i32, { "r", "rJ" } },
+    { INDEX_op_setcond_i32, { "r", "r", "rJ" } },
+
 #if TCG_TARGET_REG_BITS == 32
     { INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } },
+    { INDEX_op_setcond2_i32, { "r", "r", "r", "rJ", "rJ" } },
     { INDEX_op_add2_i32, { "r", "r", "r", "r", "rJ", "rJ" } },
     { INDEX_op_sub2_i32, { "r", "r", "r", "r", "rJ", "rJ" } },
     { INDEX_op_mulu2_i32, { "r", "r", "r", "rJ" } },
@@ -1362,6 +1488,7 @@
     { INDEX_op_ext32u_i64, { "r", "ri" } },
 
     { INDEX_op_brcond_i64, { "r", "rJ" } },
+    { INDEX_op_setcond_i64, { "r", "r", "rJ" } },
 #endif
     { -1 },
 };
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 9949814..e6a1caf 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -981,9 +981,16 @@
         op = tdefs->op;
         assert(op >= 0 && op < NB_OPS);
         def = &tcg_op_defs[op];
+#if defined(CONFIG_DEBUG_TCG)
+        /* Duplicate entry in op definitions? */
+        assert(!def->used);
+        def->used = 1;
+#endif
         nb_args = def->nb_iargs + def->nb_oargs;
         for(i = 0; i < nb_args; i++) {
             ct_str = tdefs->args_ct_str[i];
+            /* Incomplete TCGTargetOpDef entry? */
+            assert(ct_str != NULL);
             tcg_regset_clear(def->args_ct[i].u.regs);
             def->args_ct[i].ct = 0;
             if (ct_str[0] >= '0' && ct_str[0] <= '9') {
@@ -1018,6 +1025,9 @@
             }
         }
 
+        /* TCGTargetOpDef entry with too much information? */
+        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
+
         /* sort the constraints (XXX: this is just an heuristic) */
         sort_constraints(def, 0, def->nb_oargs);
         sort_constraints(def, def->nb_oargs, def->nb_iargs);
@@ -1035,6 +1045,17 @@
         tdefs++;
     }
 
+#if defined(CONFIG_DEBUG_TCG)
+    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
+        if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
+            /* Wrong entry in op definitions? */
+            assert(!tcg_op_defs[op].used);
+        } else {
+            /* Missing entry in op definitions? */
+            assert(tcg_op_defs[op].used);
+        }
+    }
+#endif
 }
 
 #ifdef USE_LIVENESS_ANALYSIS
diff --git a/tcg/tcg.h b/tcg/tcg.h
index b218abe..cf3a508 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -205,11 +205,19 @@
     TCG_COND_GTU,
 } TCGCond;
 
+/* Invert the sense of the comparison.  */
 static inline TCGCond tcg_invert_cond(TCGCond c)
 {
     return (TCGCond)(c ^ 1);
 }
 
+/* Swap the operands in a comparison.  */
+static inline TCGCond tcg_swap_cond(TCGCond c)
+{
+    int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15);
+    return (TCGCond)(c ^ mask);
+}
+
 static inline TCGCond tcg_unsigned_cond(TCGCond c)
 {
     return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c);
@@ -404,6 +412,9 @@
     uint16_t copy_size;
     TCGArgConstraint *args_ct;
     int *sorted_args;
+#if defined(CONFIG_DEBUG_TCG)
+    int used;
+#endif
 } TCGOpDef;
         
 typedef struct TCGTargetOpDef {
diff --git a/vl.c b/vl.c
index 98918ac..084604f 100644
--- a/vl.c
+++ b/vl.c
@@ -5897,6 +5897,8 @@
     if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
         exit(1);
 
+    net_check_clients();
+
     if (!display_state)
         dumb_display_init();
     /* just use the first displaystate for the moment */