summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--bootdevice.c73
-rw-r--r--cpus.c3
-rw-r--r--exec.c4
-rw-r--r--hw/core/qdev-properties-system.c82
-rw-r--r--hw/i386/pc.c22
-rw-r--r--hw/net/e1000.c21
-rw-r--r--hw/ppc/mac_newworld.c4
-rw-r--r--hw/ppc/mac_oldworld.c5
-rw-r--r--hw/sparc/sun4m.c4
-rw-r--r--hw/sparc64/sun4u.c4
-rw-r--r--include/hw/hw.h6
-rw-r--r--include/sysemu/sysemu.h8
-rw-r--r--include/ui/sdl2.h32
-rw-r--r--monitor.c14
-rw-r--r--net/l2tpv3.c9
-rw-r--r--net/queue.c2
-rw-r--r--net/slirp.c2
-rw-r--r--net/tap.c12
-rw-r--r--pc-bios/efi-e1000.rombin194560 -> 197120 bytes
-rw-r--r--pc-bios/efi-eepro100.rombin196096 -> 197632 bytes
-rw-r--r--pc-bios/efi-ne2k_pci.rombin194560 -> 195584 bytes
-rw-r--r--pc-bios/efi-pcnet.rombin194560 -> 195584 bytes
-rw-r--r--pc-bios/efi-rtl8139.rombin198144 -> 200192 bytes
-rw-r--r--pc-bios/efi-virtio.rombin192000 -> 194048 bytes
-rw-r--r--qom/cpu.c1
m---------roms/ipxe0
-rw-r--r--target-tricore/helper.h59
-rw-r--r--target-tricore/op_helper.c1086
-rw-r--r--target-tricore/translate.c1034
-rw-r--r--target-tricore/tricore-opcodes.h19
-rw-r--r--ui/Makefile.objs7
-rw-r--r--ui/sdl.c3
-rw-r--r--ui/sdl2-2d.c122
-rw-r--r--ui/sdl2-input.c106
-rw-r--r--ui/sdl2.c343
-rw-r--r--vl.c75
36 files changed, 2665 insertions, 497 deletions
diff --git a/bootdevice.c b/bootdevice.c
index b29970c7a3..5914417027 100644
--- a/bootdevice.c
+++ b/bootdevice.c
@@ -25,6 +25,7 @@
 #include "sysemu/sysemu.h"
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
+#include "hw/hw.h"
 
 typedef struct FWBootEntry FWBootEntry;
 
@@ -37,6 +38,78 @@ struct FWBootEntry {
 
 static QTAILQ_HEAD(, FWBootEntry) fw_boot_order =
     QTAILQ_HEAD_INITIALIZER(fw_boot_order);
+static QEMUBootSetHandler *boot_set_handler;
+static void *boot_set_opaque;
+
+void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
+{
+    boot_set_handler = func;
+    boot_set_opaque = opaque;
+}
+
+void qemu_boot_set(const char *boot_order, Error **errp)
+{
+    Error *local_err = NULL;
+
+    if (!boot_set_handler) {
+        error_setg(errp, "no function defined to set boot device list for"
+                         " this architecture");
+        return;
+    }
+
+    validate_bootdevices(boot_order, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    boot_set_handler(boot_set_opaque, boot_order, errp);
+}
+
+void validate_bootdevices(const char *devices, Error **errp)
+{
+    /* We just do some generic consistency checks */
+    const char *p;
+    int bitmap = 0;
+
+    for (p = devices; *p != '\0'; p++) {
+        /* Allowed boot devices are:
+         * a-b: floppy disk drives
+         * c-f: IDE disk drives
+         * g-m: machine implementation dependent drives
+         * n-p: network devices
+         * It's up to each machine implementation to check if the given boot
+         * devices match the actual hardware implementation and firmware
+         * features.
+         */
+        if (*p < 'a' || *p > 'p') {
+            error_setg(errp, "Invalid boot device '%c'", *p);
+            return;
+        }
+        if (bitmap & (1 << (*p - 'a'))) {
+            error_setg(errp, "Boot device '%c' was given twice", *p);
+            return;
+        }
+        bitmap |= 1 << (*p - 'a');
+    }
+}
+
+void restore_boot_order(void *opaque)
+{
+    char *normal_boot_order = opaque;
+    static int first = 1;
+
+    /* Restore boot order and remove ourselves after the first boot */
+    if (first) {
+        first = 0;
+        return;
+    }
+
+    qemu_boot_set(normal_boot_order, NULL);
+
+    qemu_unregister_reset(restore_boot_order, normal_boot_order);
+    g_free(normal_boot_order);
+}
 
 void check_boot_index(int32_t bootindex, Error **errp)
 {
diff --git a/cpus.c b/cpus.c
index 1b5168a1db..2edb5cd807 100644
--- a/cpus.c
+++ b/cpus.c
@@ -940,7 +940,6 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
     qemu_mutex_lock(&qemu_global_mutex);
     qemu_thread_get_self(cpu->thread);
     cpu->thread_id = qemu_get_thread_id();
-    cpu->exception_index = -1;
     cpu->can_do_io = 1;
     current_cpu = cpu;
 
@@ -982,7 +981,6 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
     qemu_mutex_lock_iothread();
     qemu_thread_get_self(cpu->thread);
     cpu->thread_id = qemu_get_thread_id();
-    cpu->exception_index = -1;
     cpu->can_do_io = 1;
 
     sigemptyset(&waitset);
@@ -1026,7 +1024,6 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
     CPU_FOREACH(cpu) {
         cpu->thread_id = qemu_get_thread_id();
         cpu->created = true;
-        cpu->exception_index = -1;
         cpu->can_do_io = 1;
     }
     qemu_cond_signal(&qemu_cpu_cond);
diff --git a/exec.c b/exec.c
index 963481a181..c2ed10a2d6 100644
--- a/exec.c
+++ b/exec.c
@@ -434,7 +434,7 @@ static int cpu_common_pre_load(void *opaque)
 {
     CPUState *cpu = opaque;
 
-    cpu->exception_index = 0;
+    cpu->exception_index = -1;
 
     return 0;
 }
@@ -443,7 +443,7 @@ static bool cpu_common_exception_index_needed(void *opaque)
 {
     CPUState *cpu = opaque;
 
-    return cpu->exception_index != 0;
+    return tcg_enabled() && cpu->exception_index != -1;
 }
 
 static const VMStateDescription vmstate_cpu_common_exception_index = {
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 65901ef10e..a2e44bd4e8 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -177,42 +177,69 @@ PropertyInfo qdev_prop_chr = {
 };
 
 /* --- netdev device --- */
+static void get_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
+{
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
+    char *p = g_strdup(peers_ptr->ncs[0] ? peers_ptr->ncs[0]->name : "");
 
-static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
+    visit_type_str(v, &p, name, errp);
+    g_free(p);
+}
+
+static void set_netdev(Object *obj, Visitor *v, void *opaque,
+                       const char *name, Error **errp)
 {
-    NICPeers *peers_ptr = (NICPeers *)ptr;
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
     NetClientState **ncs = peers_ptr->ncs;
     NetClientState *peers[MAX_QUEUE_NUM];
-    int queues, i = 0;
-    int ret;
+    Error *local_err = NULL;
+    int queues, err = 0, i = 0;
+    char *str;
+
+    if (dev->realized) {
+        qdev_prop_set_after_realize(dev, name, errp);
+        return;
+    }
+
+    visit_type_str(v, &str, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
 
     queues = qemu_find_net_clients_except(str, peers,
                                           NET_CLIENT_OPTIONS_KIND_NIC,
                                           MAX_QUEUE_NUM);
     if (queues == 0) {
-        ret = -ENOENT;
-        goto err;
+        err = -ENOENT;
+        goto out;
     }
 
     if (queues > MAX_QUEUE_NUM) {
-        ret = -E2BIG;
-        goto err;
+        error_setg(errp, "queues of backend '%s'(%d) exceeds QEMU limitation(%d)",
+                   str, queues, MAX_QUEUE_NUM);
+        goto out;
     }
 
     for (i = 0; i < queues; i++) {
         if (peers[i] == NULL) {
-            ret = -ENOENT;
-            goto err;
+            err = -ENOENT;
+            goto out;
         }
 
         if (peers[i]->peer) {
-            ret = -EEXIST;
-            goto err;
+            err = -EEXIST;
+            goto out;
         }
 
         if (ncs[i]) {
-            ret = -EINVAL;
-            goto err;
+            err = -EINVAL;
+            goto out;
         }
 
         ncs[i] = peers[i];
@@ -221,30 +248,9 @@ static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
 
     peers_ptr->queues = queues;
 
-    return 0;
-
-err:
-    return ret;
-}
-
-static char *print_netdev(void *ptr)
-{
-    NetClientState *netdev = ptr;
-    const char *val = netdev->name ? netdev->name : "";
-
-    return g_strdup(val);
-}
-
-static void get_netdev(Object *obj, Visitor *v, void *opaque,
-                       const char *name, Error **errp)
-{
-    get_pointer(obj, v, opaque, print_netdev, name, errp);
-}
-
-static void set_netdev(Object *obj, Visitor *v, void *opaque,
-                       const char *name, Error **errp)
-{
-    set_pointer(obj, v, opaque, parse_netdev, name, errp);
+out:
+    error_set_from_qdev_prop_error(errp, err, dev, prop, str);
+    g_free(str);
 }
 
 PropertyInfo qdev_prop_netdev = {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c0e55a6446..1ec7290dca 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -282,7 +282,7 @@ static int boot_device2nibble(char boot_device)
     return 0;
 }
 
-static int set_boot_dev(ISADevice *s, const char *boot_device)
+static void set_boot_dev(ISADevice *s, const char *boot_device, Error **errp)
 {
 #define PC_MAX_BOOT_DEVICES 3
     int nbds, bds[3] = { 0, };
@@ -290,25 +290,24 @@ static int set_boot_dev(ISADevice *s, const char *boot_device)
 
     nbds = strlen(boot_device);
     if (nbds > PC_MAX_BOOT_DEVICES) {
-        error_report("Too many boot devices for PC");
-        return(1);
+        error_setg(errp, "Too many boot devices for PC");
+        return;
     }
     for (i = 0; i < nbds; i++) {
         bds[i] = boot_device2nibble(boot_device[i]);
         if (bds[i] == 0) {
-            error_report("Invalid boot device for PC: '%c'",
-                         boot_device[i]);
-            return(1);
+            error_setg(errp, "Invalid boot device for PC: '%c'",
+                       boot_device[i]);
+            return;
         }
     }
     rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
     rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
-    return(0);
 }
 
-static int pc_boot_set(void *opaque, const char *boot_device)
+static void pc_boot_set(void *opaque, const char *boot_device, Error **errp)
 {
-    return set_boot_dev(opaque, boot_device);
+    set_boot_dev(opaque, boot_device, errp);
 }
 
 typedef struct pc_cmos_init_late_arg {
@@ -365,6 +364,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
     static pc_cmos_init_late_arg arg;
     PCMachineState *pc_machine = PC_MACHINE(machine);
+    Error *local_err = NULL;
 
     /* various important CMOS locations needed by PC/Bochs bios */
 
@@ -412,7 +412,9 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     object_property_set_link(OBJECT(machine), OBJECT(s),
                              "rtc_state", &error_abort);
 
-    if (set_boot_dev(s, boot_device)) {
+    set_boot_dev(s, boot_device, &local_err);
+    if (local_err) {
+        error_report("%s", error_get_pretty(local_err));
         exit(1);
     }
 
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index e33a4da9fa..89c5788b1c 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -33,6 +33,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 #include "qemu/iov.h"
+#include "qemu/range.h"
 
 #include "e1000_regs.h"
 
@@ -923,7 +924,9 @@ e1000_can_receive(NetClientState *nc)
     E1000State *s = qemu_get_nic_opaque(nc);
 
     return (s->mac_reg[STATUS] & E1000_STATUS_LU) &&
-        (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
+        (s->mac_reg[RCTL] & E1000_RCTL_EN) &&
+        (s->parent_obj.config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
+        e1000_has_rxbufs(s, 1);
 }
 
 static uint64_t rx_desc_base(E1000State *s)
@@ -1529,6 +1532,20 @@ static NetClientInfo net_e1000_info = {
     .link_status_changed = e1000_set_link_status,
 };
 
+static void e1000_write_config(PCIDevice *pci_dev, uint32_t address,
+                                uint32_t val, int len)
+{
+    E1000State *s = E1000(pci_dev);
+
+    pci_default_write_config(pci_dev, address, val, len);
+
+    if (range_covers_byte(address, len, PCI_COMMAND) &&
+        (pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
+        qemu_flush_queued_packets(qemu_get_queue(s->nic));
+    }
+}
+
+
 static int pci_e1000_init(PCIDevice *pci_dev)
 {
     DeviceState *dev = DEVICE(pci_dev);
@@ -1539,6 +1556,8 @@ static int pci_e1000_init(PCIDevice *pci_dev)
     int i;
     uint8_t *macaddr;
 
+    pci_dev->config_write = e1000_write_config;
+
     pci_conf = pci_dev->config;
 
     /* TODO: RST# value should be 0, PCI spec 6.2.4 */
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 89aee716d4..ee1ed8a344 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -116,10 +116,10 @@ static const MemoryRegionOps unin_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+                            Error **errp)
 {
     fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
 }
 
 static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 32c21a4286..15109c294a 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -49,13 +49,12 @@
 #define CLOCKFREQ 266000000UL
 #define BUSFREQ 66000000UL
 
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+                            Error **errp)
 {
     fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
 }
 
-
 static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
 {
     return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 8273199f11..df259ad605 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -121,10 +121,10 @@ void DMA_register_channel (int nchan,
 {
 }
 
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+                            Error **errp)
 {
     fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
 }
 
 static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index f42112c1b2..acac8f9ed0 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -124,10 +124,10 @@ void DMA_register_channel (int nchan,
 {
 }
 
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+                            Error **errp)
 {
     fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
 }
 
 static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
diff --git a/include/hw/hw.h b/include/hw/hw.h
index 33bdb92712..c78adae06a 100644
--- a/include/hw/hw.h
+++ b/include/hw/hw.h
@@ -41,12 +41,6 @@ typedef void QEMUResetHandler(void *opaque);
 void qemu_register_reset(QEMUResetHandler *func, void *opaque);
 void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
 
-/* handler to set the boot_device order for a specific type of QEMUMachine */
-/* return 0 if success */
-typedef int QEMUBootSetHandler(void *opaque, const char *boot_order);
-void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque);
-int qemu_boot_set(const char *boot_order);
-
 #ifdef NEED_CPU_H
 #if TARGET_LONG_BITS == 64
 #define VMSTATE_UINTTL_V(_f, _s, _v)                                  \
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 9fea3bc3af..503e5a48a7 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -216,6 +216,14 @@ void del_boot_device_path(DeviceState *dev, const char *suffix);
 void device_add_bootindex_property(Object *obj, int32_t *bootindex,
                                    const char *name, const char *suffix,
                                    DeviceState *dev, Error **errp);
+void restore_boot_order(void *opaque);
+void validate_bootdevices(const char *devices, Error **errp);
+
+/* handler to set the boot_device order for a specific type of QEMUMachine */
+typedef void QEMUBootSetHandler(void *opaque, const char *boot_order,
+                                Error **errp);
+void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque);
+void qemu_boot_set(const char *boot_order, Error **errp);
 
 QemuOpts *qemu_get_machine_opts(void);
 
diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
new file mode 100644
index 0000000000..f56c596e31
--- /dev/null
+++ b/include/ui/sdl2.h
@@ -0,0 +1,32 @@
+#ifndef SDL2_H
+#define SDL2_H
+
+struct sdl2_console {
+    DisplayChangeListener dcl;
+    DisplaySurface *surface;
+    SDL_Texture *texture;
+    SDL_Window *real_window;
+    SDL_Renderer *real_renderer;
+    int idx;
+    int last_vm_running; /* per console for caption reasons */
+    int x, y;
+    int hidden;
+};
+
+void sdl2_window_create(struct sdl2_console *scon);
+void sdl2_window_destroy(struct sdl2_console *scon);
+void sdl2_window_resize(struct sdl2_console *scon);
+void sdl2_poll_events(struct sdl2_console *scon);
+
+void sdl2_reset_keys(struct sdl2_console *scon);
+void sdl2_process_key(struct sdl2_console *scon,
+                      SDL_KeyboardEvent *ev);
+
+void sdl2_2d_update(DisplayChangeListener *dcl,
+                    int x, int y, int w, int h);
+void sdl2_2d_switch(DisplayChangeListener *dcl,
+                    DisplaySurface *new_surface);
+void sdl2_2d_refresh(DisplayChangeListener *dcl);
+void sdl2_2d_redraw(struct sdl2_console *scon);
+
+#endif /* SDL2_H */
diff --git a/monitor.c b/monitor.c
index 503cf515ad..1808e41932 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1494,17 +1494,15 @@ static void do_ioport_write(Monitor *mon, const QDict *qdict)
 
 static void do_boot_set(Monitor *mon, const QDict *qdict)
 {
-    int res;
+    Error *local_err = NULL;
     const char *bootdevice = qdict_get_str(qdict, "bootdevice");
 
-    res = qemu_boot_set(bootdevice);
-    if (res == 0) {
-        monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
-    } else if (res > 0) {
-        monitor_printf(mon, "setting boot device list failed\n");
+    qemu_boot_set(bootdevice, &local_err);
+    if (local_err) {
+        monitor_printf(mon, "%s\n", error_get_pretty(local_err));
+        error_free(local_err);
     } else {
-        monitor_printf(mon, "no function defined to set boot device list for "
-                       "this architecture\n");
+        monitor_printf(mon, "boot device list now set to %s\n", bootdevice);
     }
 }
 
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index 3b805a7a4c..8c598b09bc 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -489,12 +489,12 @@ static struct mmsghdr *build_l2tpv3_vector(NetL2TPV3State *s, int count)
     struct iovec *iov;
     struct mmsghdr *msgvec, *result;
 
-    msgvec = g_malloc(sizeof(struct mmsghdr) * count);
+    msgvec = g_new(struct mmsghdr, count);
     result = msgvec;
     for (i = 0; i < count ; i++) {
         msgvec->msg_hdr.msg_name = NULL;
         msgvec->msg_hdr.msg_namelen = 0;
-        iov =  g_malloc(sizeof(struct iovec) * IOVSIZE);
+        iov =  g_new(struct iovec, IOVSIZE);
         msgvec->msg_hdr.msg_iov = iov;
         iov->iov_base = g_malloc(s->header_size);
         iov->iov_len = s->header_size;
@@ -695,8 +695,7 @@ int net_init_l2tpv3(const NetClientOptions *opts,
         goto outerr;
     }
 
-    s->dgram_dst = g_malloc(sizeof(struct sockaddr_storage));
-    memset(s->dgram_dst, '\0' , sizeof(struct sockaddr_storage));
+    s->dgram_dst = g_new0(struct sockaddr_storage, 1);
     memcpy(s->dgram_dst, result->ai_addr, result->ai_addrlen);
     s->dst_size = result->ai_addrlen;
 
@@ -730,7 +729,7 @@ int net_init_l2tpv3(const NetClientOptions *opts,
     }
 
     s->msgvec = build_l2tpv3_vector(s, MAX_L2TPV3_MSGCNT);
-    s->vec = g_malloc(sizeof(struct iovec) * MAX_L2TPV3_IOVCNT);
+    s->vec = g_new(struct iovec, MAX_L2TPV3_IOVCNT);
     s->header_buf = g_malloc(s->header_size);
 
     qemu_set_nonblock(fd);
diff --git a/net/queue.c b/net/queue.c
index f948318718..ebbe2bb93b 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -62,7 +62,7 @@ NetQueue *qemu_new_net_queue(void *opaque)
 {
     NetQueue *queue;
 
-    queue = g_malloc0(sizeof(NetQueue));
+    queue = g_new0(NetQueue, 1);
 
     queue->opaque = opaque;
     queue->nq_maxlen = 10000;
diff --git a/net/slirp.c b/net/slirp.c
index 377d7ef8c0..0cbca3cc83 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -652,7 +652,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
             return -1;
         }
     } else {
-        fwd = g_malloc(sizeof(struct GuestFwd));
+        fwd = g_new(struct GuestFwd, 1);
         fwd->hd = qemu_chr_new(buf, p, NULL);
         if (!fwd->hd) {
             error_report("could not open guest forwarding device '%s'", buf);
diff --git a/net/tap.c b/net/tap.c
index bde6b58b17..1fe0edfdf7 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -189,6 +189,7 @@ static void tap_send(void *opaque)
 {
     TAPState *s = opaque;
     int size;
+    int packets = 0;
 
     while (qemu_can_send_packet(&s->nc)) {
         uint8_t *buf = s->buf;
@@ -210,6 +211,17 @@ static void tap_send(void *opaque)
         } else if (size < 0) {
             break;
         }
+
+        /*
+         * When the host keeps receiving more packets while tap_send() is
+         * running we can hog the QEMU global mutex.  Limit the number of
+         * packets that are processed per tap_send() callback to prevent
+         * stalling the guest.
+         */
+        packets++;
+        if (packets >= 50) {
+            break;
+        }
     }
 }
 
diff --git a/pc-bios/efi-e1000.rom b/pc-bios/efi-e1000.rom
index 776e217a61..4e29d9d1ad 100644
--- a/pc-bios/efi-e1000.rom
+++ b/pc-bios/efi-e1000.rom
Binary files differdiff --git a/pc-bios/efi-eepro100.rom b/pc-bios/efi-eepro100.rom
index 677a8c373e..2a92d6f32f 100644
--- a/pc-bios/efi-eepro100.rom
+++ b/pc-bios/efi-eepro100.rom
Binary files differdiff --git a/pc-bios/efi-ne2k_pci.rom b/pc-bios/efi-ne2k_pci.rom
index 9dd6d91e31..6366017009 100644
--- a/pc-bios/efi-ne2k_pci.rom
+++ b/pc-bios/efi-ne2k_pci.rom
Binary files differdiff --git a/pc-bios/efi-pcnet.rom b/pc-bios/efi-pcnet.rom
index cae3a85887..a61f586eeb 100644
--- a/pc-bios/efi-pcnet.rom
+++ b/pc-bios/efi-pcnet.rom
Binary files differdiff --git a/pc-bios/efi-rtl8139.rom b/pc-bios/efi-rtl8139.rom
index 477f9b9b91..c9c77ea7f0 100644
--- a/pc-bios/efi-rtl8139.rom
+++ b/pc-bios/efi-rtl8139.rom
Binary files differdiff --git a/pc-bios/efi-virtio.rom b/pc-bios/efi-virtio.rom
index 935c927400..eec2790990 100644
--- a/pc-bios/efi-virtio.rom
+++ b/pc-bios/efi-virtio.rom
Binary files differdiff --git a/qom/cpu.c b/qom/cpu.c
index 79d22285f3..9c68fa4810 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -249,6 +249,7 @@ static void cpu_common_reset(CPUState *cpu)
     cpu->icount_extra = 0;
     cpu->icount_decr.u32 = 0;
     cpu->can_do_io = 0;
+    cpu->exception_index = -1;
     memset(cpu->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *));
 }
 
diff --git a/roms/ipxe b/roms/ipxe
-Subproject 69313edad85f8958acc8a47272b3c3da494835e
+Subproject 35c5379760aa1fea5e38f7a78b090f92bb7813e
diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index 6c07bd7f28..068dc7b422 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -18,8 +18,12 @@
 /* Arithmetic */
 DEF_HELPER_3(add_ssov, i32, env, i32, i32)
 DEF_HELPER_3(add_suov, i32, env, i32, i32)
+DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
+DEF_HELPER_3(add_h_suov, i32, env, i32, i32)
 DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
 DEF_HELPER_3(sub_suov, i32, env, i32, i32)
+DEF_HELPER_3(sub_h_ssov, i32, env, i32, i32)
+DEF_HELPER_3(sub_h_suov, i32, env, i32, i32)
 DEF_HELPER_3(mul_ssov, i32, env, i32, i32)
 DEF_HELPER_3(mul_suov, i32, env, i32, i32)
 DEF_HELPER_3(sha_ssov, i32, env, i32, i32)
@@ -32,6 +36,61 @@ DEF_HELPER_4(msub32_ssov, i32, env, i32, i32, i32)
 DEF_HELPER_4(msub32_suov, i32, env, i32, i32, i32)
 DEF_HELPER_4(msub64_ssov, i64, env, i32, i64, i32)
 DEF_HELPER_4(msub64_suov, i64, env, i32, i64, i32)
+DEF_HELPER_3(absdif_h_ssov, i32, env, i32, i32)
+DEF_HELPER_2(abs_ssov, i32, env, i32)
+DEF_HELPER_2(abs_h_ssov, i32, env, i32)
+/* hword/byte arithmetic */
+DEF_HELPER_2(abs_b, i32, env, i32)
+DEF_HELPER_2(abs_h, i32, env, i32)
+DEF_HELPER_3(absdif_b, i32, env, i32, i32)
+DEF_HELPER_3(absdif_h, i32, env, i32, i32)
+DEF_HELPER_3(add_b, i32, env, i32, i32)
+DEF_HELPER_3(add_h, i32, env, i32, i32)
+DEF_HELPER_3(sub_b, i32, env, i32, i32)
+DEF_HELPER_3(sub_h, i32, env, i32, i32)
+DEF_HELPER_FLAGS_2(eq_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eq_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eqany_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eqany_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+/* count leading ... */
+DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clz_h, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(cls, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(cls_h, TCG_CALL_NO_RWG_SE, i32, i32)
+/* sh */
+DEF_HELPER_FLAGS_2(sh, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(sh_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_3(sha, i32, env, i32, i32)
+DEF_HELPER_2(sha_h, i32, i32, i32)
+/* merge/split/parity */
+DEF_HELPER_FLAGS_2(bmerge, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_1(bsplit, TCG_CALL_NO_RWG_SE, i64, i32)
+DEF_HELPER_FLAGS_1(parity, TCG_CALL_NO_RWG_SE, i32, i32)
+/* float */
+DEF_HELPER_1(unpack, i64, i32)
+/* dvinit */
+DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_h_13, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32)
+/* mulh */
+DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32)
 /* CSA */
 DEF_HELPER_2(call, void, env, i32)
 DEF_HELPER_1(ret, void, env)
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index 4da76ff232..13e27291c1 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -56,118 +56,211 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off)
     return reg - index + new_index;
 }
 
-#define SSOV(env, ret, arg, len) do {               \
-    int64_t max_pos = INT##len ##_MAX;              \
-    int64_t max_neg = INT##len ##_MIN;              \
-    if (arg > max_pos) {                            \
-        env->PSW_USB_V = (1 << 31);                 \
-        env->PSW_USB_SV = (1 << 31);                \
-        ret = (target_ulong)max_pos;                \
-    } else {                                        \
-        if (arg < max_neg) {                        \
-            env->PSW_USB_V = (1 << 31);             \
-            env->PSW_USB_SV = (1 << 31);            \
-            ret = (target_ulong)max_neg;            \
-        } else {                                    \
-            env->PSW_USB_V = 0;                     \
-            ret = (target_ulong)arg;                \
-        }                                           \
-    }                                               \
-    env->PSW_USB_AV = arg ^ arg * 2u;               \
-    env->PSW_USB_SAV |= env->PSW_USB_AV;            \
-} while (0)
-
-#define SUOV(env, ret, arg, len) do {               \
-    int64_t max_pos = UINT##len ##_MAX;             \
-    if (arg > max_pos) {                            \
-        env->PSW_USB_V = (1 << 31);                 \
-        env->PSW_USB_SV = (1 << 31);                \
-        ret = (target_ulong)max_pos;                \
-    } else {                                        \
-        if (arg < 0) {                              \
-            env->PSW_USB_V = (1 << 31);             \
-            env->PSW_USB_SV = (1 << 31);            \
-            ret = 0;                                \
-        } else {                                    \
-            env->PSW_USB_V = 0;                     \
-            ret = (target_ulong)arg;                \
-        }                                           \
-     }                                              \
-    env->PSW_USB_AV = arg ^ arg * 2u;               \
-    env->PSW_USB_SAV |= env->PSW_USB_AV;            \
-} while (0)
+static uint32_t ssov32(CPUTriCoreState *env, int64_t arg)
+{
+    uint32_t ret;
+    int64_t max_pos = INT32_MAX;
+    int64_t max_neg = INT32_MIN;
+    if (arg > max_pos) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        ret = (target_ulong)max_pos;
+    } else {
+        if (arg < max_neg) {
+            env->PSW_USB_V = (1 << 31);
+            env->PSW_USB_SV = (1 << 31);
+            ret = (target_ulong)max_neg;
+        } else {
+            env->PSW_USB_V = 0;
+            ret = (target_ulong)arg;
+        }
+    }
+    env->PSW_USB_AV = arg ^ arg * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret;
+}
+
+static uint32_t suov32(CPUTriCoreState *env, int64_t arg)
+{
+    uint32_t ret;
+    int64_t max_pos = UINT32_MAX;
+    if (arg > max_pos) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        ret = (target_ulong)max_pos;
+    } else {
+        if (arg < 0) {
+            env->PSW_USB_V = (1 << 31);
+            env->PSW_USB_SV = (1 << 31);
+            ret = 0;
+        } else {
+            env->PSW_USB_V = 0;
+            ret = (target_ulong)arg;
+        }
+     }
+    env->PSW_USB_AV = arg ^ arg * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret;
+}
 
+static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
+{
+    int32_t max_pos = INT16_MAX;
+    int32_t max_neg = INT16_MIN;
+    int32_t av0, av1;
+
+    env->PSW_USB_V = 0;
+    av0 = hw0 ^ hw0 * 2u;
+    if (hw0 > max_pos) {
+        env->PSW_USB_V = (1 << 31);
+        hw0 = max_pos;
+    } else if (hw0 < max_neg) {
+        env->PSW_USB_V = (1 << 31);
+        hw0 = max_neg;
+    }
+
+    av1 = hw1 ^ hw1 * 2u;
+    if (hw1 > max_pos) {
+        env->PSW_USB_V = (1 << 31);
+        hw1 = max_pos;
+    } else if (hw1 < max_neg) {
+        env->PSW_USB_V = (1 << 31);
+        hw1 = max_neg;
+    }
+
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = (av0 | av1) << 16;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return (hw0 & 0xffff) | (hw1 << 16);
+}
+
+static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
+{
+    int32_t max_pos = UINT16_MAX;
+    int32_t av0, av1;
+
+    env->PSW_USB_V = 0;
+    av0 = hw0 ^ hw0 * 2u;
+    if (hw0 > max_pos) {
+        env->PSW_USB_V = (1 << 31);
+        hw0 = max_pos;
+    } else if (hw0 < 0) {
+        env->PSW_USB_V = (1 << 31);
+        hw0 = 0;
+    }
+
+    av1 = hw1 ^ hw1 * 2u;
+    if (hw1 > max_pos) {
+        env->PSW_USB_V = (1 << 31);
+        hw1 = max_pos;
+    } else if (hw1 < 0) {
+        env->PSW_USB_V = (1 << 31);
+        hw1 = 0;
+    }
+
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = (av0 | av1) << 16;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return (hw0 & 0xffff) | (hw1 << 16);
+}
 
 target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = sextract64(r1, 0, 32);
     int64_t t2 = sextract64(r2, 0, 32);
     int64_t result = t1 + t2;
-    SSOV(env, ret, result, 32);
-    return ret;
+    return ssov32(env, result);
+}
+
+target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
+                               target_ulong r2)
+{
+    int32_t ret_hw0, ret_hw1;
+
+    ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16);
+    ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16);
+    return ssov16(env, ret_hw0, ret_hw1);
 }
 
 target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = extract64(r1, 0, 32);
     int64_t t2 = extract64(r2, 0, 32);
     int64_t result = t1 + t2;
-    SUOV(env, ret, result, 32);
-    return ret;
+    return suov32(env, result);
+}
+
+target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1,
+                               target_ulong r2)
+{
+    int32_t ret_hw0, ret_hw1;
+
+    ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16);
+    ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16);
+    return suov16(env, ret_hw0, ret_hw1);
 }
 
 target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = sextract64(r1, 0, 32);
     int64_t t2 = sextract64(r2, 0, 32);
     int64_t result = t1 - t2;
-    SSOV(env, ret, result, 32);
-    return ret;
+    return ssov32(env, result);
+}
+
+target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1,
+                             target_ulong r2)
+{
+    int32_t ret_hw0, ret_hw1;
+
+    ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16);
+    ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16);
+    return ssov16(env, ret_hw0, ret_hw1);
 }
 
 target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = extract64(r1, 0, 32);
     int64_t t2 = extract64(r2, 0, 32);
     int64_t result = t1 - t2;
-    SUOV(env, ret, result, 32);
-    return ret;
+    return suov32(env, result);
+}
+
+target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1,
+                               target_ulong r2)
+{
+    int32_t ret_hw0, ret_hw1;
+
+    ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16);
+    ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16);
+    return suov16(env, ret_hw0, ret_hw1);
 }
 
 target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = sextract64(r1, 0, 32);
     int64_t t2 = sextract64(r2, 0, 32);
     int64_t result = t1 * t2;
-    SSOV(env, ret, result, 32);
-    return ret;
+    return ssov32(env, result);
 }
 
 target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = extract64(r1, 0, 32);
     int64_t t2 = extract64(r2, 0, 32);
     int64_t result = t1 * t2;
-    SUOV(env, ret, result, 32);
-    return ret;
+    return suov32(env, result);
 }
 
 target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = sextract64(r1, 0, 32);
     int32_t t2 = sextract64(r2, 0, 6);
     int64_t result;
@@ -178,14 +271,32 @@ target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
     } else {
         result = t1 >> -t2;
     }
-    SSOV(env, ret, result, 32);
-    return ret;
+    return ssov32(env, result);
+}
+
+uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1)
+{
+    target_ulong result;
+    result = ((int32_t)r1 >= 0) ? r1 : (0 - r1);
+    return ssov32(env, result);
+}
+
+uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1)
+{
+    int32_t ret_h0, ret_h1;
+
+    ret_h0 = sextract32(r1, 0, 16);
+    ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0);
+
+    ret_h1 = sextract32(r1, 16, 16);
+    ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1);
+
+    return ssov16(env, ret_h0, ret_h1);
 }
 
 target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
                                 target_ulong r2)
 {
-    target_ulong ret;
     int64_t t1 = sextract64(r1, 0, 32);
     int64_t t2 = sextract64(r2, 0, 32);
     int64_t result;
@@ -195,36 +306,56 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
     } else {
         result = t2 - t1;
     }
-    SSOV(env, ret, result, 32);
-    return ret;
+    return ssov32(env, result);
+}
+
+uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1,
+                              target_ulong r2)
+{
+    int32_t t1, t2;
+    int32_t ret_h0, ret_h1;
+
+    t1 = sextract32(r1, 0, 16);
+    t2 = sextract32(r2, 0, 16);
+    if (t1 > t2) {
+        ret_h0 = t1 - t2;
+    } else {
+        ret_h0 = t2 - t1;
+    }
+
+    t1 = sextract32(r1, 16, 16);
+    t2 = sextract32(r2, 16, 16);
+    if (t1 > t2) {
+        ret_h1 = t1 - t2;
+    } else {
+        ret_h1 = t2 - t1;
+    }
+
+    return ssov16(env, ret_h0, ret_h1);
 }
 
 target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1,
                                 target_ulong r2, target_ulong r3)
 {
-    target_ulong ret;
     int64_t t1 = sextract64(r1, 0, 32);
     int64_t t2 = sextract64(r2, 0, 32);
     int64_t t3 = sextract64(r3, 0, 32);
     int64_t result;
 
     result = t2 + (t1 * t3);
-    SSOV(env, ret, result, 32);
-    return ret;
+    return ssov32(env, result);
 }
 
 target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1,
                                 target_ulong r2, target_ulong r3)
 {
-    target_ulong ret;
     uint64_t t1 = extract64(r1, 0, 32);
     uint64_t t2 = extract64(r2, 0, 32);
     uint64_t t3 = extract64(r3, 0, 32);
     int64_t result;
 
     result = t2 + (t1 * t3);
-    SUOV(env, ret, result, 32);
-    return ret;
+    return suov32(env, result);
 }
 
 uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -286,29 +417,25 @@ uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
 target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1,
                                 target_ulong r2, target_ulong r3)
 {
-    target_ulong ret;
     int64_t t1 = sextract64(r1, 0, 32);
     int64_t t2 = sextract64(r2, 0, 32);
     int64_t t3 = sextract64(r3, 0, 32);
     int64_t result;
 
     result = t2 - (t1 * t3);
-    SSOV(env, ret, result, 32);
-    return ret;
+    return ssov32(env, result);
 }
 
 target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,
                                 target_ulong r2, target_ulong r3)
 {
-    target_ulong ret;
     int64_t t1 = extract64(r1, 0, 32);
     int64_t t2 = extract64(r2, 0, 32);
     int64_t t3 = extract64(r3, 0, 32);
     int64_t result;
 
     result = t2 - (t1 * t3);
-    SUOV(env, ret, result, 32);
-    return ret;
+    return suov32(env, result);
 }
 
 uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -366,6 +493,813 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
     return ret;
 }
 
+uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg)
+{
+    int32_t b, i;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    int32_t ret = 0;
+
+    for (i = 0; i < 4; i++) {
+        b = sextract32(arg, i * 8, 8);
+        b = (b >= 0) ? b : (0 - b);
+        ovf |= (b > 0x7F) || (b < -0x80);
+        avf |= b ^ b * 2u;
+        ret |= (b & 0xff) << (i * 8);
+    }
+
+    env->PSW_USB_V = ovf << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = avf << 24;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg)
+{
+    int32_t h, i;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    int32_t ret = 0;
+
+    for (i = 0; i < 2; i++) {
+        h = sextract32(arg, i * 16, 16);
+        h = (h >= 0) ? h : (0 - h);
+        ovf |= (h > 0x7FFF) || (h < -0x8000);
+        avf |= h ^ h * 2u;
+        ret |= (h & 0xffff) << (i * 16);
+    }
+
+    env->PSW_USB_V = ovf << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = avf << 16;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+    int32_t b, i;
+    int32_t extr_r2;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    int32_t ret = 0;
+
+    for (i = 0; i < 4; i++) {
+        extr_r2 = sextract32(r2, i * 8, 8);
+        b = sextract32(r1, i * 8, 8);
+        b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b);
+        ovf |= (b > 0x7F) || (b < -0x80);
+        avf |= b ^ b * 2u;
+        ret |= (b & 0xff) << (i * 8);
+    }
+
+    env->PSW_USB_V = ovf << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = avf << 24;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret;
+}
+
+uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+    int32_t h, i;
+    int32_t extr_r2;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    int32_t ret = 0;
+
+    for (i = 0; i < 2; i++) {
+        extr_r2 = sextract32(r2, i * 16, 16);
+        h = sextract32(r1, i * 16, 16);
+        h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h);
+        ovf |= (h > 0x7FFF) || (h < -0x8000);
+        avf |= h ^ h * 2u;
+        ret |= (h & 0xffff) << (i * 16);
+    }
+
+    env->PSW_USB_V = ovf << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = avf << 16;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+    int32_t b, i;
+    int32_t extr_r1, extr_r2;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    uint32_t ret = 0;
+
+    for (i = 0; i < 4; i++) {
+        extr_r1 = sextract32(r1, i * 8, 8);
+        extr_r2 = sextract32(r2, i * 8, 8);
+
+        b = extr_r1 + extr_r2;
+        ovf |= ((b > 0x7f) || (b < -0x80));
+        avf |= b ^ b * 2u;
+        ret |= ((b & 0xff) << (i*8));
+    }
+
+    env->PSW_USB_V = (ovf << 31);
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = avf << 24;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+    int32_t h, i;
+    int32_t extr_r1, extr_r2;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    int32_t ret = 0;
+
+    for (i = 0; i < 2; i++) {
+        extr_r1 = sextract32(r1, i * 16, 16);
+        extr_r2 = sextract32(r2, i * 16, 16);
+        h = extr_r1 + extr_r2;
+        ovf |= ((h > 0x7fff) || (h < -0x8000));
+        avf |= h ^ h * 2u;
+        ret |= (h & 0xffff) << (i * 16);
+    }
+
+    env->PSW_USB_V = (ovf << 31);
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = (avf << 16);
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+    int32_t b, i;
+    int32_t extr_r1, extr_r2;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    uint32_t ret = 0;
+
+    for (i = 0; i < 4; i++) {
+        extr_r1 = sextract32(r1, i * 8, 8);
+        extr_r2 = sextract32(r2, i * 8, 8);
+
+        b = extr_r1 - extr_r2;
+        ovf |= ((b > 0x7f) || (b < -0x80));
+        avf |= b ^ b * 2u;
+        ret |= ((b & 0xff) << (i*8));
+    }
+
+    env->PSW_USB_V = (ovf << 31);
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = avf << 24;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+    int32_t h, i;
+    int32_t extr_r1, extr_r2;
+    int32_t ovf = 0;
+    int32_t avf = 0;
+    int32_t ret = 0;
+
+    for (i = 0; i < 2; i++) {
+        extr_r1 = sextract32(r1, i * 16, 16);
+        extr_r2 = sextract32(r2, i * 16, 16);
+        h = extr_r1 - extr_r2;
+        ovf |= ((h > 0x7fff) || (h < -0x8000));
+        avf |= h ^ h * 2u;
+        ret |= (h & 0xffff) << (i * 16);
+    }
+
+    env->PSW_USB_V = (ovf << 31);
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = avf << 16;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_eq_b(target_ulong r1, target_ulong r2)
+{
+    int32_t ret;
+    int32_t i, msk;
+
+    ret = 0;
+    msk = 0xff;
+    for (i = 0; i < 4; i++) {
+        if ((r1 & msk) == (r2 & msk)) {
+            ret |= msk;
+        }
+        msk = msk << 8;
+    }
+
+    return ret;
+}
+
+uint32_t helper_eq_h(target_ulong r1, target_ulong r2)
+{
+    int32_t ret = 0;
+
+    if ((r1 & 0xffff) == (r2 & 0xffff)) {
+        ret = 0xffff;
+    }
+
+    if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) {
+        ret |= 0xffff0000;
+    }
+
+    return ret;
+}
+
+uint32_t helper_eqany_b(target_ulong r1, target_ulong r2)
+{
+    int32_t i;
+    uint32_t ret = 0;
+
+    for (i = 0; i < 4; i++) {
+        ret |= (sextract32(r1,  i * 8, 8) == sextract32(r2,  i * 8, 8));
+    }
+
+    return ret;
+}
+
+uint32_t helper_eqany_h(target_ulong r1, target_ulong r2)
+{
+    uint32_t ret;
+
+    ret = (sextract32(r1, 0, 16) == sextract32(r2,  0, 16));
+    ret |= (sextract32(r1, 16, 16) == sextract32(r2,  16, 16));
+
+    return ret;
+}
+
+uint32_t helper_lt_b(target_ulong r1, target_ulong r2)
+{
+    int32_t i;
+    uint32_t ret = 0;
+
+    for (i = 0; i < 4; i++) {
+        if (sextract32(r1,  i * 8, 8) < sextract32(r2,  i * 8, 8)) {
+            ret |= (0xff << (i * 8));
+        }
+    }
+
+    return ret;
+}
+
+uint32_t helper_lt_bu(target_ulong r1, target_ulong r2)
+{
+    int32_t i;
+    uint32_t ret = 0;
+
+    for (i = 0; i < 4; i++) {
+        if (extract32(r1,  i * 8, 8) < extract32(r2,  i * 8, 8)) {
+            ret |= (0xff << (i * 8));
+        }
+    }
+
+    return ret;
+}
+
+uint32_t helper_lt_h(target_ulong r1, target_ulong r2)
+{
+    uint32_t ret = 0;
+
+    if (sextract32(r1,  0, 16) < sextract32(r2,  0, 16)) {
+        ret |= 0xffff;
+    }
+
+    if (sextract32(r1,  16, 16) < sextract32(r2,  16, 16)) {
+        ret |= 0xffff0000;
+    }
+
+    return ret;
+}
+
+uint32_t helper_lt_hu(target_ulong r1, target_ulong r2)
+{
+    uint32_t ret = 0;
+
+    if (extract32(r1,  0, 16) < extract32(r2,  0, 16)) {
+        ret |= 0xffff;
+    }
+
+    if (extract32(r1,  16, 16) < extract32(r2,  16, 16)) {
+        ret |= 0xffff0000;
+    }
+
+    return ret;
+}
+
+#define EXTREMA_H_B(name, op)                                 \
+uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \
+{                                                             \
+    int32_t i, extr_r1, extr_r2;                              \
+    uint32_t ret = 0;                                         \
+                                                              \
+    for (i = 0; i < 4; i++) {                                 \
+        extr_r1 = sextract32(r1, i * 8, 8);                   \
+        extr_r2 = sextract32(r2, i * 8, 8);                   \
+        extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2;   \
+        ret |= (extr_r1 & 0xff) << (i * 8);                   \
+    }                                                         \
+    return ret;                                               \
+}                                                             \
+                                                              \
+uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\
+{                                                             \
+    int32_t i;                                                \
+    uint32_t extr_r1, extr_r2;                                \
+    uint32_t ret = 0;                                         \
+                                                              \
+    for (i = 0; i < 4; i++) {                                 \
+        extr_r1 = extract32(r1, i * 8, 8);                    \
+        extr_r2 = extract32(r2, i * 8, 8);                    \
+        extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2;   \
+        ret |= (extr_r1 & 0xff) << (i * 8);                   \
+    }                                                         \
+    return ret;                                               \
+}                                                             \
+                                                              \
+uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \
+{                                                             \
+    int32_t extr_r1, extr_r2;                                 \
+    uint32_t ret = 0;                                         \
+                                                              \
+    extr_r1 = sextract32(r1, 0, 16);                          \
+    extr_r2 = sextract32(r2, 0, 16);                          \
+    ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2;           \
+    ret = ret & 0xffff;                                       \
+                                                              \
+    extr_r1 = sextract32(r1, 16, 16);                         \
+    extr_r2 = sextract32(r2, 16, 16);                         \
+    extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2;       \
+    ret |= extr_r1 << 16;                                     \
+                                                              \
+    return ret;                                               \
+}                                                             \
+                                                              \
+uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\
+{                                                             \
+    uint32_t extr_r1, extr_r2;                                \
+    uint32_t ret = 0;                                         \
+                                                              \
+    extr_r1 = extract32(r1, 0, 16);                           \
+    extr_r2 = extract32(r2, 0, 16);                           \
+    ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2;           \
+    ret = ret & 0xffff;                                       \
+                                                              \
+    extr_r1 = extract32(r1, 16, 16);                          \
+    extr_r2 = extract32(r2, 16, 16);                          \
+    extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2;       \
+    ret |= extr_r1 << (16);                                   \
+                                                              \
+    return ret;                                               \
+}                                                             \
+
+EXTREMA_H_B(max, >)
+EXTREMA_H_B(min, <)
+
+#undef EXTREMA_H_B
+
+uint32_t helper_clo(target_ulong r1)
+{
+    return clo32(r1);
+}
+
+uint32_t helper_clo_h(target_ulong r1)
+{
+    uint32_t ret_hw0 = extract32(r1, 0, 16);
+    uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+    ret_hw0 = clo32(ret_hw0 << 16);
+    ret_hw1 = clo32(ret_hw1 << 16);
+
+    if (ret_hw0 > 16) {
+        ret_hw0 = 16;
+    }
+    if (ret_hw1 > 16) {
+        ret_hw1 = 16;
+    }
+
+    return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_clz(target_ulong r1)
+{
+    return clz32(r1);
+}
+
+uint32_t helper_clz_h(target_ulong r1)
+{
+    uint32_t ret_hw0 = extract32(r1, 0, 16);
+    uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+    ret_hw0 = clz32(ret_hw0 << 16);
+    ret_hw1 = clz32(ret_hw1 << 16);
+
+    if (ret_hw0 > 16) {
+        ret_hw0 = 16;
+    }
+    if (ret_hw1 > 16) {
+        ret_hw1 = 16;
+    }
+
+    return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_cls(target_ulong r1)
+{
+    return clrsb32(r1);
+}
+
+uint32_t helper_cls_h(target_ulong r1)
+{
+    uint32_t ret_hw0 = extract32(r1, 0, 16);
+    uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+    ret_hw0 = clrsb32(ret_hw0 << 16);
+    ret_hw1 = clrsb32(ret_hw1 << 16);
+
+    if (ret_hw0 > 15) {
+        ret_hw0 = 15;
+    }
+    if (ret_hw1 > 15) {
+        ret_hw1 = 15;
+    }
+
+    return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_sh(target_ulong r1, target_ulong r2)
+{
+    int32_t shift_count = sextract32(r2, 0, 6);
+
+    if (shift_count == -32) {
+        return 0;
+    } else if (shift_count < 0) {
+        return r1 >> -shift_count;
+    } else {
+        return r1 << shift_count;
+    }
+}
+
+uint32_t helper_sh_h(target_ulong r1, target_ulong r2)
+{
+    int32_t ret_hw0, ret_hw1;
+    int32_t shift_count;
+
+    shift_count = sextract32(r2, 0, 5);
+
+    if (shift_count == -16) {
+        return 0;
+    } else if (shift_count < 0) {
+        ret_hw0 = extract32(r1, 0, 16) >> -shift_count;
+        ret_hw1 = extract32(r1, 16, 16) >> -shift_count;
+        return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+    } else {
+        ret_hw0 = extract32(r1, 0, 16) << shift_count;
+        ret_hw1 = extract32(r1, 16, 16) << shift_count;
+        return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+    }
+}
+
+uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+    int32_t shift_count;
+    int64_t result, t1;
+    uint32_t ret;
+
+    shift_count = sextract32(r2, 0, 6);
+    t1 = sextract32(r1, 0, 32);
+
+    if (shift_count == 0) {
+        env->PSW_USB_C = env->PSW_USB_V = 0;
+        ret = r1;
+    } else if (shift_count == -32) {
+        env->PSW_USB_C = r1;
+        env->PSW_USB_V = 0;
+        ret = t1 >> 31;
+    } else if (shift_count > 0) {
+        result = t1 << shift_count;
+        /* calc carry */
+        env->PSW_USB_C = ((result & 0xffffffff00000000) != 0);
+        /* calc v */
+        env->PSW_USB_V = (((result > 0x7fffffffLL) ||
+                           (result < -0x80000000LL)) << 31);
+        /* calc sv */
+        env->PSW_USB_SV |= env->PSW_USB_V;
+        ret = (uint32_t)result;
+    } else {
+        env->PSW_USB_V = 0;
+        env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1));
+        ret = t1 >> -shift_count;
+    }
+
+    env->PSW_USB_AV = ret ^ ret * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint32_t helper_sha_h(target_ulong r1, target_ulong r2)
+{
+    int32_t shift_count;
+    int32_t ret_hw0, ret_hw1;
+
+    shift_count = sextract32(r2, 0, 5);
+
+    if (shift_count == 0) {
+        return r1;
+    } else if (shift_count < 0) {
+        ret_hw0 = sextract32(r1, 0, 16) >> -shift_count;
+        ret_hw1 = sextract32(r1, 16, 16) >> -shift_count;
+        return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+    } else {
+        ret_hw0 = sextract32(r1, 0, 16) << shift_count;
+        ret_hw1 = sextract32(r1, 16, 16) << shift_count;
+        return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+    }
+}
+
+uint32_t helper_bmerge(target_ulong r1, target_ulong r2)
+{
+    uint32_t i, ret;
+
+    ret = 0;
+    for (i = 0; i < 16; i++) {
+        ret |= (r1 & 1) << (2 * i + 1);
+        ret |= (r2 & 1) << (2 * i);
+        r1 = r1 >> 1;
+        r2 = r2 >> 1;
+    }
+    return ret;
+}
+
+uint64_t helper_bsplit(uint32_t r1)
+{
+    int32_t i;
+    uint64_t ret;
+
+    ret = 0;
+    for (i = 0; i < 32; i = i + 2) {
+        /* even */
+        ret |= (r1 & 1) << (i/2);
+        r1 = r1 >> 1;
+        /* odd */
+        ret |= (uint64_t)(r1 & 1) << (i/2 + 32);
+        r1 = r1 >> 1;
+    }
+    return ret;
+}
+
+uint32_t helper_parity(target_ulong r1)
+{
+    uint32_t ret;
+    uint32_t nOnes, i;
+
+    ret = 0;
+    nOnes = 0;
+    for (i = 0; i < 8; i++) {
+        ret ^= (r1 & 1);
+        r1 = r1 >> 1;
+    }
+    /* second byte */
+    nOnes = 0;
+    for (i = 0; i < 8; i++) {
+        nOnes ^= (r1 & 1);
+        r1 = r1 >> 1;
+    }
+    ret |= nOnes << 8;
+    /* third byte */
+    nOnes = 0;
+    for (i = 0; i < 8; i++) {
+        nOnes ^= (r1 & 1);
+        r1 = r1 >> 1;
+    }
+    ret |= nOnes << 16;
+    /* fourth byte */
+    nOnes = 0;
+    for (i = 0; i < 8; i++) {
+        nOnes ^= (r1 & 1);
+        r1 = r1 >> 1;
+    }
+    ret |= nOnes << 24;
+
+    return ret;
+}
+
+uint64_t helper_unpack(target_ulong arg1)
+{
+    int32_t fp_exp  = extract32(arg1, 23, 8);
+    int32_t fp_frac = extract32(arg1, 0, 23);
+    uint64_t ret;
+    int32_t int_exp, int_mant;
+
+    if (fp_exp == 255) {
+        int_exp = 255;
+        int_mant = (fp_frac << 7);
+    } else if ((fp_exp == 0) && (fp_frac == 0)) {
+        int_exp  = -127;
+        int_mant = 0;
+    } else if ((fp_exp == 0) && (fp_frac != 0)) {
+        int_exp  = -126;
+        int_mant = (fp_frac << 7);
+    } else {
+        int_exp  = fp_exp - 127;
+        int_mant = (fp_frac << 7);
+        int_mant |= (1 << 30);
+    }
+    ret = int_exp;
+    ret = ret << 32;
+    ret |= int_mant;
+
+    return ret;
+}
+
+uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+    uint64_t ret;
+    int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
+    int32_t quotient_sign;
+
+    ret = sextract32(r1, 0, 32);
+    ret = ret << 24;
+    quotient_sign = 0;
+    if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+        ret |= 0xffffff;
+        quotient_sign = 1;
+    }
+
+    abs_sig_dividend = abs(r1) >> 7;
+    abs_base_dividend = abs(r1) & 0x7f;
+    abs_divisor = abs(r1);
+    /* calc overflow */
+    env->PSW_USB_V = 0;
+    if ((quotient_sign) && (abs_divisor)) {
+        env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
+                         (abs_base_dividend >= abs_divisor)) ||
+                         (abs_sig_dividend > abs_divisor));
+    } else {
+        env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
+    }
+    env->PSW_USB_V = env->PSW_USB_V << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = 0;
+
+    return ret;
+}
+
+uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+    uint64_t ret = sextract32(r1, 0, 32);
+
+    ret = ret << 24;
+    if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+        ret |= 0xffffff;
+    }
+    /* calc overflow */
+    env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80)));
+    env->PSW_USB_V = env->PSW_USB_V << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = 0;
+
+    return ret;
+}
+
+uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+    uint64_t ret;
+    int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
+    int32_t quotient_sign;
+
+    ret = sextract32(r1, 0, 32);
+    ret = ret << 16;
+    quotient_sign = 0;
+    if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+        ret |= 0xffff;
+        quotient_sign = 1;
+    }
+
+    abs_sig_dividend = abs(r1) >> 7;
+    abs_base_dividend = abs(r1) & 0x7f;
+    abs_divisor = abs(r1);
+    /* calc overflow */
+    env->PSW_USB_V = 0;
+    if ((quotient_sign) && (abs_divisor)) {
+        env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
+                         (abs_base_dividend >= abs_divisor)) ||
+                         (abs_sig_dividend > abs_divisor));
+    } else {
+        env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
+    }
+    env->PSW_USB_V = env->PSW_USB_V << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = 0;
+
+    return ret;
+}
+
+uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+    uint64_t ret = sextract32(r1, 0, 32);
+
+    ret = ret << 16;
+    if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+        ret |= 0xffff;
+    }
+    /* calc overflow */
+    env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000)));
+    env->PSW_USB_V = env->PSW_USB_V << 31;
+    env->PSW_USB_SV |= env->PSW_USB_V;
+    env->PSW_USB_AV = 0;
+
+    return ret;
+}
+
+uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01,
+                      uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+    uint64_t ret;
+    uint32_t result0, result1;
+
+    int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+                  ((arg10 & 0xffff) == 0x8000) && (n == 1);
+    int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+                  ((arg11 & 0xffff) == 0x8000) && (n == 1);
+    if (sc1) {
+        result1 = 0x7fffffff;
+    } else {
+        result1 = (((uint32_t)(arg00 * arg10)) << n);
+    }
+    if (sc0) {
+        result0 = 0x7fffffff;
+    } else {
+        result0 = (((uint32_t)(arg01 * arg11)) << n);
+    }
+    ret = (((uint64_t)result1 << 32)) | result0;
+    return ret;
+}
+
+uint64_t helper_mulm_h(uint32_t arg00, uint32_t arg01,
+                       uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+    uint64_t ret;
+    int64_t result0, result1;
+
+    int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+                  ((arg10 & 0xffff) == 0x8000) && (n == 1);
+    int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+                  ((arg11 & 0xffff) == 0x8000) && (n == 1);
+
+    if (sc1) {
+        result1 = 0x7fffffff;
+    } else {
+        result1 = (((int32_t)arg00 * (int32_t)arg10) << n);
+    }
+    if (sc0) {
+        result0 = 0x7fffffff;
+    } else {
+        result0 = (((int32_t)arg01 * (int32_t)arg11) << n);
+    }
+    ret = (result1 + result0);
+    ret = ret << 16;
+    return ret;
+}
+uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01,
+                       uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+    uint32_t result0, result1;
+
+    int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+                  ((arg10 & 0xffff) == 0x8000) && (n == 1);
+    int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+                  ((arg11 & 0xffff) == 0x8000) && (n == 1);
+
+    if (sc1) {
+        result1 = 0x7fffffff;
+    } else {
+        result1 = ((arg00 * arg10) << n) + 0x8000;
+    }
+    if (sc0) {
+        result0 = 0x7fffffff;
+    } else {
+        result0 = ((arg01 * arg11) << n) + 0x8000;
+    }
+    return (result1 & 0xffff0000) | (result0 >> 16);
+}
+
 /* context save area (CSA) related helpers */
 
 static int cdc_increment(target_ulong *psw)
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 65abf453f0..dbcf87e383 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -85,22 +85,31 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
 {
     TriCoreCPU *cpu = TRICORE_CPU(cs);
     CPUTriCoreState *env = &cpu->env;
+    uint32_t psw;
     int i;
 
-    cpu_fprintf(f, "PC=%08x\n", env->PC);
+    psw = psw_read(env);
+
+    cpu_fprintf(f, "PC: " TARGET_FMT_lx, env->PC);
+    cpu_fprintf(f, " PSW: " TARGET_FMT_lx, psw);
+    cpu_fprintf(f, " ICR: " TARGET_FMT_lx, env->ICR);
+    cpu_fprintf(f, "\nPCXI: " TARGET_FMT_lx, env->PCXI);
+    cpu_fprintf(f, " FCX: " TARGET_FMT_lx, env->FCX);
+    cpu_fprintf(f, " LCX: " TARGET_FMT_lx, env->LCX);
+
     for (i = 0; i < 16; ++i) {
         if ((i & 3) == 0) {
-            cpu_fprintf(f, "GPR A%02d:", i);
+            cpu_fprintf(f, "\nGPR A%02d:", i);
         }
-        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]);
+        cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_a[i]);
     }
     for (i = 0; i < 16; ++i) {
         if ((i & 3) == 0) {
-            cpu_fprintf(f, "GPR D%02d:", i);
+            cpu_fprintf(f, "\nGPR D%02d:", i);
         }
-        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]);
+        cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_d[i]);
     }
-
+    cpu_fprintf(f, "\n");
 }
 
 /*
@@ -115,6 +124,64 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
     tcg_temp_free_i32(helper_tmp);                                \
     } while (0)
 
+#define GEN_HELPER_LL(name, ret, arg0, arg1, n) do {         \
+    TCGv arg00 = tcg_temp_new();                             \
+    TCGv arg01 = tcg_temp_new();                             \
+    TCGv arg11 = tcg_temp_new();                             \
+    tcg_gen_sari_tl(arg00, arg0, 16);                        \
+    tcg_gen_ext16s_tl(arg01, arg0);                          \
+    tcg_gen_ext16s_tl(arg11, arg1);                          \
+    gen_helper_##name(ret, arg00, arg01, arg11, arg11, n);   \
+    tcg_temp_free(arg00);                                    \
+    tcg_temp_free(arg01);                                    \
+    tcg_temp_free(arg11);                                    \
+} while (0)
+
+#define GEN_HELPER_LU(name, ret, arg0, arg1, n) do {         \
+    TCGv arg00 = tcg_temp_new();                             \
+    TCGv arg01 = tcg_temp_new();                             \
+    TCGv arg10 = tcg_temp_new();                             \
+    TCGv arg11 = tcg_temp_new();                             \
+    tcg_gen_sari_tl(arg00, arg0, 16);                        \
+    tcg_gen_ext16s_tl(arg01, arg0);                          \
+    tcg_gen_sari_tl(arg11, arg1, 16);                        \
+    tcg_gen_ext16s_tl(arg10, arg1);                          \
+    gen_helper_##name(ret, arg00, arg01, arg10, arg11, n);   \
+    tcg_temp_free(arg00);                                    \
+    tcg_temp_free(arg01);                                    \
+    tcg_temp_free(arg10);                                    \
+    tcg_temp_free(arg11);                                    \
+} while (0)
+
+#define GEN_HELPER_UL(name, ret, arg0, arg1, n) do {         \
+    TCGv arg00 = tcg_temp_new();                             \
+    TCGv arg01 = tcg_temp_new();                             \
+    TCGv arg10 = tcg_temp_new();                             \
+    TCGv arg11 = tcg_temp_new();                             \
+    tcg_gen_sari_tl(arg00, arg0, 16);                        \
+    tcg_gen_ext16s_tl(arg01, arg0);                          \
+    tcg_gen_sari_tl(arg10, arg1, 16);                        \
+    tcg_gen_ext16s_tl(arg11, arg1);                          \
+    gen_helper_##name(ret, arg00, arg01, arg10, arg11, n);   \
+    tcg_temp_free(arg00);                                    \
+    tcg_temp_free(arg01);                                    \
+    tcg_temp_free(arg10);                                    \
+    tcg_temp_free(arg11);                                    \
+} while (0)
+
+#define GEN_HELPER_UU(name, ret, arg0, arg1, n) do {         \
+    TCGv arg00 = tcg_temp_new();                             \
+    TCGv arg01 = tcg_temp_new();                             \
+    TCGv arg11 = tcg_temp_new();                             \
+    tcg_gen_sari_tl(arg01, arg0, 16);                        \
+    tcg_gen_ext16s_tl(arg00, arg0);                          \
+    tcg_gen_sari_tl(arg11, arg1, 16);                        \
+    gen_helper_##name(ret, arg00, arg01, arg11, arg11, n);   \
+    tcg_temp_free(arg00);                                    \
+    tcg_temp_free(arg01);                                    \
+    tcg_temp_free(arg11);                                    \
+} while (0)
+
 #define EA_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF))
 #define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \
                            ((offset & 0x0fffff) << 1))
@@ -719,6 +786,62 @@ static inline void gen_sub_d(TCGv ret, TCGv r1, TCGv r2)
     tcg_temp_free(result);
 }
 
+static inline void gen_sub_CC(TCGv ret, TCGv r1, TCGv r2)
+{
+    TCGv result = tcg_temp_new();
+    TCGv temp = tcg_temp_new();
+
+    tcg_gen_sub_tl(result, r1, r2);
+    /* calc C bit */
+    tcg_gen_setcond_tl(TCG_COND_GEU, cpu_PSW_C, r1, r2);
+    /* calc V bit */
+    tcg_gen_xor_tl(cpu_PSW_V, result, r1);
+    tcg_gen_xor_tl(temp, r1, r2);
+    tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, temp);
+    /* calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV bit */
+    tcg_gen_add_tl(cpu_PSW_AV, result, result);
+    tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV);
+    /* calc SAV bit */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+    /* write back result */
+    tcg_gen_mov_tl(ret, result);
+
+    tcg_temp_free(result);
+    tcg_temp_free(temp);
+}
+
+static inline void gen_subc_CC(TCGv ret, TCGv r1, TCGv r2)
+{
+    TCGv temp = tcg_temp_new();
+    tcg_gen_not_tl(temp, r2);
+    gen_addc_CC(ret, r1, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void gen_abs(TCGv ret, TCGv r1)
+{
+    TCGv temp = tcg_temp_new();
+    TCGv t0 = tcg_const_i32(0);
+
+    tcg_gen_neg_tl(temp, r1);
+    tcg_gen_movcond_tl(TCG_COND_GE, ret, r1, t0, r1, temp);
+    /* overflow can only happen, if r1 = 0x80000000 */
+    tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, r1, 0x80000000);
+    tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+    /* calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV bit */
+    tcg_gen_add_tl(cpu_PSW_AV, ret, ret);
+    tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV);
+    /* calc SAV bit */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+    tcg_temp_free(temp);
+    tcg_temp_free(t0);
+}
+
 static inline void gen_absdif(TCGv ret, TCGv r1, TCGv r2)
 {
     TCGv temp = tcg_temp_new_i32();
@@ -1208,6 +1331,13 @@ gen_accumulating_condi(int cond, TCGv ret, TCGv r1, int32_t con,
     tcg_temp_free(temp);
 }
 
+/* ret = (r1 cond r2) ? 0xFFFFFFFF ? 0x00000000;*/
+static inline void gen_cond_w(TCGCond cond, TCGv ret, TCGv r1, TCGv r2)
+{
+    tcg_gen_setcond_tl(cond, ret, r1, r2);
+    tcg_gen_neg_tl(ret, ret);
+}
+
 static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con)
 {
     TCGv b0 = tcg_temp_new();
@@ -1284,6 +1414,86 @@ static inline void gen_insert(TCGv ret, TCGv r1, TCGv r2, TCGv width, TCGv pos)
     tcg_temp_free(temp2);
 }
 
+static inline void gen_bsplit(TCGv rl, TCGv rh, TCGv r1)
+{
+    TCGv_i64 temp = tcg_temp_new_i64();
+
+    gen_helper_bsplit(temp, r1);
+    tcg_gen_extr_i64_i32(rl, rh, temp);
+
+    tcg_temp_free_i64(temp);
+}
+
+static inline void gen_unpack(TCGv rl, TCGv rh, TCGv r1)
+{
+    TCGv_i64 temp = tcg_temp_new_i64();
+
+    gen_helper_unpack(temp, r1);
+    tcg_gen_extr_i64_i32(rl, rh, temp);
+
+    tcg_temp_free_i64(temp);
+}
+
+static inline void
+gen_dvinit_b(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+{
+    TCGv_i64 ret = tcg_temp_new_i64();
+
+    if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+        gen_helper_dvinit_b_13(ret, cpu_env, r1, r2);
+    } else {
+        gen_helper_dvinit_b_131(ret, cpu_env, r1, r2);
+    }
+    tcg_gen_extr_i64_i32(rl, rh, ret);
+
+    tcg_temp_free_i64(ret);
+}
+
+static inline void
+gen_dvinit_h(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+{
+    TCGv_i64 ret = tcg_temp_new_i64();
+
+    if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+        gen_helper_dvinit_h_13(ret, cpu_env, r1, r2);
+    } else {
+        gen_helper_dvinit_h_131(ret, cpu_env, r1, r2);
+    }
+    tcg_gen_extr_i64_i32(rl, rh, ret);
+
+    tcg_temp_free_i64(ret);
+}
+
+static void gen_calc_usb_mul_h(TCGv arg_low, TCGv arg_high)
+{
+    TCGv temp = tcg_temp_new();
+    /* calc AV bit */
+    tcg_gen_add_tl(temp, arg_low, arg_low);
+    tcg_gen_xor_tl(temp, temp, arg_low);
+    tcg_gen_add_tl(cpu_PSW_AV, arg_high, arg_high);
+    tcg_gen_xor_tl(cpu_PSW_AV, cpu_PSW_AV, arg_high);
+    tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp);
+    /* calc SAV bit */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+    tcg_gen_movi_tl(cpu_PSW_V, 0);
+    tcg_temp_free(temp);
+}
+
+static void gen_calc_usb_mulr_h(TCGv arg)
+{
+    TCGv temp = tcg_temp_new();
+    /* calc AV bit */
+    tcg_gen_add_tl(temp, arg, arg);
+    tcg_gen_xor_tl(temp, temp, arg);
+    tcg_gen_shli_tl(cpu_PSW_AV, temp, 16);
+    tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp);
+    /* calc SAV bit */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+    /* clear V bit */
+    tcg_gen_movi_tl(cpu_PSW_V, 0);
+    tcg_temp_free(temp);
+}
+
 /* helpers for generating program flow micro-ops */
 
 static inline void gen_save_pc(target_ulong pc)
@@ -3203,7 +3413,7 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
         tcg_gen_qemu_ld_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LEUL);
         tcg_temp_free(temp);
         break;
-    case OPC1_32_BOL_LD_W_LONFOFF:
+    case OPC1_32_BOL_LD_W_LONGOFF:
         temp = tcg_temp_new();
         tcg_gen_addi_tl(temp, cpu_gpr_a[r2], address);
         tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUL);
@@ -3222,8 +3432,49 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
     case OPC1_32_BOL_ST_W_LONGOFF:
         gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL);
         break;
+    case OPC1_32_BOL_LD_B_LONGOFF:
+        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+            gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
+        } else {
+            /* raise illegal opcode trap */
+        }
+        break;
+    case OPC1_32_BOL_LD_BU_LONGOFF:
+        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+            gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_UB);
+        } else {
+            /* raise illegal opcode trap */
+        }
+        break;
+    case OPC1_32_BOL_LD_H_LONGOFF:
+        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+            gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
+        } else {
+            /* raise illegal opcode trap */
+        }
+        break;
+    case OPC1_32_BOL_LD_HU_LONGOFF:
+        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+            gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUW);
+        } else {
+            /* raise illegal opcode trap */
+        }
+        break;
+    case OPC1_32_BOL_ST_B_LONGOFF:
+        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+            gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
+        } else {
+            /* raise illegal opcode trap */
+        }
+        break;
+    case OPC1_32_BOL_ST_H_LONGOFF:
+        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+            gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
+        } else {
+            /* raise illegal opcode trap */
+        }
+        break;
     }
-
 }
 
 /* RC format */
@@ -3776,11 +4027,23 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
         tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r1], const16 << 16);
         break;
     case OPC1_32_RLC_MFCR:
+        const16 = MASK_OP_RLC_CONST16(ctx->opcode);
         gen_mfcr(env, cpu_gpr_d[r2], const16);
         break;
     case OPC1_32_RLC_MOV:
         tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
         break;
+    case OPC1_32_RLC_MOV_64:
+        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+            if ((r2 & 0x1) != 0) {
+                /* TODO: raise OPD trap */
+            }
+            tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
+            tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15);
+        } else {
+            /* TODO: raise illegal opcode trap */
+        }
+        break;
     case OPC1_32_RLC_MOV_U:
         const16 = MASK_OP_RLC_CONST16(ctx->opcode);
         tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
@@ -3792,11 +4055,729 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
         tcg_gen_movi_tl(cpu_gpr_a[r2], const16 << 16);
         break;
     case OPC1_32_RLC_MTCR:
-        gen_mtcr(env, ctx, cpu_gpr_d[r2], const16);
+        const16 = MASK_OP_RLC_CONST16(ctx->opcode);
+        gen_mtcr(env, ctx, cpu_gpr_d[r1], const16);
         break;
     }
 }
 
+/* RR format */
+static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r3, r2, r1;
+
+    r3 = MASK_OP_RR_D(ctx->opcode);
+    r2 = MASK_OP_RR_S2(ctx->opcode);
+    r1 = MASK_OP_RR_S1(ctx->opcode);
+    op2 = MASK_OP_RR_OP2(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RR_ABS:
+        gen_abs(cpu_gpr_d[r3], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABS_B:
+        gen_helper_abs_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABS_H:
+        gen_helper_abs_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABSDIF:
+        gen_absdif(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABSDIF_B:
+        gen_helper_absdif_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                            cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABSDIF_H:
+        gen_helper_absdif_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                            cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABSDIFS:
+        gen_helper_absdif_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                               cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABSDIFS_H:
+        gen_helper_absdif_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                                 cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABSS:
+        gen_helper_abs_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ABSS_H:
+        gen_helper_abs_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADD:
+        gen_add_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADD_B:
+        gen_helper_add_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADD_H:
+        gen_helper_add_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADDC:
+        gen_addc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADDS:
+        gen_adds(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADDS_H:
+        gen_helper_add_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                              cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADDS_HU:
+        gen_helper_add_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                              cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADDS_U:
+        gen_helper_add_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                            cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ADDX:
+        gen_add_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_AND_EQ:
+        gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_and_tl);
+        break;
+    case OPC2_32_RR_AND_GE:
+        gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_and_tl);
+        break;
+    case OPC2_32_RR_AND_GE_U:
+        gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_and_tl);
+        break;
+    case OPC2_32_RR_AND_LT:
+        gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_and_tl);
+        break;
+    case OPC2_32_RR_AND_LT_U:
+        gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_and_tl);
+        break;
+    case OPC2_32_RR_AND_NE:
+        gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_and_tl);
+        break;
+    case OPC2_32_RR_EQ:
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_EQ_B:
+        gen_helper_eq_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_EQ_H:
+        gen_helper_eq_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_EQ_W:
+        gen_cond_w(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_EQANY_B:
+        gen_helper_eqany_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_EQANY_H:
+        gen_helper_eqany_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_GE:
+        tcg_gen_setcond_tl(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_GE_U:
+        tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT:
+        tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT_U:
+        tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT_B:
+        gen_helper_lt_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT_BU:
+        gen_helper_lt_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT_H:
+        gen_helper_lt_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT_HU:
+        gen_helper_lt_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT_W:
+        gen_cond_w(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_LT_WU:
+        gen_cond_w(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MAX:
+        tcg_gen_movcond_tl(TCG_COND_GT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MAX_U:
+        tcg_gen_movcond_tl(TCG_COND_GTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MAX_B:
+        gen_helper_max_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MAX_BU:
+        gen_helper_max_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MAX_H:
+        gen_helper_max_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MAX_HU:
+        gen_helper_max_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MIN:
+        tcg_gen_movcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MIN_U:
+        tcg_gen_movcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MIN_B:
+        gen_helper_min_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MIN_BU:
+        gen_helper_min_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MIN_H:
+        gen_helper_min_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MIN_HU:
+        gen_helper_min_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MOV:
+        tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_NE:
+        tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                           cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_OR_EQ:
+        gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_or_tl);
+        break;
+    case OPC2_32_RR_OR_GE:
+        gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_or_tl);
+        break;
+    case OPC2_32_RR_OR_GE_U:
+        gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_or_tl);
+        break;
+    case OPC2_32_RR_OR_LT:
+        gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_or_tl);
+        break;
+    case OPC2_32_RR_OR_LT_U:
+        gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_or_tl);
+        break;
+    case OPC2_32_RR_OR_NE:
+        gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_or_tl);
+        break;
+    case OPC2_32_RR_SAT_B:
+        gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7f, -0x80);
+        break;
+    case OPC2_32_RR_SAT_BU:
+        gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xff);
+        break;
+    case OPC2_32_RR_SAT_H:
+        gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7fff, -0x8000);
+        break;
+    case OPC2_32_RR_SAT_HU:
+        gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xffff);
+        break;
+    case OPC2_32_RR_SH_EQ:
+        gen_sh_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                    cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SH_GE:
+        gen_sh_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                    cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SH_GE_U:
+        gen_sh_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                    cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SH_LT:
+        gen_sh_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                    cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SH_LT_U:
+        gen_sh_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                    cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SH_NE:
+        gen_sh_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                    cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUB:
+        gen_sub_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUB_B:
+        gen_helper_sub_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUB_H:
+        gen_helper_sub_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUBC:
+        gen_subc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUBS:
+        gen_subs(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUBS_U:
+        gen_subsu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUBS_H:
+        gen_helper_sub_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                              cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUBS_HU:
+        gen_helper_sub_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+                              cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SUBX:
+        gen_sub_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_XOR_EQ:
+        gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_xor_tl);
+        break;
+    case OPC2_32_RR_XOR_GE:
+        gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_xor_tl);
+        break;
+    case OPC2_32_RR_XOR_GE_U:
+        gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_xor_tl);
+        break;
+    case OPC2_32_RR_XOR_LT:
+        gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_xor_tl);
+        break;
+    case OPC2_32_RR_XOR_LT_U:
+        gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_xor_tl);
+        break;
+    case OPC2_32_RR_XOR_NE:
+        gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+                              cpu_gpr_d[r2], &tcg_gen_xor_tl);
+        break;
+    }
+}
+
+static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r3, r2, r1;
+    TCGv temp;
+
+    r3 = MASK_OP_RR_D(ctx->opcode);
+    r2 = MASK_OP_RR_S2(ctx->opcode);
+    r1 = MASK_OP_RR_S1(ctx->opcode);
+
+    temp = tcg_temp_new();
+    op2 = MASK_OP_RR_OP2(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RR_AND:
+        tcg_gen_and_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ANDN:
+        tcg_gen_andc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_CLO:
+        gen_helper_clo(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_CLO_H:
+        gen_helper_clo_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_CLS:
+        gen_helper_cls(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_CLS_H:
+        gen_helper_cls_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_CLZ:
+        gen_helper_clz(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_CLZ_H:
+        gen_helper_clz_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_NAND:
+        tcg_gen_nand_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_NOR:
+        tcg_gen_nor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_OR:
+        tcg_gen_or_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_ORN:
+        tcg_gen_orc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SH:
+        gen_helper_sh(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SH_H:
+        gen_helper_sh_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SHA:
+        gen_helper_sha(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SHA_H:
+        gen_helper_sha_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_SHAS:
+        gen_shas(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_XNOR:
+        tcg_gen_eqv_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_XOR:
+        tcg_gen_xor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    }
+    tcg_temp_free(temp);
+}
+
+static void decode_rr_address(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2, n;
+    int r1, r2, r3;
+    TCGv temp;
+
+    op2 = MASK_OP_RR_OP2(ctx->opcode);
+    r3 = MASK_OP_RR_D(ctx->opcode);
+    r2 = MASK_OP_RR_S2(ctx->opcode);
+    r1 = MASK_OP_RR_S1(ctx->opcode);
+    n = MASK_OP_RR_N(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RR_ADD_A:
+        tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]);
+        break;
+    case OPC2_32_RR_ADDSC_A:
+        temp = tcg_temp_new();
+        tcg_gen_shli_tl(temp, cpu_gpr_d[r1], n);
+        tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r2], temp);
+        tcg_temp_free(temp);
+        break;
+    case OPC2_32_RR_ADDSC_AT:
+        temp = tcg_temp_new();
+        tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 3);
+        tcg_gen_add_tl(temp, cpu_gpr_a[r2], temp);
+        tcg_gen_andi_tl(cpu_gpr_a[r3], temp, 0xFFFFFFFC);
+        tcg_temp_free(temp);
+        break;
+    case OPC2_32_RR_EQ_A:
+        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1],
+                           cpu_gpr_a[r2]);
+        break;
+    case OPC2_32_RR_EQZ:
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1], 0);
+        break;
+    case OPC2_32_RR_GE_A:
+        tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_a[r1],
+                           cpu_gpr_a[r2]);
+        break;
+    case OPC2_32_RR_LT_A:
+        tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_a[r1],
+                           cpu_gpr_a[r2]);
+        break;
+    case OPC2_32_RR_MOV_A:
+        tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_MOV_AA:
+        tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_a[r2]);
+        break;
+    case OPC2_32_RR_MOV_D:
+        tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_a[r2]);
+        break;
+    case OPC2_32_RR_NE_A:
+        tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1],
+                           cpu_gpr_a[r2]);
+        break;
+    case OPC2_32_RR_NEZ_A:
+        tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1], 0);
+        break;
+    case OPC2_32_RR_SUB_A:
+        tcg_gen_sub_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]);
+        break;
+    }
+}
+
+static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r1;
+
+    op2 = MASK_OP_RR_OP2(ctx->opcode);
+    r1 = MASK_OP_RR_S1(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RR_JI:
+        tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+        break;
+    case OPC2_32_RR_JLI:
+        tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
+        tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+        break;
+    case OPC2_32_RR_CALLI:
+        gen_helper_1arg(call, ctx->next_pc);
+        tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+        break;
+    }
+    tcg_gen_exit_tb(0);
+    ctx->bstate = BS_BRANCH;
+}
+
+static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r1, r2, r3;
+
+    TCGv temp, temp2;
+
+    op2 = MASK_OP_RR_OP2(ctx->opcode);
+    r3 = MASK_OP_RR_D(ctx->opcode);
+    r2 = MASK_OP_RR_S2(ctx->opcode);
+    r1 = MASK_OP_RR_S1(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RR_BMERGE:
+        gen_helper_bmerge(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_BSPLIT:
+        gen_bsplit(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_DVINIT_B:
+        gen_dvinit_b(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+                     cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_DVINIT_BU:
+        temp = tcg_temp_new();
+        temp2 = tcg_temp_new();
+        /* reset av */
+        tcg_gen_movi_tl(cpu_PSW_AV, 0);
+        if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+            /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
+            tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]);
+            /* use cpu_PSW_AV to compare against 0 */
+            tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV,
+                               temp, cpu_gpr_d[r3+1]);
+            tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]);
+            tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV,
+                               temp2, cpu_gpr_d[r2]);
+            tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2);
+        } else {
+            /* overflow = (D[b] == 0) */
+            tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+        }
+        tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+        /* sv */
+        tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+        /* write result */
+        tcg_gen_shri_tl(temp, cpu_gpr_d[r1], 8);
+        tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], 24);
+        tcg_gen_mov_tl(cpu_gpr_d[r3+1], temp);
+
+        tcg_temp_free(temp);
+        tcg_temp_free(temp2);
+        break;
+    case OPC2_32_RR_DVINIT_H:
+        gen_dvinit_h(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+                     cpu_gpr_d[r2]);
+        break;
+    case OPC2_32_RR_DVINIT_HU:
+        temp = tcg_temp_new();
+        temp2 = tcg_temp_new();
+        /* reset av */
+        tcg_gen_movi_tl(cpu_PSW_AV, 0);
+        if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+            /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
+            tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]);
+            /* use cpu_PSW_AV to compare against 0 */
+            tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV,
+                               temp, cpu_gpr_d[r3+1]);
+            tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]);
+            tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV,
+                               temp2, cpu_gpr_d[r2]);
+            tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2);
+        } else {
+            /* overflow = (D[b] == 0) */
+            tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+        }
+        tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+        /* sv */
+        tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+        /* write result */
+        tcg_gen_mov_tl(temp, cpu_gpr_d[r1]);
+        tcg_gen_shri_tl(cpu_gpr_d[r3+1], temp, 16);
+        tcg_gen_shli_tl(cpu_gpr_d[r3], temp, 16);
+        tcg_temp_free(temp);
+        tcg_temp_free(temp2);
+        break;
+    case OPC2_32_RR_DVINIT:
+        temp = tcg_temp_new();
+        temp2 = tcg_temp_new();
+        /* overflow = ((D[b] == 0) ||
+                      ((D[b] == 0xFFFFFFFF) && (D[a] == 0x80000000))) */
+        tcg_gen_setcondi_tl(TCG_COND_EQ, temp, cpu_gpr_d[r2], 0xffffffff);
+        tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r1], 0x80000000);
+        tcg_gen_and_tl(temp, temp, temp2);
+        tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r2], 0);
+        tcg_gen_or_tl(cpu_PSW_V, temp, temp2);
+        tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+        /* sv */
+        tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+        /* reset av */
+       tcg_gen_movi_tl(cpu_PSW_AV, 0);
+        /* write result */
+        tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        /* sign extend to high reg */
+        tcg_gen_sari_tl(cpu_gpr_d[r3+1], cpu_gpr_d[r1], 31);
+        tcg_temp_free(temp);
+        tcg_temp_free(temp2);
+        break;
+    case OPC2_32_RR_DVINIT_U:
+        /* overflow = (D[b] == 0) */
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+        tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+        /* sv */
+        tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+        /* reset av */
+        tcg_gen_movi_tl(cpu_PSW_AV, 0);
+        /* write result */
+        tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        /* zero extend to high reg*/
+        tcg_gen_movi_tl(cpu_gpr_d[r3+1], 0);
+        break;
+    case OPC2_32_RR_PARITY:
+        gen_helper_parity(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+        break;
+    case OPC2_32_RR_UNPACK:
+        gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
+        break;
+    }
+}
+
+/* RR1 Format */
+static void decode_rr1_mul(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+
+    int r1, r2, r3;
+    TCGv n;
+    TCGv_i64 temp64;
+
+    r1 = MASK_OP_RR1_S1(ctx->opcode);
+    r2 = MASK_OP_RR1_S2(ctx->opcode);
+    r3 = MASK_OP_RR1_D(ctx->opcode);
+    n  = tcg_const_i32(MASK_OP_RR1_N(ctx->opcode));
+    op2 = MASK_OP_RR1_OP2(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RR1_MUL_H_32_LL:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_LL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+        tcg_temp_free_i64(temp64);
+        break;
+    case OPC2_32_RR1_MUL_H_32_LU:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_LU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+        tcg_temp_free_i64(temp64);
+        break;
+    case OPC2_32_RR1_MUL_H_32_UL:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_UL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+        tcg_temp_free_i64(temp64);
+        break;
+    case OPC2_32_RR1_MUL_H_32_UU:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_UU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+        tcg_temp_free_i64(temp64);
+        break;
+    case OPC2_32_RR1_MULM_H_64_LL:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_LL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        /* reset V bit */
+        tcg_gen_movi_tl(cpu_PSW_V, 0);
+        /* reset AV bit */
+        tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+        tcg_temp_free_i64(temp64);
+        break;
+    case OPC2_32_RR1_MULM_H_64_LU:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_LU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        /* reset V bit */
+        tcg_gen_movi_tl(cpu_PSW_V, 0);
+        /* reset AV bit */
+        tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+        tcg_temp_free_i64(temp64);
+        break;
+    case OPC2_32_RR1_MULM_H_64_UL:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_UL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        /* reset V bit */
+        tcg_gen_movi_tl(cpu_PSW_V, 0);
+        /* reset AV bit */
+        tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+        tcg_temp_free_i64(temp64);
+        break;
+    case OPC2_32_RR1_MULM_H_64_UU:
+        temp64 = tcg_temp_new_i64();
+        GEN_HELPER_UU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+        /* reset V bit */
+        tcg_gen_movi_tl(cpu_PSW_V, 0);
+        /* reset AV bit */
+        tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+        tcg_temp_free_i64(temp64);
+
+        break;
+    case OPC2_32_RR1_MULR_H_16_LL:
+        GEN_HELPER_LL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+        break;
+    case OPC2_32_RR1_MULR_H_16_LU:
+        GEN_HELPER_LU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+        break;
+    case OPC2_32_RR1_MULR_H_16_UL:
+        GEN_HELPER_UL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+        break;
+    case OPC2_32_RR1_MULR_H_16_UU:
+        GEN_HELPER_UU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+        gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+        break;
+    }
+    tcg_temp_free(n);
+}
+
 static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
 {
     int op1;
@@ -3808,8 +4789,8 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
 
     op1 = MASK_OP_MAJOR(ctx->opcode);
 
-    /* handle JNZ.T opcode only being 6 bit long */
-    if (unlikely((op1 & 0x3f) == OPCM_32_BRN_JTT)) {
+    /* handle JNZ.T opcode only being 7 bit long */
+    if (unlikely((op1 & 0x7f) == OPCM_32_BRN_JTT)) {
         op1 = OPCM_32_BRN_JTT;
     }
 
@@ -3884,7 +4865,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPC1_32_B_JA:
     case OPC1_32_B_JL:
     case OPC1_32_B_JLA:
-        address = MASK_OP_B_DISP24(ctx->opcode);
+        address = MASK_OP_B_DISP24_SEXT(ctx->opcode);
         gen_compute_branch(ctx, op1, 0, 0, 0, address);
         break;
 /* Bit-format */
@@ -3930,10 +4911,16 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
         break;
 /* BOL-format */
     case OPC1_32_BOL_LD_A_LONGOFF:
-    case OPC1_32_BOL_LD_W_LONFOFF:
+    case OPC1_32_BOL_LD_W_LONGOFF:
     case OPC1_32_BOL_LEA_LONGOFF:
     case OPC1_32_BOL_ST_W_LONGOFF:
     case OPC1_32_BOL_ST_A_LONGOFF:
+    case OPC1_32_BOL_LD_B_LONGOFF:
+    case OPC1_32_BOL_LD_BU_LONGOFF:
+    case OPC1_32_BOL_LD_H_LONGOFF:
+    case OPC1_32_BOL_LD_HU_LONGOFF:
+    case OPC1_32_BOL_ST_B_LONGOFF:
+    case OPC1_32_BOL_ST_H_LONGOFF:
         decode_bol_opc(env, ctx, op1);
         break;
 /* BRC Format */
@@ -4021,12 +5008,33 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPC1_32_RLC_ADDIH_A:
     case OPC1_32_RLC_MFCR:
     case OPC1_32_RLC_MOV:
+    case OPC1_32_RLC_MOV_64:
     case OPC1_32_RLC_MOV_U:
     case OPC1_32_RLC_MOV_H:
     case OPC1_32_RLC_MOVH_A:
     case OPC1_32_RLC_MTCR:
         decode_rlc_opc(env, ctx, op1);
         break;
+/* RR Format */
+    case OPCM_32_RR_ACCUMULATOR:
+        decode_rr_accumulator(env, ctx);
+        break;
+    case OPCM_32_RR_LOGICAL_SHIFT:
+        decode_rr_logical_shift(env, ctx);
+        break;
+    case OPCM_32_RR_ADRESS:
+        decode_rr_address(env, ctx);
+        break;
+    case OPCM_32_RR_IDIRECT:
+        decode_rr_idirect(env, ctx);
+        break;
+    case OPCM_32_RR_DIVIDE:
+        decode_rr_divide(env, ctx);
+        break;
+/* RR1 Format */
+    case OPCM_32_RR1_MUL:
+        decode_rr1_mul(env, ctx);
+        break;
     }
 }
 
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 0a9122cfb9..919063e422 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -94,6 +94,8 @@
 /* B Format   */
 #define MASK_OP_B_DISP24(op)   (MASK_BITS_SHIFT(op, 16, 31) + \
                                (MASK_BITS_SHIFT(op, 8, 15) << 16))
+#define MASK_OP_B_DISP24_SEXT(op)   (MASK_BITS_SHIFT(op, 16, 31) + \
+                                    (MASK_BITS_SHIFT_SEXT(op, 8, 15) << 16))
 /* BIT Format */
 #define MASK_OP_BIT_D(op)      MASK_BITS_SHIFT(op, 28, 31)
 #define MASK_OP_BIT_POS2(op)   MASK_BITS_SHIFT(op, 23, 27)
@@ -114,7 +116,7 @@
 /* BOL Format */
 #define MASK_OP_BOL_OFF16(op)  ((MASK_BITS_SHIFT(op, 16, 21) +        \
                                (MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
-                               (MASK_BITS_SHIFT(op, 22, 27) >> 10))
+                               (MASK_BITS_SHIFT(op, 22, 27) << 10))
 #define MASK_OP_BOL_OFF16_SEXT(op)  ((MASK_BITS_SHIFT(op, 16, 21) +        \
                                     (MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
                                     (MASK_BITS_SHIFT_SEXT(op, 22, 27) << 10))
@@ -447,10 +449,16 @@ enum {
     OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR    = 0x69,
 /* BOL Format */
     OPC1_32_BOL_LD_A_LONGOFF                         = 0x99,
-    OPC1_32_BOL_LD_W_LONFOFF                         = 0x19,
+    OPC1_32_BOL_LD_W_LONGOFF                         = 0x19,
     OPC1_32_BOL_LEA_LONGOFF                          = 0xd9,
     OPC1_32_BOL_ST_W_LONGOFF                         = 0x59,
     OPC1_32_BOL_ST_A_LONGOFF                         = 0xb5, /* 1.6 only */
+    OPC1_32_BOL_LD_B_LONGOFF                         = 0x79, /* 1.6 only */
+    OPC1_32_BOL_LD_BU_LONGOFF                        = 0x39, /* 1.6 only */
+    OPC1_32_BOL_LD_H_LONGOFF                         = 0xc9, /* 1.6 only */
+    OPC1_32_BOL_LD_HU_LONGOFF                        = 0xb9, /* 1.6 only */
+    OPC1_32_BOL_ST_B_LONGOFF                         = 0xe9, /* 1.6 only */
+    OPC1_32_BOL_ST_H_LONGOFF                         = 0xf9, /* 1.6 only */
 /* BRC Format */
     OPCM_32_BRC_EQ_NEQ                               = 0xdf,
     OPCM_32_BRC_GE                                   = 0xff,
@@ -487,6 +495,7 @@ enum {
     OPC1_32_RLC_ADDIH_A                              = 0x11,
     OPC1_32_RLC_MFCR                                 = 0x4d,
     OPC1_32_RLC_MOV                                  = 0x3b,
+    OPC1_32_RLC_MOV_64                               = 0xfb, /* 1.6 only */
     OPC1_32_RLC_MOV_U                                = 0xbb,
     OPC1_32_RLC_MOV_H                                = 0x7b,
     OPC1_32_RLC_MOVH_A                               = 0x91,
@@ -495,7 +504,7 @@ enum {
     OPCM_32_RR_LOGICAL_SHIFT                         = 0x0f,
     OPCM_32_RR_ACCUMULATOR                           = 0x0b,
     OPCM_32_RR_ADRESS                                = 0x01,
-    OPCM_32_RR_FLOAT                                 = 0x4b,
+    OPCM_32_RR_DIVIDE                                = 0x4b,
     OPCM_32_RR_IDIRECT                               = 0x2d,
 /* RR1 Format */
     OPCM_32_RR1_MUL                                  = 0xb3,
@@ -1033,8 +1042,8 @@ enum {
     OPC2_32_RR_MAX_BU                            = 0x5b,
     OPC2_32_RR_MAX_H                             = 0x7a,
     OPC2_32_RR_MAX_HU                            = 0x7b,
-    OPC2_32_RR_MIN                               = 0x19,
-    OPC2_32_RR_MIN_U                             = 0x18,
+    OPC2_32_RR_MIN                               = 0x18,
+    OPC2_32_RR_MIN_U                             = 0x19,
     OPC2_32_RR_MIN_B                             = 0x58,
     OPC2_32_RR_MIN_BU                            = 0x59,
     OPC2_32_RR_MIN_H                             = 0x78,
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
index 801cba2675..13b5cfbe41 100644
--- a/ui/Makefile.objs
+++ b/ui/Makefile.objs
@@ -16,7 +16,12 @@ common-obj-$(CONFIG_CURSES) += curses.o
 common-obj-$(CONFIG_VNC) += $(vnc-obj-y)
 common-obj-$(CONFIG_GTK) += gtk.o x_keymap.o
 
-sdl.mo-objs := sdl.o sdl_zoom.o sdl2.o
+ifeq ($(CONFIG_SDLABI),1.2)
+sdl.mo-objs := sdl.o sdl_zoom.o
+endif
+ifeq ($(CONFIG_SDLABI),2.0)
+sdl.mo-objs := sdl2.o sdl2-input.o sdl2-2d.o
+endif
 sdl.mo-cflags := $(SDL_CFLAGS)
 
 gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS)
diff --git a/ui/sdl.c b/ui/sdl.c
index 94c1d9dc3a..3e9d81076b 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -26,8 +26,6 @@
 #undef WIN32_LEAN_AND_MEAN
 
 #include <SDL.h>
-
-#if SDL_MAJOR_VERSION == 1
 #include <SDL_syswm.h>
 
 #include "qemu-common.h"
@@ -958,4 +956,3 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
 
     atexit(sdl_cleanup);
 }
-#endif
diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c
new file mode 100644
index 0000000000..9264817e76
--- /dev/null
+++ b/ui/sdl2-2d.c
@@ -0,0 +1,122 @@
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */
+
+/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */
+#undef WIN32_LEAN_AND_MEAN
+
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "ui/input.h"
+#include "ui/sdl2.h"
+#include "sysemu/sysemu.h"
+
+void sdl2_2d_update(DisplayChangeListener *dcl,
+                    int x, int y, int w, int h)
+{
+    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
+    DisplaySurface *surf = qemu_console_surface(dcl->con);
+    SDL_Rect rect;
+
+    if (!surf) {
+        return;
+    }
+    if (!scon->texture) {
+        return;
+    }
+
+    rect.x = x;
+    rect.y = y;
+    rect.w = w;
+    rect.h = h;
+
+    SDL_UpdateTexture(scon->texture, NULL, surface_data(surf),
+                      surface_stride(surf));
+    SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect);
+    SDL_RenderPresent(scon->real_renderer);
+}
+
+void sdl2_2d_switch(DisplayChangeListener *dcl,
+                    DisplaySurface *new_surface)
+{
+    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
+    DisplaySurface *old_surface = scon->surface;
+    int format = 0;
+
+    scon->surface = new_surface;
+
+    if (scon->texture) {
+        SDL_DestroyTexture(scon->texture);
+        scon->texture = NULL;
+    }
+
+    if (!new_surface) {
+        sdl2_window_destroy(scon);
+        return;
+    }
+
+    if (!scon->real_window) {
+        sdl2_window_create(scon);
+    } else if (old_surface &&
+               ((surface_width(old_surface)  != surface_width(new_surface)) ||
+                (surface_height(old_surface) != surface_height(new_surface)))) {
+        sdl2_window_resize(scon);
+    }
+
+    SDL_RenderSetLogicalSize(scon->real_renderer,
+                             surface_width(new_surface),
+                             surface_height(new_surface));
+
+    if (surface_bits_per_pixel(scon->surface) == 16) {
+        format = SDL_PIXELFORMAT_RGB565;
+    } else if (surface_bits_per_pixel(scon->surface) == 32) {
+        format = SDL_PIXELFORMAT_ARGB8888;
+    }
+    scon->texture = SDL_CreateTexture(scon->real_renderer, format,
+                                      SDL_TEXTUREACCESS_STREAMING,
+                                      surface_width(new_surface),
+                                      surface_height(new_surface));
+    sdl2_2d_redraw(scon);
+}
+
+void sdl2_2d_refresh(DisplayChangeListener *dcl)
+{
+    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
+
+    graphic_hw_update(dcl->con);
+    sdl2_poll_events(scon);
+}
+
+void sdl2_2d_redraw(struct sdl2_console *scon)
+{
+    if (!scon->surface) {
+        return;
+    }
+    sdl2_2d_update(&scon->dcl, 0, 0,
+                   surface_width(scon->surface),
+                   surface_height(scon->surface));
+}
diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c
new file mode 100644
index 0000000000..a1973fc2e0
--- /dev/null
+++ b/ui/sdl2-input.c
@@ -0,0 +1,106 @@
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */
+
+/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */
+#undef WIN32_LEAN_AND_MEAN
+
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "ui/input.h"
+#include "ui/sdl2.h"
+#include "sysemu/sysemu.h"
+
+#include "sdl2-keymap.h"
+
+static uint8_t modifiers_state[SDL_NUM_SCANCODES];
+
+void sdl2_reset_keys(struct sdl2_console *scon)
+{
+    QemuConsole *con = scon ? scon->dcl.con : NULL;
+    int i;
+
+    for (i = 0; i < SDL_NUM_SCANCODES; i++) {
+        if (modifiers_state[i]) {
+            int qcode = sdl2_scancode_to_qcode[i];
+            qemu_input_event_send_key_qcode(con, qcode, false);
+            modifiers_state[i] = 0;
+        }
+    }
+}
+
+void sdl2_process_key(struct sdl2_console *scon,
+                      SDL_KeyboardEvent *ev)
+{
+    int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode];
+    QemuConsole *con = scon ? scon->dcl.con : NULL;
+
+    if (!qemu_console_is_graphic(con)) {
+        if (ev->type == SDL_KEYDOWN) {
+            switch (ev->keysym.scancode) {
+            case SDL_SCANCODE_RETURN:
+                kbd_put_keysym_console(con, '\n');
+                break;
+            case SDL_SCANCODE_BACKSPACE:
+                kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE);
+                break;
+            default:
+                kbd_put_qcode_console(con, qcode);
+                break;
+            }
+        }
+        return;
+    }
+
+    switch (ev->keysym.scancode) {
+#if 0
+    case SDL_SCANCODE_NUMLOCKCLEAR:
+    case SDL_SCANCODE_CAPSLOCK:
+        /* SDL does not send the key up event, so we generate it */
+        qemu_input_event_send_key_qcode(con, qcode, true);
+        qemu_input_event_send_key_qcode(con, qcode, false);
+        return;
+#endif
+    case SDL_SCANCODE_LCTRL:
+    case SDL_SCANCODE_LSHIFT:
+    case SDL_SCANCODE_LALT:
+    case SDL_SCANCODE_LGUI:
+    case SDL_SCANCODE_RCTRL:
+    case SDL_SCANCODE_RSHIFT:
+    case SDL_SCANCODE_RALT:
+    case SDL_SCANCODE_RGUI:
+        if (ev->type == SDL_KEYUP) {
+            modifiers_state[ev->keysym.scancode] = 0;
+        } else {
+            modifiers_state[ev->keysym.scancode] = 1;
+        }
+        /* fall though */
+    default:
+        qemu_input_event_send_key_qcode(con, qcode,
+                                        ev->type == SDL_KEYDOWN);
+    }
+}
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 1ad74baafc..1ae2781624 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -27,55 +27,37 @@
 #undef WIN32_LEAN_AND_MEAN
 
 #include <SDL.h>
-
-#if SDL_MAJOR_VERSION == 2
 #include <SDL_syswm.h>
 
 #include "qemu-common.h"
 #include "ui/console.h"
 #include "ui/input.h"
+#include "ui/sdl2.h"
 #include "sysemu/sysemu.h"
 
-#include "sdl2-keymap.h"
-
 static int sdl2_num_outputs;
-static struct sdl2_state {
-    DisplayChangeListener dcl;
-    DisplaySurface *surface;
-    SDL_Texture *texture;
-    SDL_Window *real_window;
-    SDL_Renderer *real_renderer;
-    int idx;
-    int last_vm_running; /* per console for caption reasons */
-    int x, y;
-    int hidden;
-} *sdl2_console;
+static struct sdl2_console *sdl2_console;
 
 static SDL_Surface *guest_sprite_surface;
 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
 
-static bool gui_saved_scaling;
-static int gui_saved_width;
-static int gui_saved_height;
 static int gui_saved_grab;
 static int gui_fullscreen;
 static int gui_noframe;
 static int gui_key_modifier_pressed;
 static int gui_keysym;
 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
-static uint8_t modifiers_state[SDL_NUM_SCANCODES];
 static SDL_Cursor *sdl_cursor_normal;
 static SDL_Cursor *sdl_cursor_hidden;
 static int absolute_enabled;
 static int guest_cursor;
 static int guest_x, guest_y;
 static SDL_Cursor *guest_sprite;
-static int scaling_active;
 static Notifier mouse_mode_notifier;
 
-static void sdl_update_caption(struct sdl2_state *scon);
+static void sdl_update_caption(struct sdl2_console *scon);
 
-static struct sdl2_state *get_scon_from_window(uint32_t window_id)
+static struct sdl2_console *get_scon_from_window(uint32_t window_id)
 {
     int i;
     for (i = 0; i < sdl2_num_outputs; i++) {
@@ -86,180 +68,57 @@ static struct sdl2_state *get_scon_from_window(uint32_t window_id)
     return NULL;
 }
 
-static void sdl_update(DisplayChangeListener *dcl,
-                       int x, int y, int w, int h)
+void sdl2_window_create(struct sdl2_console *scon)
 {
-    struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
-    SDL_Rect rect;
-    DisplaySurface *surf = qemu_console_surface(dcl->con);
+    int flags = 0;
 
-    if (!surf) {
+    if (!scon->surface) {
         return;
     }
-    if (!scon->texture) {
-        return;
-    }
-
-    rect.x = x;
-    rect.y = y;
-    rect.w = w;
-    rect.h = h;
-
-    SDL_UpdateTexture(scon->texture, NULL, surface_data(surf),
-                      surface_stride(surf));
-    SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect);
-    SDL_RenderPresent(scon->real_renderer);
-}
-
-static void do_sdl_resize(struct sdl2_state *scon, int width, int height,
-                          int bpp)
-{
-    int flags;
-
-    if (scon->real_window && scon->real_renderer) {
-        if (width && height) {
-            SDL_RenderSetLogicalSize(scon->real_renderer, width, height);
-            SDL_SetWindowSize(scon->real_window, width, height);
-        } else {
-            SDL_DestroyRenderer(scon->real_renderer);
-            SDL_DestroyWindow(scon->real_window);
-            scon->real_renderer = NULL;
-            scon->real_window = NULL;
-        }
-    } else {
-        if (!width || !height) {
-            return;
-        }
-        flags = 0;
-        if (gui_fullscreen) {
-            flags |= SDL_WINDOW_FULLSCREEN;
-        } else {
-            flags |= SDL_WINDOW_RESIZABLE;
-        }
-        if (scon->hidden) {
-            flags |= SDL_WINDOW_HIDDEN;
-        }
-
-        scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
-                                             SDL_WINDOWPOS_UNDEFINED,
-                                             width, height, flags);
-        scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
-        sdl_update_caption(scon);
-    }
-}
-
-static void sdl_switch(DisplayChangeListener *dcl,
-                       DisplaySurface *new_surface)
-{
-    struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
-    int format = 0;
-    int idx = scon->idx;
-    DisplaySurface *old_surface = scon->surface;
-
-    /* temporary hack: allows to call sdl_switch to handle scaling changes */
-    if (new_surface) {
-        scon->surface = new_surface;
-    }
-
-    if (!new_surface && idx > 0) {
-        scon->surface = NULL;
-    }
+    assert(!scon->real_window);
 
-    if (new_surface == NULL) {
-        do_sdl_resize(scon, 0, 0, 0);
+    if (gui_fullscreen) {
+        flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
     } else {
-        do_sdl_resize(scon, surface_width(scon->surface),
-                      surface_height(scon->surface), 0);
+        flags |= SDL_WINDOW_RESIZABLE;
     }
-
-    if (old_surface && scon->texture) {
-        SDL_DestroyTexture(scon->texture);
-        scon->texture = NULL;
+    if (scon->hidden) {
+        flags |= SDL_WINDOW_HIDDEN;
     }
 
-    if (new_surface) {
-        if (!scon->texture) {
-            if (surface_bits_per_pixel(scon->surface) == 16) {
-                format = SDL_PIXELFORMAT_RGB565;
-            } else if (surface_bits_per_pixel(scon->surface) == 32) {
-                format = SDL_PIXELFORMAT_ARGB8888;
-            }
-
-            scon->texture = SDL_CreateTexture(scon->real_renderer, format,
-                                              SDL_TEXTUREACCESS_STREAMING,
-                                              surface_width(new_surface),
-                                              surface_height(new_surface));
-        }
-    }
+    scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
+                                         SDL_WINDOWPOS_UNDEFINED,
+                                         surface_width(scon->surface),
+                                         surface_height(scon->surface),
+                                         flags);
+    scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
+    sdl_update_caption(scon);
 }
 
-static void reset_keys(struct sdl2_state *scon)
+void sdl2_window_destroy(struct sdl2_console *scon)
 {
-    QemuConsole *con = scon ? scon->dcl.con : NULL;
-    int i;
-
-    for (i = 0; i < 256; i++) {
-        if (modifiers_state[i]) {
-            int qcode = sdl2_scancode_to_qcode[i];
-            qemu_input_event_send_key_qcode(con, qcode, false);
-            modifiers_state[i] = 0;
-        }
+    if (!scon->real_window) {
+        return;
     }
+
+    SDL_DestroyRenderer(scon->real_renderer);
+    scon->real_renderer = NULL;
+    SDL_DestroyWindow(scon->real_window);
+    scon->real_window = NULL;
 }
 
-static void sdl_process_key(struct sdl2_state *scon,
-                            SDL_KeyboardEvent *ev)
+void sdl2_window_resize(struct sdl2_console *scon)
 {
-    int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode];
-    QemuConsole *con = scon ? scon->dcl.con : NULL;
-
-    if (!qemu_console_is_graphic(con)) {
-        if (ev->type == SDL_KEYDOWN) {
-            switch (ev->keysym.scancode) {
-            case SDL_SCANCODE_RETURN:
-                kbd_put_keysym_console(con, '\n');
-                break;
-            case SDL_SCANCODE_BACKSPACE:
-                kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE);
-                break;
-            default:
-                kbd_put_qcode_console(con, qcode);
-                break;
-            }
-        }
+    if (!scon->real_window) {
         return;
     }
 
-    switch (ev->keysym.scancode) {
-#if 0
-    case SDL_SCANCODE_NUMLOCKCLEAR:
-    case SDL_SCANCODE_CAPSLOCK:
-        /* SDL does not send the key up event, so we generate it */
-        qemu_input_event_send_key_qcode(con, qcode, true);
-        qemu_input_event_send_key_qcode(con, qcode, false);
-        return;
-#endif
-    case SDL_SCANCODE_LCTRL:
-    case SDL_SCANCODE_LSHIFT:
-    case SDL_SCANCODE_LALT:
-    case SDL_SCANCODE_LGUI:
-    case SDL_SCANCODE_RCTRL:
-    case SDL_SCANCODE_RSHIFT:
-    case SDL_SCANCODE_RALT:
-    case SDL_SCANCODE_RGUI:
-        if (ev->type == SDL_KEYUP) {
-            modifiers_state[ev->keysym.scancode] = 0;
-        } else {
-            modifiers_state[ev->keysym.scancode] = 1;
-        }
-        /* fall though */
-    default:
-        qemu_input_event_send_key_qcode(con, qcode,
-                                        ev->type == SDL_KEYDOWN);
-    }
+    SDL_SetWindowSize(scon->real_window,
+                      surface_width(scon->surface),
+                      surface_height(scon->surface));
 }
 
-static void sdl_update_caption(struct sdl2_state *scon)
+static void sdl_update_caption(struct sdl2_console *scon)
 {
     char win_title[1024];
     char icon_title[1024];
@@ -269,11 +128,11 @@ static void sdl_update_caption(struct sdl2_state *scon)
         status = " [Stopped]";
     } else if (gui_grab) {
         if (alt_grab) {
-            status = " - Press Ctrl-Alt-Shift to exit mouse grab";
+            status = " - Press Ctrl-Alt-Shift to exit grab";
         } else if (ctrl_grab) {
-            status = " - Press Right-Ctrl to exit mouse grab";
+            status = " - Press Right-Ctrl to exit grab";
         } else {
-            status = " - Press Ctrl-Alt to exit mouse grab";
+            status = " - Press Ctrl-Alt to exit grab";
         }
     }
 
@@ -323,7 +182,7 @@ static void sdl_show_cursor(void)
     }
 }
 
-static void sdl_grab_start(struct sdl2_state *scon)
+static void sdl_grab_start(struct sdl2_console *scon)
 {
     QemuConsole *con = scon ? scon->dcl.con : NULL;
 
@@ -351,7 +210,7 @@ static void sdl_grab_start(struct sdl2_state *scon)
     sdl_update_caption(scon);
 }
 
-static void sdl_grab_end(struct sdl2_state *scon)
+static void sdl_grab_end(struct sdl2_console *scon)
 {
     SDL_SetWindowGrab(scon->real_window, SDL_FALSE);
     gui_grab = 0;
@@ -359,7 +218,7 @@ static void sdl_grab_end(struct sdl2_state *scon)
     sdl_update_caption(scon);
 }
 
-static void absolute_mouse_grab(struct sdl2_state *scon)
+static void absolute_mouse_grab(struct sdl2_console *scon)
 {
     int mouse_x, mouse_y;
     int scr_w, scr_h;
@@ -386,7 +245,7 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data)
     }
 }
 
-static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
+static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy,
                                  int x, int y, int state)
 {
     static uint32_t bmap[INPUT_BUTTON_MAX] = {
@@ -409,7 +268,7 @@ static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
         int i;
 
         for (i = 0; i < sdl2_num_outputs; i++) {
-            struct sdl2_state *thiscon = &sdl2_console[i];
+            struct sdl2_console *thiscon = &sdl2_console[i];
             if (thiscon->real_window && thiscon->surface) {
                 SDL_GetWindowSize(thiscon->real_window, &scr_w, &scr_h);
                 cur_off_x = thiscon->x;
@@ -443,48 +302,27 @@ static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
     qemu_input_event_sync();
 }
 
-static void sdl_scale(struct sdl2_state *scon, int width, int height)
-{
-    int bpp = 0;
-    do_sdl_resize(scon, width, height, bpp);
-    scaling_active = 1;
-}
-
-static void toggle_full_screen(struct sdl2_state *scon)
+static void toggle_full_screen(struct sdl2_console *scon)
 {
-    int width = surface_width(scon->surface);
-    int height = surface_height(scon->surface);
-    int bpp = surface_bits_per_pixel(scon->surface);
-
     gui_fullscreen = !gui_fullscreen;
     if (gui_fullscreen) {
-        SDL_GetWindowSize(scon->real_window,
-                          &gui_saved_width, &gui_saved_height);
-        gui_saved_scaling = scaling_active;
-
-        do_sdl_resize(scon, width, height, bpp);
-        scaling_active = 0;
-
+        SDL_SetWindowFullscreen(scon->real_window,
+                                SDL_WINDOW_FULLSCREEN_DESKTOP);
         gui_saved_grab = gui_grab;
         sdl_grab_start(scon);
     } else {
-        if (gui_saved_scaling) {
-            sdl_scale(scon, gui_saved_width, gui_saved_height);
-        } else {
-            do_sdl_resize(scon, width, height, 0);
-        }
         if (!gui_saved_grab) {
             sdl_grab_end(scon);
         }
+        SDL_SetWindowFullscreen(scon->real_window, 0);
     }
-    graphic_hw_invalidate(scon->dcl.con);
-    graphic_hw_update(scon->dcl.con);
+    sdl2_2d_redraw(scon);
 }
 
 static void handle_keydown(SDL_Event *ev)
 {
     int mod_state, win;
-    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
 
     if (alt_grab) {
         mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
@@ -524,14 +362,13 @@ static void handle_keydown(SDL_Event *ev)
             gui_keysym = 1;
             break;
         case SDL_SCANCODE_U:
-            if (scaling_active) {
-                scaling_active = 0;
-                sdl_switch(&scon->dcl, NULL);
-                graphic_hw_invalidate(scon->dcl.con);
-                graphic_hw_update(scon->dcl.con);
-            }
+            sdl2_window_destroy(scon);
+            sdl2_window_create(scon);
+            /* re-create texture */
+            sdl2_2d_switch(&scon->dcl, scon->surface);
             gui_keysym = 1;
             break;
+#if 0
         case SDL_SCANCODE_KP_PLUS:
         case SDL_SCANCODE_KP_MINUS:
             if (!gui_fullscreen) {
@@ -544,25 +381,26 @@ static void handle_keydown(SDL_Event *ev)
                             160);
                 height = (surface_height(scon->surface) * width) /
                     surface_width(scon->surface);
-
+                fprintf(stderr, "%s: scale to %dx%d\n",
+                        __func__, width, height);
                 sdl_scale(scon, width, height);
-                graphic_hw_invalidate(NULL);
-                graphic_hw_update(NULL);
+                sdl2_2d_redraw(scon);
                 gui_keysym = 1;
             }
+#endif
         default:
             break;
         }
     }
     if (!gui_keysym) {
-        sdl_process_key(scon, &ev->key);
+        sdl2_process_key(scon, &ev->key);
     }
 }
 
 static void handle_keyup(SDL_Event *ev)
 {
     int mod_state;
-    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
 
     if (!alt_grab) {
         mod_state = (ev->key.keysym.mod & gui_grab_code);
@@ -580,19 +418,19 @@ static void handle_keyup(SDL_Event *ev)
             }
             /* SDL does not send back all the modifiers key, so we must
              * correct it. */
-            reset_keys(scon);
+            sdl2_reset_keys(scon);
             return;
         }
         gui_keysym = 0;
     }
     if (!gui_keysym) {
-        sdl_process_key(scon, &ev->key);
+        sdl2_process_key(scon, &ev->key);
     }
 }
 
 static void handle_textinput(SDL_Event *ev)
 {
-    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
     QemuConsole *con = scon ? scon->dcl.con : NULL;
 
     if (qemu_console_is_graphic(con)) {
@@ -604,7 +442,7 @@ static void handle_textinput(SDL_Event *ev)
 static void handle_mousemotion(SDL_Event *ev)
 {
     int max_x, max_y;
-    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
 
     if (qemu_input_is_absolute() || absolute_enabled) {
         int scr_w, scr_h;
@@ -631,7 +469,7 @@ static void handle_mousebutton(SDL_Event *ev)
 {
     int buttonstate = SDL_GetMouseState(NULL, NULL);
     SDL_MouseButtonEvent *bev;
-    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
 
     bev = &ev->button;
     if (!gui_grab && !qemu_input_is_absolute()) {
@@ -651,7 +489,7 @@ static void handle_mousebutton(SDL_Event *ev)
 
 static void handle_mousewheel(SDL_Event *ev)
 {
-    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
     SDL_MouseWheelEvent *wev = &ev->wheel;
     InputButton btn;
 
@@ -669,14 +507,12 @@ static void handle_mousewheel(SDL_Event *ev)
     qemu_input_event_sync();
 }
 
-static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
+static void handle_windowevent(SDL_Event *ev)
 {
-    int w, h;
-    struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
+    struct sdl2_console *scon = get_scon_from_window(ev->window.windowID);
 
     switch (ev->window.event) {
     case SDL_WINDOWEVENT_RESIZED:
-        sdl_scale(scon, ev->window.data1, ev->window.data2);
         {
             QemuUIInfo info;
             memset(&info, 0, sizeof(info));
@@ -684,12 +520,10 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
             info.height = ev->window.data2;
             dpy_set_ui_info(scon->dcl.con, &info);
         }
-        graphic_hw_invalidate(scon->dcl.con);
-        graphic_hw_update(scon->dcl.con);
+        sdl2_2d_redraw(scon);
         break;
     case SDL_WINDOWEVENT_EXPOSED:
-        SDL_GetWindowSize(SDL_GetWindowFromID(ev->window.windowID), &w, &h);
-        sdl_update(dcl, 0, 0, w, h);
+        sdl2_2d_redraw(scon);
         break;
     case SDL_WINDOWEVENT_FOCUS_GAINED:
     case SDL_WINDOWEVENT_ENTER:
@@ -703,10 +537,10 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
         }
         break;
     case SDL_WINDOWEVENT_RESTORED:
-        update_displaychangelistener(dcl, GUI_REFRESH_INTERVAL_DEFAULT);
+        update_displaychangelistener(&scon->dcl, GUI_REFRESH_INTERVAL_DEFAULT);
         break;
     case SDL_WINDOWEVENT_MINIMIZED:
-        update_displaychangelistener(dcl, 500);
+        update_displaychangelistener(&scon->dcl, 500);
         break;
     case SDL_WINDOWEVENT_CLOSE:
         if (!no_quit) {
@@ -714,12 +548,21 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
             qemu_system_shutdown_request();
         }
         break;
+    case SDL_WINDOWEVENT_SHOWN:
+        if (scon->hidden) {
+            SDL_HideWindow(scon->real_window);
+        }
+        break;
+    case SDL_WINDOWEVENT_HIDDEN:
+        if (!scon->hidden) {
+            SDL_ShowWindow(scon->real_window);
+        }
+        break;
     }
 }
 
-static void sdl_refresh(DisplayChangeListener *dcl)
+void sdl2_poll_events(struct sdl2_console *scon)
 {
-    struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
     SDL_Event ev1, *ev = &ev1;
 
     if (scon->last_vm_running != runstate_is_running()) {
@@ -727,8 +570,6 @@ static void sdl_refresh(DisplayChangeListener *dcl)
         sdl_update_caption(scon);
     }
 
-    graphic_hw_update(dcl->con);
-
     while (SDL_PollEvent(ev)) {
         switch (ev->type) {
         case SDL_KEYDOWN:
@@ -757,7 +598,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
             handle_mousewheel(ev);
             break;
         case SDL_WINDOWEVENT:
-            handle_windowevent(dcl, ev);
+            handle_windowevent(ev);
             break;
         default:
             break;
@@ -768,7 +609,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
 static void sdl_mouse_warp(DisplayChangeListener *dcl,
                            int x, int y, int on)
 {
-    struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
+    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
     if (on) {
         if (!guest_cursor) {
             sdl_show_cursor();
@@ -826,11 +667,11 @@ static void sdl_cleanup(void)
     SDL_QuitSubSystem(SDL_INIT_VIDEO);
 }
 
-static const DisplayChangeListenerOps dcl_ops = {
-    .dpy_name          = "sdl",
-    .dpy_gfx_update    = sdl_update,
-    .dpy_gfx_switch    = sdl_switch,
-    .dpy_refresh       = sdl_refresh,
+static const DisplayChangeListenerOps dcl_2d_ops = {
+    .dpy_name          = "sdl2-2d",
+    .dpy_gfx_update    = sdl2_2d_update,
+    .dpy_gfx_switch    = sdl2_2d_switch,
+    .dpy_refresh       = sdl2_2d_refresh,
     .dpy_mouse_set     = sdl_mouse_warp,
     .dpy_cursor_define = sdl_mouse_define,
 };
@@ -865,6 +706,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
                 SDL_GetError());
         exit(1);
     }
+    SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
 
     for (i = 0;; i++) {
         QemuConsole *con = qemu_console_lookup_by_index(i);
@@ -873,13 +715,13 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
         }
     }
     sdl2_num_outputs = i;
-    sdl2_console = g_new0(struct sdl2_state, sdl2_num_outputs);
+    sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs);
     for (i = 0; i < sdl2_num_outputs; i++) {
         QemuConsole *con = qemu_console_lookup_by_index(i);
         if (!qemu_console_is_graphic(con)) {
             sdl2_console[i].hidden = true;
         }
-        sdl2_console[i].dcl.ops = &dcl_ops;
+        sdl2_console[i].dcl.ops = &dcl_2d_ops;
         sdl2_console[i].dcl.con = con;
         register_displaychangelistener(&sdl2_console[i].dcl);
         sdl2_console[i].idx = i;
@@ -912,4 +754,3 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
 
     atexit(sdl_cleanup);
 }
-#endif
diff --git a/vl.c b/vl.c
index 113e98e56b..a824a7d8b4 100644
--- a/vl.c
+++ b/vl.c
@@ -196,9 +196,6 @@ NodeInfo numa_info[MAX_NODES];
 uint8_t qemu_uuid[16];
 bool qemu_uuid_set;
 
-static QEMUBootSetHandler *boot_set_handler;
-static void *boot_set_opaque;
-
 static NotifierList exit_notifiers =
     NOTIFIER_LIST_INITIALIZER(exit_notifiers);
 
@@ -1198,65 +1195,6 @@ static void default_drive(int enable, int snapshot, BlockInterfaceType type,
 
 }
 
-void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
-{
-    boot_set_handler = func;
-    boot_set_opaque = opaque;
-}
-
-int qemu_boot_set(const char *boot_order)
-{
-    if (!boot_set_handler) {
-        return -EINVAL;
-    }
-    return boot_set_handler(boot_set_opaque, boot_order);
-}
-
-static void validate_bootdevices(const char *devices)
-{
-    /* We just do some generic consistency checks */
-    const char *p;
-    int bitmap = 0;
-
-    for (p = devices; *p != '\0'; p++) {
-        /* Allowed boot devices are:
-         * a-b: floppy disk drives
-         * c-f: IDE disk drives
-         * g-m: machine implementation dependent drives
-         * n-p: network devices
-         * It's up to each machine implementation to check if the given boot
-         * devices match the actual hardware implementation and firmware
-         * features.
-         */
-        if (*p < 'a' || *p > 'p') {
-            fprintf(stderr, "Invalid boot device '%c'\n", *p);
-            exit(1);
-        }
-        if (bitmap & (1 << (*p - 'a'))) {
-            fprintf(stderr, "Boot device '%c' was given twice\n", *p);
-            exit(1);
-        }
-        bitmap |= 1 << (*p - 'a');
-    }
-}
-
-static void restore_boot_order(void *opaque)
-{
-    char *normal_boot_order = opaque;
-    static int first = 1;
-
-    /* Restore boot order and remove ourselves after the first boot */
-    if (first) {
-        first = 0;
-        return;
-    }
-
-    qemu_boot_set(normal_boot_order);
-
-    qemu_unregister_reset(restore_boot_order, normal_boot_order);
-    g_free(normal_boot_order);
-}
-
 static QemuOptsList qemu_smp_opts = {
     .name = "smp-opts",
     .implied_opt_name = "cpus",
@@ -4149,16 +4087,25 @@ int main(int argc, char **argv, char **envp)
     if (opts) {
         char *normal_boot_order;
         const char *order, *once;
+        Error *local_err = NULL;
 
         order = qemu_opt_get(opts, "order");
         if (order) {
-            validate_bootdevices(order);
+            validate_bootdevices(order, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
             boot_order = order;
         }
 
         once = qemu_opt_get(opts, "once");
         if (once) {
-            validate_bootdevices(once);
+            validate_bootdevices(once, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
             normal_boot_order = g_strdup(boot_order);
             boot_order = once;
             qemu_register_reset(restore_boot_order, normal_boot_order);