summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/e1000.c10
-rw-r--r--hw/ich9.h1
-rw-r--r--hw/lpc_ich9.c33
-rw-r--r--hw/pc_piix.c4
-rw-r--r--hw/pc_q35.c1
-rw-r--r--hw/piix_pci.c70
-rw-r--r--hw/vfio_pci.c4
-rw-r--r--hw/virtio-net.c143
-rw-r--r--hw/virtio-net.h26
-rw-r--r--rules.mak14
-rw-r--r--target-arm/cpu.c8
-rw-r--r--target-arm/helper.c11
-rw-r--r--target-arm/translate.c5
-rw-r--r--target-mips/dsp_helper.c621
-rw-r--r--target-mips/helper.h13
-rw-r--r--target-mips/op_helper.c25
-rw-r--r--target-mips/translate.c921
-rw-r--r--tests/tcg/mips/mips32-dsp/mthlip.c2
-rw-r--r--trace/Makefile.objs4
19 files changed, 947 insertions, 969 deletions
diff --git a/hw/e1000.c b/hw/e1000.c
index ef06ca1894..ee85c53d38 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -237,7 +237,17 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
         val |= E1000_ICR_INT_ASSERTED;
     }
     s->mac_reg[ICR] = val;
+
+    /*
+     * Make sure ICR and ICS registers have the same value.
+     * The spec says that the ICS register is write-only.  However in practice,
+     * on real hardware ICS is readable, and for reads it has the same value as
+     * ICR (except that ICS does not have the clear on read behaviour of ICR).
+     *
+     * The VxWorks PRO/1000 driver uses this behaviour.
+     */
     s->mac_reg[ICS] = val;
+
     qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
 }
 
diff --git a/hw/ich9.h b/hw/ich9.h
index b8d8e6d3df..d4509bb606 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -18,6 +18,7 @@
 
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
+PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin);
 void ich9_lpc_pm_init(PCIDevice *pci_lpc, qemu_irq cmos_s3);
 PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus);
 i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 16843d76bc..e25689bf87 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -158,6 +158,7 @@ static void ich9_cc_write(void *opaque, hwaddr addr,
 
     ich9_cc_addr_len(&addr, &len);
     memcpy(lpc->chip_config + addr, &val, len);
+    pci_bus_fire_intx_routing_notifier(lpc->d.bus);
     ich9_cc_update(lpc);
 }
 
@@ -286,6 +287,32 @@ int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx)
     return lpc->irr[PCI_SLOT(pci_dev->devfn)][intx];
 }
 
+PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin)
+{
+    ICH9LPCState *lpc = opaque;
+    PCIINTxRoute route;
+    int pic_irq;
+    int pic_dis;
+
+    assert(0 <= pirq_pin);
+    assert(pirq_pin < ICH9_LPC_NB_PIRQS);
+
+    route.mode = PCI_INTX_ENABLED;
+    ich9_lpc_pic_irq(lpc, pirq_pin, &pic_irq, &pic_dis);
+    if (!pic_dis) {
+        if (pic_irq < ICH9_LPC_PIC_NUM_PINS) {
+            route.irq = pic_irq;
+        } else {
+            route.mode = PCI_INTX_DISABLED;
+            route.irq = -1;
+        }
+    } else {
+        route.irq = ich9_pirq_to_gsi(pirq_pin);
+    }
+
+    return route;
+}
+
 static int ich9_lpc_sci_irq(ICH9LPCState *lpc)
 {
     switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] &
@@ -405,6 +432,12 @@ static void ich9_lpc_config_write(PCIDevice *d,
     if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) {
         ich9_lpc_rcba_update(lpc, rbca_old);
     }
+    if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) {
+        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
+    }
+    if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
+        pci_bus_fire_intx_routing_notifier(lpc->d.bus);
+    }
 }
 
 static void ich9_lpc_reset(DeviceState *qdev)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index b9a9b2efe1..ba09714d6c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -309,6 +309,10 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
             .driver   = "usb-tablet",\
             .property = "usb_version",\
             .value    = stringify(1),\
+        },{\
+            .driver   = "virtio-net-pci",\
+            .property = "ctrl_mac_addr",\
+            .value    = "off",      \
         }
 
 static QEMUMachine pc_machine_v1_3 = {
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index d82353e84f..6f5ff8dcae 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -147,6 +147,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     ich9_lpc->ioapic = gsi_state->ioapic_irq;
     pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
                  ICH9_LPC_NB_PIRQS);
+    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
     isa_bus = ich9_lpc->isa_bus;
 
     /*end early*/
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 3d79c73fda..6c77e493e4 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -31,6 +31,7 @@
 #include "qemu/range.h"
 #include "xen.h"
 #include "pam.h"
+#include "sysemu/sysemu.h"
 
 /*
  * I440FX chipset data sheet.
@@ -46,6 +47,12 @@ typedef struct I440FXState {
 #define XEN_PIIX_NUM_PIRQS      128ULL
 #define PIIX_PIRQC              0x60
 
+/*
+ * Reset Control Register: PCI-accessible ISA-Compatible Register at address
+ * 0xcf9, provided by the PCI/ISA bridge (PIIX3 PCI function 0, 8086:7000).
+ */
+#define RCR_IOPORT 0xcf9
+
 typedef struct PIIX3State {
     PCIDevice dev;
 
@@ -67,6 +74,12 @@ typedef struct PIIX3State {
 
     /* This member isn't used. Just for save/load compatibility */
     int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
+
+    /* Reset Control Register contents */
+    uint8_t rcr;
+
+    /* IO memory region for Reset Control Register (RCR_IOPORT) */
+    MemoryRegion rcr_mem;
 } PIIX3State;
 
 struct PCII440FXState {
@@ -442,6 +455,7 @@ static void piix3_reset(void *opaque)
     pci_conf[0xae] = 0x00;
 
     d->pic_levels = 0;
+    d->rcr = 0;
 }
 
 static int piix3_post_load(void *opaque, int version_id)
@@ -462,6 +476,23 @@ static void piix3_pre_save(void *opaque)
     }
 }
 
+static bool piix3_rcr_needed(void *opaque)
+{
+    PIIX3State *piix3 = opaque;
+
+    return (piix3->rcr != 0);
+}
+
+static const VMStateDescription vmstate_piix3_rcr = {
+    .name = "PIIX3/rcr",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(rcr, PIIX3State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_piix3 = {
     .name = "PIIX3",
     .version_id = 3,
@@ -469,12 +500,44 @@ static const VMStateDescription vmstate_piix3 = {
     .minimum_version_id_old = 2,
     .post_load = piix3_post_load,
     .pre_save = piix3_pre_save,
-    .fields      = (VMStateField []) {
+    .fields      = (VMStateField[]) {
         VMSTATE_PCI_DEVICE(dev, PIIX3State),
         VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
                               PIIX_NUM_PIRQS, 3),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &vmstate_piix3_rcr,
+            .needed = piix3_rcr_needed,
+        },
+        { 0 }
+    }
+};
+
+
+static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
+{
+    PIIX3State *d = opaque;
+
+    if (val & 4) {
+        qemu_system_reset_request();
+        return;
     }
+    d->rcr = val & 2; /* keep System Reset type only */
+}
+
+static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len)
+{
+    PIIX3State *d = opaque;
+
+    return d->rcr;
+}
+
+static const MemoryRegionOps rcr_ops = {
+    .read = rcr_read,
+    .write = rcr_write,
+    .endianness = DEVICE_LITTLE_ENDIAN
 };
 
 static int piix3_initfn(PCIDevice *dev)
@@ -482,6 +545,11 @@ static int piix3_initfn(PCIDevice *dev)
     PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
 
     isa_bus_new(&d->dev.qdev, pci_address_space_io(dev));
+
+    memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1);
+    memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
+                                        &d->rcr_mem, 1);
+
     qemu_register_reset(piix3_reset, d);
     return 0;
 }
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index c51ae6761b..66537b7eb5 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -1899,6 +1899,9 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
             (unsigned long)reg_info.flags);
 
     vdev->config_size = reg_info.size;
+    if (vdev->config_size == PCI_CONFIG_SPACE_SIZE) {
+        vdev->pdev.cap_present &= ~QEMU_PCI_CAP_EXPRESS;
+    }
     vdev->config_offset = reg_info.offset;
 
 error:
@@ -2121,6 +2124,7 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data)
     pdc->exit = vfio_exitfn;
     pdc->config_read = vfio_pci_read_config;
     pdc->config_write = vfio_pci_write_config;
+    pdc->is_express = 1; /* We might be */
 }
 
 static const TypeInfo vfio_pci_dev_info = {
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 3bb01b1037..dfb9687d2f 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -93,7 +93,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 
     memcpy(&netcfg, config, sizeof(netcfg));
 
-    if (memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
+    if (!(n->vdev.guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
+        memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
         memcpy(n->mac, netcfg.mac, ETH_ALEN);
         qemu_format_nic_info_str(&n->nic->nc, n->mac);
     }
@@ -199,6 +200,7 @@ static void virtio_net_reset(VirtIODevice *vdev)
     n->mac_table.multi_overflow = 0;
     n->mac_table.uni_overflow = 0;
     memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
+    memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
     memset(n->vlans, 0, MAX_VLAN >> 3);
 }
 
@@ -315,44 +317,54 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
 }
 
 static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
-                                     VirtQueueElement *elem)
+                                     struct iovec *iov, unsigned int iov_cnt)
 {
     uint8_t on;
+    size_t s;
 
-    if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(on)) {
-        error_report("virtio-net ctrl invalid rx mode command");
-        exit(1);
+    s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on));
+    if (s != sizeof(on)) {
+        return VIRTIO_NET_ERR;
     }
 
-    on = ldub_p(elem->out_sg[1].iov_base);
-
-    if (cmd == VIRTIO_NET_CTRL_RX_MODE_PROMISC)
+    if (cmd == VIRTIO_NET_CTRL_RX_PROMISC) {
         n->promisc = on;
-    else if (cmd == VIRTIO_NET_CTRL_RX_MODE_ALLMULTI)
+    } else if (cmd == VIRTIO_NET_CTRL_RX_ALLMULTI) {
         n->allmulti = on;
-    else if (cmd == VIRTIO_NET_CTRL_RX_MODE_ALLUNI)
+    } else if (cmd == VIRTIO_NET_CTRL_RX_ALLUNI) {
         n->alluni = on;
-    else if (cmd == VIRTIO_NET_CTRL_RX_MODE_NOMULTI)
+    } else if (cmd == VIRTIO_NET_CTRL_RX_NOMULTI) {
         n->nomulti = on;
-    else if (cmd == VIRTIO_NET_CTRL_RX_MODE_NOUNI)
+    } else if (cmd == VIRTIO_NET_CTRL_RX_NOUNI) {
         n->nouni = on;
-    else if (cmd == VIRTIO_NET_CTRL_RX_MODE_NOBCAST)
+    } else if (cmd == VIRTIO_NET_CTRL_RX_NOBCAST) {
         n->nobcast = on;
-    else
+    } else {
         return VIRTIO_NET_ERR;
+    }
 
     return VIRTIO_NET_OK;
 }
 
 static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
-                                 VirtQueueElement *elem)
+                                 struct iovec *iov, unsigned int iov_cnt)
 {
     struct virtio_net_ctrl_mac mac_data;
+    size_t s;
 
-    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET || elem->out_num != 3 ||
-        elem->out_sg[1].iov_len < sizeof(mac_data) ||
-        elem->out_sg[2].iov_len < sizeof(mac_data))
+    if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {
+        if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {
+            return VIRTIO_NET_ERR;
+        }
+        s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));
+        assert(s == sizeof(n->mac));
+        qemu_format_nic_info_str(&n->nic->nc, n->mac);
+        return VIRTIO_NET_OK;
+    }
+
+    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {
         return VIRTIO_NET_ERR;
+    }
 
     n->mac_table.in_use = 0;
     n->mac_table.first_multi = 0;
@@ -360,54 +372,72 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
     n->mac_table.multi_overflow = 0;
     memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
 
-    mac_data.entries = ldl_p(elem->out_sg[1].iov_base);
+    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
+                   sizeof(mac_data.entries));
+    mac_data.entries = ldl_p(&mac_data.entries);
+    if (s != sizeof(mac_data.entries)) {
+        return VIRTIO_NET_ERR;
+    }
+    iov_discard_front(&iov, &iov_cnt, s);
 
-    if (sizeof(mac_data.entries) +
-        (mac_data.entries * ETH_ALEN) > elem->out_sg[1].iov_len)
+    if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) {
         return VIRTIO_NET_ERR;
+    }
 
     if (mac_data.entries <= MAC_TABLE_ENTRIES) {
-        memcpy(n->mac_table.macs, elem->out_sg[1].iov_base + sizeof(mac_data),
-               mac_data.entries * ETH_ALEN);
+        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
+                       mac_data.entries * ETH_ALEN);
+        if (s != mac_data.entries * ETH_ALEN) {
+            return VIRTIO_NET_ERR;
+        }
         n->mac_table.in_use += mac_data.entries;
     } else {
         n->mac_table.uni_overflow = 1;
     }
 
+    iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN);
+
     n->mac_table.first_multi = n->mac_table.in_use;
 
-    mac_data.entries = ldl_p(elem->out_sg[2].iov_base);
+    s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
+                   sizeof(mac_data.entries));
+    mac_data.entries = ldl_p(&mac_data.entries);
+    if (s != sizeof(mac_data.entries)) {
+        return VIRTIO_NET_ERR;
+    }
 
-    if (sizeof(mac_data.entries) +
-        (mac_data.entries * ETH_ALEN) > elem->out_sg[2].iov_len)
+    iov_discard_front(&iov, &iov_cnt, s);
+
+    if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) {
         return VIRTIO_NET_ERR;
+    }
 
-    if (mac_data.entries) {
-        if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
-            memcpy(n->mac_table.macs + (n->mac_table.in_use * ETH_ALEN),
-                   elem->out_sg[2].iov_base + sizeof(mac_data),
-                   mac_data.entries * ETH_ALEN);
-            n->mac_table.in_use += mac_data.entries;
-        } else {
-            n->mac_table.multi_overflow = 1;
+    if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {
+        s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs,
+                       mac_data.entries * ETH_ALEN);
+        if (s != mac_data.entries * ETH_ALEN) {
+            return VIRTIO_NET_ERR;
         }
+        n->mac_table.in_use += mac_data.entries;
+    } else {
+        n->mac_table.multi_overflow = 1;
     }
 
     return VIRTIO_NET_OK;
 }
 
 static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
-                                        VirtQueueElement *elem)
+                                        struct iovec *iov, unsigned int iov_cnt)
 {
     uint16_t vid;
+    size_t s;
 
-    if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(vid)) {
-        error_report("virtio-net ctrl invalid vlan command");
+    s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid));
+    vid = lduw_p(&vid);
+    if (s != sizeof(vid)) {
         return VIRTIO_NET_ERR;
     }
 
-    vid = lduw_p(elem->out_sg[1].iov_base);
-
     if (vid >= MAX_VLAN)
         return VIRTIO_NET_ERR;
 
@@ -427,30 +457,33 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
     struct virtio_net_ctrl_hdr ctrl;
     virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
     VirtQueueElement elem;
+    size_t s;
+    struct iovec *iov;
+    unsigned int iov_cnt;
 
     while (virtqueue_pop(vq, &elem)) {
-        if ((elem.in_num < 1) || (elem.out_num < 1)) {
+        if (iov_size(elem.in_sg, elem.in_num) < sizeof(status) ||
+            iov_size(elem.out_sg, elem.out_num) < sizeof(ctrl)) {
             error_report("virtio-net ctrl missing headers");
             exit(1);
         }
 
-        if (elem.out_sg[0].iov_len < sizeof(ctrl) ||
-            elem.in_sg[elem.in_num - 1].iov_len < sizeof(status)) {
-            error_report("virtio-net ctrl header not in correct element");
-            exit(1);
+        iov = elem.out_sg;
+        iov_cnt = elem.out_num;
+        s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
+        iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
+        if (s != sizeof(ctrl)) {
+            status = VIRTIO_NET_ERR;
+        } else if (ctrl.class == VIRTIO_NET_CTRL_RX) {
+            status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, iov_cnt);
+        } else if (ctrl.class == VIRTIO_NET_CTRL_MAC) {
+            status = virtio_net_handle_mac(n, ctrl.cmd, iov, iov_cnt);
+        } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
+            status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
         }
 
-        ctrl.class = ldub_p(elem.out_sg[0].iov_base);
-        ctrl.cmd = ldub_p(elem.out_sg[0].iov_base + sizeof(ctrl.class));
-
-        if (ctrl.class == VIRTIO_NET_CTRL_RX_MODE)
-            status = virtio_net_handle_rx_mode(n, ctrl.cmd, &elem);
-        else if (ctrl.class == VIRTIO_NET_CTRL_MAC)
-            status = virtio_net_handle_mac(n, ctrl.cmd, &elem);
-        else if (ctrl.class == VIRTIO_NET_CTRL_VLAN)
-            status = virtio_net_handle_vlan_table(n, ctrl.cmd, &elem);
-
-        stb_p(elem.in_sg[elem.in_num - 1].iov_base, status);
+        s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status));
+        assert(s == sizeof(status));
 
         virtqueue_push(vq, &elem, sizeof(status));
         virtio_notify(vdev, vq);
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index d46fb9840f..c0bb284df2 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -44,6 +44,8 @@
 #define VIRTIO_NET_F_CTRL_VLAN  19      /* Control channel VLAN filtering */
 #define VIRTIO_NET_F_CTRL_RX_EXTRA 20   /* Extra RX mode control support */
 
+#define VIRTIO_NET_F_CTRL_MAC_ADDR   23 /* Set MAC address */
+
 #define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
 
 #define TX_TIMER_INTERVAL 150000 /* 150 us */
@@ -97,16 +99,16 @@ typedef uint8_t virtio_net_ctrl_ack;
  * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
  * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
  */
-#define VIRTIO_NET_CTRL_RX_MODE    0
- #define VIRTIO_NET_CTRL_RX_MODE_PROMISC      0
- #define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI     1
- #define VIRTIO_NET_CTRL_RX_MODE_ALLUNI       2
- #define VIRTIO_NET_CTRL_RX_MODE_NOMULTI      3
- #define VIRTIO_NET_CTRL_RX_MODE_NOUNI        4
- #define VIRTIO_NET_CTRL_RX_MODE_NOBCAST      5
+#define VIRTIO_NET_CTRL_RX    0
+ #define VIRTIO_NET_CTRL_RX_PROMISC      0
+ #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
+ #define VIRTIO_NET_CTRL_RX_ALLUNI       2
+ #define VIRTIO_NET_CTRL_RX_NOMULTI      3
+ #define VIRTIO_NET_CTRL_RX_NOUNI        4
+ #define VIRTIO_NET_CTRL_RX_NOBCAST      5
 
 /*
- * Control the MAC filter table.
+ * Control the MAC
  *
  * The MAC filter table is managed by the hypervisor, the guest should
  * assume the size is infinite.  Filtering should be considered
@@ -119,6 +121,10 @@ typedef uint8_t virtio_net_ctrl_ack;
  * first sg list contains unicast addresses, the second is for multicast.
  * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
  * is available.
+ *
+ * The ADDR_SET command requests one out scatterlist, it contains a
+ * 6 bytes MAC address. This functionality is present if the
+ * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
  */
 struct virtio_net_ctrl_mac {
     uint32_t entries;
@@ -126,6 +132,7 @@ struct virtio_net_ctrl_mac {
 };
 #define VIRTIO_NET_CTRL_MAC    1
  #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
+ #define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
 
 /*
  * Control VLAN filtering
@@ -158,5 +165,6 @@ struct virtio_net_ctrl_mac {
         DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \
         DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
         DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
-        DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
+        DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \
+        DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true)
 #endif
diff --git a/rules.mak b/rules.mak
index 6d82c0d5a0..edc2552f08 100644
--- a/rules.mak
+++ b/rules.mak
@@ -82,12 +82,16 @@ TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py
 
 # Generate timestamp files for .h include files
 
-%.h: %.h-timestamp
-	@test -f $@ || cp $< $@
+config-%.h: config-%.h-timestamp
+	@cmp $< $@ >/dev/null 2>&1 || cp $< $@
 
-%.h-timestamp: %.mak
-	$(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@, "  GEN   $(TARGET_DIR)$*.h")
-	@cmp $@ $*.h >/dev/null 2>&1 || cp $@ $*.h
+config-%.h-timestamp: config-%.mak
+	$(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@, "  GEN   $(TARGET_DIR)config-$*.h")
+
+.PHONY: clean-timestamp
+clean-timestamp:
+	rm -f *.timestamp
+clean: clean-timestamp
 
 # will delete the target of a rule if commands exit with a nonzero exit status
 .DELETE_ON_ERROR:
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index d1a4c82680..1c6a628df4 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -204,12 +204,15 @@ void arm_cpu_realize(ARMCPU *cpu)
 static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
 {
     ObjectClass *oc;
+    char *typename;
 
     if (!cpu_model) {
         return NULL;
     }
 
-    oc = object_class_by_name(cpu_model);
+    typename = g_strdup_printf("%s-" TYPE_ARM_CPU, cpu_model);
+    oc = object_class_by_name(typename);
+    g_free(typename);
     if (!oc || !object_class_dynamic_cast(oc, TYPE_ARM_CPU) ||
         object_class_is_abstract(oc)) {
         return NULL;
@@ -789,14 +792,15 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
 static void cpu_register(const ARMCPUInfo *info)
 {
     TypeInfo type_info = {
-        .name = info->name,
         .parent = TYPE_ARM_CPU,
         .instance_size = sizeof(ARMCPU),
         .instance_init = info->initfn,
         .class_size = sizeof(ARMCPUClass),
     };
 
+    type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
     type_register(&type_info);
+    g_free((void *)type_info.name);
 }
 
 static const TypeInfo arm_cpu_type_info = {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7a10fddf25..eb7b2910c3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1303,9 +1303,9 @@ static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
 
     name_a = object_class_get_name(class_a);
     name_b = object_class_get_name(class_b);
-    if (strcmp(name_a, "any") == 0) {
+    if (strcmp(name_a, "any-" TYPE_ARM_CPU) == 0) {
         return 1;
-    } else if (strcmp(name_b, "any") == 0) {
+    } else if (strcmp(name_b, "any-" TYPE_ARM_CPU) == 0) {
         return -1;
     } else {
         return strcmp(name_a, name_b);
@@ -1316,9 +1316,14 @@ static void arm_cpu_list_entry(gpointer data, gpointer user_data)
 {
     ObjectClass *oc = data;
     CPUListState *s = user_data;
+    const char *typename;
+    char *name;
 
+    typename = object_class_get_name(oc);
+    name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARM_CPU));
     (*s->cpu_fprintf)(s->file, "  %s\n",
-                      object_class_get_name(oc));
+                      name);
+    g_free(name);
 }
 
 void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 724e00f7cf..a8893f767f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2737,7 +2737,6 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                     }
                 } else {
                     /* arm->vfp */
-                    tmp = load_reg(s, rd);
                     if (insn & (1 << 21)) {
                         rn >>= 1;
                         /* system register */
@@ -2748,6 +2747,7 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                             /* Writes are ignored.  */
                             break;
                         case ARM_VFP_FPSCR:
+                            tmp = load_reg(s, rd);
                             gen_helper_vfp_set_fpscr(cpu_env, tmp);
                             tcg_temp_free_i32(tmp);
                             gen_lookup_tb(s);
@@ -2757,18 +2757,21 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                                 return 1;
                             /* TODO: VFP subarchitecture support.
                              * For now, keep the EN bit only */
+                            tmp = load_reg(s, rd);
                             tcg_gen_andi_i32(tmp, tmp, 1 << 30);
                             store_cpu_field(tmp, vfp.xregs[rn]);
                             gen_lookup_tb(s);
                             break;
                         case ARM_VFP_FPINST:
                         case ARM_VFP_FPINST2:
+                            tmp = load_reg(s, rd);
                             store_cpu_field(tmp, vfp.xregs[rn]);
                             break;
                         default:
                             return 1;
                         }
                     } else {
+                        tmp = load_reg(s, rd);
                         gen_vfp_msr(tmp);
                         gen_mov_vreg_F0(0, rn);
                     }
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 4870e3dbbc..96cb0447e2 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -20,6 +20,28 @@
 #include "cpu.h"
 #include "helper.h"
 
+/* As the byte ordering doesn't matter, i.e. all columns are treated
+   identically, these unions can be used directly.  */
+typedef union {
+    uint8_t  ub[4];
+    int8_t   sb[4];
+    uint16_t uh[2];
+    int16_t  sh[2];
+    uint32_t uw[1];
+    int32_t  sw[1];
+} DSP32Value;
+
+typedef union {
+    uint8_t  ub[8];
+    int8_t   sb[8];
+    uint16_t uh[4];
+    int16_t  sh[4];
+    uint32_t uw[2];
+    int32_t  sw[2];
+    uint64_t ul[1];
+    int64_t  sl[1];
+} DSP64Value;
+
 /*** MIPS DSP internal functions begin ***/
 #define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
 #define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
@@ -1056,7 +1078,6 @@ static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
         b = num & MIPSDSP_LO;               \
     } while (0)
 
-#define MIPSDSP_RETURN32(a)             ((target_long)(int32_t)a)
 #define MIPSDSP_RETURN32_8(a, b, c, d)  ((target_long)(int32_t) \
                                          (((uint32_t)a << 24) | \
                                          (((uint32_t)b << 16) | \
@@ -1089,287 +1110,169 @@ static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
 #endif
 
 /** DSP Arithmetic Sub-class insns **/
-#define ARITH_PH(name, func)                                      \
-target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt) \
-{                                                                 \
-    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
-                                                                  \
-    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
-    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
-                                                                  \
-    temph = mipsdsp_##func(rsh, rth);                             \
-    templ = mipsdsp_##func(rsl, rtl);                             \
-                                                                  \
-    return MIPSDSP_RETURN32_16(temph, templ);                     \
-}
-
-#define ARITH_PH_ENV(name, func)                                  \
-target_ulong helper_##name##_ph(target_ulong rs, target_ulong rt, \
-                                CPUMIPSState *env)                \
-{                                                                 \
-    uint16_t  rsh, rsl, rth, rtl, temph, templ;                   \
-                                                                  \
-    MIPSDSP_SPLIT32_16(rs, rsh, rsl);                             \
-    MIPSDSP_SPLIT32_16(rt, rth, rtl);                             \
-                                                                  \
-    temph = mipsdsp_##func(rsh, rth, env);                        \
-    templ = mipsdsp_##func(rsl, rtl, env);                        \
-                                                                  \
-    return MIPSDSP_RETURN32_16(temph, templ);                     \
-}
-
-
-ARITH_PH_ENV(addq, add_i16);
-ARITH_PH_ENV(addq_s, sat_add_i16);
-ARITH_PH_ENV(addu, add_u16);
-ARITH_PH_ENV(addu_s, sat_add_u16);
-
-ARITH_PH(addqh, rshift1_add_q16);
-ARITH_PH(addqh_r, rrshift1_add_q16);
-
-ARITH_PH_ENV(subq, sub_i16);
-ARITH_PH_ENV(subq_s, sat16_sub);
-ARITH_PH_ENV(subu, sub_u16_u16);
-ARITH_PH_ENV(subu_s, satu16_sub_u16_u16);
-
-ARITH_PH(subqh, rshift1_sub_q16);
-ARITH_PH(subqh_r, rrshift1_sub_q16);
-
-#undef ARITH_PH
-#undef ARITH_PH_ENV
-
-#ifdef TARGET_MIPS64
-#define ARITH_QH_ENV(name, func) \
-target_ulong helper_##name##_qh(target_ulong rs, target_ulong rt, \
-                                CPUMIPSState *env)           \
-{                                                            \
-    uint16_t rs3, rs2, rs1, rs0;                             \
-    uint16_t rt3, rt2, rt1, rt0;                             \
-    uint16_t tempD, tempC, tempB, tempA;                     \
-                                                             \
-    MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);              \
-    MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);              \
-                                                             \
-    tempD = mipsdsp_##func(rs3, rt3, env);                   \
-    tempC = mipsdsp_##func(rs2, rt2, env);                   \
-    tempB = mipsdsp_##func(rs1, rt1, env);                   \
-    tempA = mipsdsp_##func(rs0, rt0, env);                   \
-                                                             \
-    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);  \
-}
-
-ARITH_QH_ENV(addq, add_i16);
-ARITH_QH_ENV(addq_s, sat_add_i16);
-ARITH_QH_ENV(addu, add_u16);
-ARITH_QH_ENV(addu_s, sat_add_u16);
-
-ARITH_QH_ENV(subq, sub_i16);
-ARITH_QH_ENV(subq_s, sat16_sub);
-ARITH_QH_ENV(subu, sub_u16_u16);
-ARITH_QH_ENV(subu_s, satu16_sub_u16_u16);
-
-#undef ARITH_QH_ENV
-
-#endif
-
-#define ARITH_W(name, func) \
-target_ulong helper_##name##_w(target_ulong rs, target_ulong rt) \
-{                                                                \
-    uint32_t rd;                                                 \
-    rd = mipsdsp_##func(rs, rt);                                 \
-    return MIPSDSP_RETURN32(rd);                                 \
-}
-
-#define ARITH_W_ENV(name, func) \
-target_ulong helper_##name##_w(target_ulong rs, target_ulong rt, \
-                               CPUMIPSState *env)                \
-{                                                                \
-    uint32_t rd;                                                 \
-    rd = mipsdsp_##func(rs, rt, env);                            \
-    return MIPSDSP_RETURN32(rd);                                 \
-}
-
-ARITH_W_ENV(addq_s, sat_add_i32);
-
-ARITH_W(addqh, rshift1_add_q32);
-ARITH_W(addqh_r, rrshift1_add_q32);
-
-ARITH_W_ENV(subq_s, sat32_sub);
-
-ARITH_W(subqh, rshift1_sub_q32);
-ARITH_W(subqh_r, rrshift1_sub_q32);
-
-#undef ARITH_W
-#undef ARITH_W_ENV
-
-target_ulong helper_absq_s_w(target_ulong rt, CPUMIPSState *env)
-{
-    uint32_t rd;
-
-    rd = mipsdsp_sat_abs32(rt, env);
-
-    return (target_ulong)rd;
-}
-
+#define MIPSDSP32_UNOP_ENV(name, func, element)                            \
+target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
+{                                                                          \
+    DSP32Value dt;                                                         \
+    unsigned int i, n;                                                     \
+                                                                           \
+    n = sizeof(DSP32Value) / sizeof(dt.element[0]);                        \
+    dt.sw[0] = rt;                                                         \
+                                                                           \
+    for (i = 0; i < n; i++) {                                              \
+        dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
+    }                                                                      \
+                                                                           \
+    return (target_long)dt.sw[0];                                          \
+}
+MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh)
+MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb)
+MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw)
+#undef MIPSDSP32_UNOP_ENV
 
 #if defined(TARGET_MIPS64)
-
-#define ARITH_PW_ENV(name, func) \
-target_ulong helper_##name##_pw(target_ulong rs, target_ulong rt, \
-                                CPUMIPSState *env)                \
-{                                                                 \
-    uint32_t rs1, rs0;                                            \
-    uint32_t rt1, rt0;                                            \
-    uint32_t tempB, tempA;                                        \
-                                                                  \
-    MIPSDSP_SPLIT64_32(rs, rs1, rs0);                             \
-    MIPSDSP_SPLIT64_32(rt, rt1, rt0);                             \
-                                                                  \
-    tempB = mipsdsp_##func(rs1, rt1, env);                        \
-    tempA = mipsdsp_##func(rs0, rt0, env);                        \
-                                                                  \
-    return MIPSDSP_RETURN64_32(tempB, tempA);                     \
-}
-
-ARITH_PW_ENV(addq, add_i32);
-ARITH_PW_ENV(addq_s, sat_add_i32);
-ARITH_PW_ENV(subq, sub32);
-ARITH_PW_ENV(subq_s, sat32_sub);
-
-#undef ARITH_PW_ENV
-
+#define MIPSDSP64_UNOP_ENV(name, func, element)                            \
+target_ulong helper_##name(target_ulong rt, CPUMIPSState *env)             \
+{                                                                          \
+    DSP64Value dt;                                                         \
+    unsigned int i, n;                                                     \
+                                                                           \
+    n = sizeof(DSP64Value) / sizeof(dt.element[0]);                        \
+    dt.sl[0] = rt;                                                         \
+                                                                           \
+    for (i = 0; i < n; i++) {                                              \
+        dt.element[i] = mipsdsp_##func(dt.element[i], env);                \
+    }                                                                      \
+                                                                           \
+    return dt.sl[0];                                                       \
+}
+MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb)
+MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh)
+MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw)
+#undef MIPSDSP64_UNOP_ENV
 #endif
 
-#define ARITH_QB(name, func) \
-target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
-{                                                                 \
-    uint8_t  rs0, rs1, rs2, rs3;                                  \
-    uint8_t  rt0, rt1, rt2, rt3;                                  \
-    uint8_t  temp0, temp1, temp2, temp3;                          \
-                                                                  \
-    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                    \
-    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                    \
-                                                                  \
-    temp0 = mipsdsp_##func(rs0, rt0);                             \
-    temp1 = mipsdsp_##func(rs1, rt1);                             \
-    temp2 = mipsdsp_##func(rs2, rt2);                             \
-    temp3 = mipsdsp_##func(rs3, rt3);                             \
-                                                                  \
-    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);        \
-}
+#define MIPSDSP32_BINOP(name, func, element)                               \
+target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
+{                                                                          \
+    DSP32Value ds, dt;                                                     \
+    unsigned int i, n;                                                     \
+                                                                           \
+    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
+    ds.sw[0] = rs;                                                         \
+    dt.sw[0] = rt;                                                         \
+                                                                           \
+    for (i = 0; i < n; i++) {                                              \
+        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
+    }                                                                      \
+                                                                           \
+    return (target_long)ds.sw[0];                                          \
+}
+MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh);
+MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh);
+MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw);
+MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw);
+MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub);
+MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub);
+MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh);
+MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh);
+MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw);
+MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw);
+#undef MIPSDSP32_BINOP
+
+#define MIPSDSP32_BINOP_ENV(name, func, element)                           \
+target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
+                           CPUMIPSState *env)                              \
+{                                                                          \
+    DSP32Value ds, dt;                                                     \
+    unsigned int i, n;                                                     \
+                                                                           \
+    n = sizeof(DSP32Value) / sizeof(ds.element[0]);                        \
+    ds.sw[0] = rs;                                                         \
+    dt.sw[0] = rt;                                                         \
+                                                                           \
+    for (i = 0 ; i < n ; i++) {                                            \
+        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
+    }                                                                      \
+                                                                           \
+    return (target_long)ds.sw[0];                                          \
+}
+MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh)
+MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh)
+MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw);
+MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh)
+MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub);
+MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh)
+MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub);
+MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh);
+MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh);
+MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw);
+MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh);
+MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub);
+MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh);
+MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub);
+#undef MIPSDSP32_BINOP_ENV
 
-#define ARITH_QB_ENV(name, func) \
-target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt, \
-                                CPUMIPSState *env)          \
-{                                                           \
-    uint8_t  rs0, rs1, rs2, rs3;                            \
-    uint8_t  rt0, rt1, rt2, rt3;                            \
-    uint8_t  temp0, temp1, temp2, temp3;                    \
-                                                            \
-    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);              \
-    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);              \
-                                                            \
-    temp0 = mipsdsp_##func(rs0, rt0, env);                  \
-    temp1 = mipsdsp_##func(rs1, rt1, env);                  \
-    temp2 = mipsdsp_##func(rs2, rt2, env);                  \
-    temp3 = mipsdsp_##func(rs3, rt3, env);                  \
-                                                            \
-    return MIPSDSP_RETURN32_8(temp3, temp2, temp1, temp0);  \
-}
-
-ARITH_QB(adduh, rshift1_add_u8);
-ARITH_QB(adduh_r, rrshift1_add_u8);
-
-ARITH_QB_ENV(addu, add_u8);
-ARITH_QB_ENV(addu_s, sat_add_u8);
-
-#undef ADDU_QB
-#undef ADDU_QB_ENV
-
-#if defined(TARGET_MIPS64)
-#define ARITH_OB(name, func) \
-target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt) \
-{                                                                 \
-    int i;                                                        \
-    uint8_t rs_t[8], rt_t[8];                                     \
-    uint8_t temp[8];                                              \
-    uint64_t result;                                              \
-                                                                  \
-    result = 0;                                                   \
-                                                                  \
-    for (i = 0; i < 8; i++) {                                     \
-        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;                   \
-        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                   \
-        temp[i] = mipsdsp_##func(rs_t[i], rt_t[i]);               \
-        result |= (uint64_t)temp[i] << (8 * i);                   \
-    }                                                             \
-                                                                  \
-    return result;                                                \
-}
-
-#define ARITH_OB_ENV(name, func) \
-target_ulong helper_##name##_ob(target_ulong rs, target_ulong rt, \
-                                CPUMIPSState *env)                \
-{                                                                 \
-    int i;                                                        \
-    uint8_t rs_t[8], rt_t[8];                                     \
-    uint8_t temp[8];                                              \
-    uint64_t result;                                              \
-                                                                  \
-    result = 0;                                                   \
-                                                                  \
-    for (i = 0; i < 8; i++) {                                     \
-        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;                   \
-        rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0;                   \
-        temp[i] = mipsdsp_##func(rs_t[i], rt_t[i], env);          \
-        result |= (uint64_t)temp[i] << (8 * i);                   \
-    }                                                             \
-                                                                  \
-    return result;                                                \
-}
-
-ARITH_OB_ENV(addu, add_u8);
-ARITH_OB_ENV(addu_s, sat_add_u8);
-
-ARITH_OB(adduh, rshift1_add_u8);
-ARITH_OB(adduh_r, rrshift1_add_u8);
-
-ARITH_OB_ENV(subu, sub_u8);
-ARITH_OB_ENV(subu_s, satu8_sub);
-
-ARITH_OB(subuh, rshift1_sub_u8);
-ARITH_OB(subuh_r, rrshift1_sub_u8);
-
-#undef ARITH_OB
-#undef ARITH_OB_ENV
+#ifdef TARGET_MIPS64
+#define MIPSDSP64_BINOP(name, func, element)                               \
+target_ulong helper_##name(target_ulong rs, target_ulong rt)               \
+{                                                                          \
+    DSP64Value ds, dt;                                                     \
+    unsigned int i, n;                                                     \
+                                                                           \
+    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
+    ds.sl[0] = rs;                                                         \
+    dt.sl[0] = rt;                                                         \
+                                                                           \
+    for (i = 0 ; i < n ; i++) {                                            \
+        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]);      \
+    }                                                                      \
+                                                                           \
+    return ds.sl[0];                                                       \
+}
+MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub);
+MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub);
+MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub);
+MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub);
+#undef MIPSDSP64_BINOP
+
+#define MIPSDSP64_BINOP_ENV(name, func, element)                           \
+target_ulong helper_##name(target_ulong rs, target_ulong rt,               \
+                           CPUMIPSState *env)                              \
+{                                                                          \
+    DSP64Value ds, dt;                                                     \
+    unsigned int i, n;                                                     \
+                                                                           \
+    n = sizeof(DSP64Value) / sizeof(ds.element[0]);                        \
+    ds.sl[0] = rs;                                                         \
+    dt.sl[0] = rt;                                                         \
+                                                                           \
+    for (i = 0 ; i < n ; i++) {                                            \
+        ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
+    }                                                                      \
+                                                                           \
+    return ds.sl[0];                                                       \
+}
+MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw);
+MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh);
+MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw);
+MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh);
+MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh);
+MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh);
+MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh);
+MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh);
+MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw);
+MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh);
+MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw);
+MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh);
+MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh);
+MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh);
+MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh);
+MIPSDSP64_BINOP_ENV(subu_s_qh, satu16_sub_u16_u16, uh);
+#undef MIPSDSP64_BINOP_ENV
 
 #endif
 
-#define SUBU_QB(name, func) \
-target_ulong helper_##name##_qb(target_ulong rs,               \
-                                target_ulong rt,               \
-                                CPUMIPSState *env)             \
-{                                                              \
-    uint8_t rs3, rs2, rs1, rs0;                                \
-    uint8_t rt3, rt2, rt1, rt0;                                \
-    uint8_t tempD, tempC, tempB, tempA;                        \
-                                                               \
-    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);                 \
-    MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0);                 \
-                                                               \
-    tempD = mipsdsp_##func(rs3, rt3, env);                     \
-    tempC = mipsdsp_##func(rs2, rt2, env);                     \
-    tempB = mipsdsp_##func(rs1, rt1, env);                     \
-    tempA = mipsdsp_##func(rs0, rt0, env);                     \
-                                                               \
-    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);     \
-}
-
-SUBU_QB(subu, sub_u8);
-SUBU_QB(subu_s, satu8_sub);
-
-#undef SUBU_QB
-
 #define SUBUH_QB(name, var) \
 target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
 {                                                                 \
@@ -1449,103 +1352,29 @@ target_ulong helper_modsub(target_ulong rs, target_ulong rt)
 
 target_ulong helper_raddu_w_qb(target_ulong rs)
 {
-    uint8_t  rs3, rs2, rs1, rs0;
-    uint16_t temp;
+    target_ulong ret = 0;
+    DSP32Value ds;
+    unsigned int i;
 
-    MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0);
-
-    temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
-
-    return (target_ulong)temp;
-}
-
-#if defined(TARGET_MIPS64)
-target_ulong helper_raddu_l_ob(target_ulong rs)
-{
-    int i;
-    uint16_t rs_t[8];
-    uint64_t temp;
-
-    temp = 0;
-
-    for (i = 0; i < 8; i++) {
-        rs_t[i] = (rs >> (8 * i)) & MIPSDSP_Q0;
-        temp += (uint64_t)rs_t[i];
+    ds.uw[0] = rs;
+    for (i = 0; i < 4; i++) {
+        ret += ds.ub[i];
     }
-
-    return temp;
-}
-#endif
-
-target_ulong helper_absq_s_qb(target_ulong rt, CPUMIPSState *env)
-{
-    uint8_t tempD, tempC, tempB, tempA;
-
-    MIPSDSP_SPLIT32_8(rt, tempD, tempC, tempB, tempA);
-
-    tempD = mipsdsp_sat_abs8(tempD, env);
-    tempC = mipsdsp_sat_abs8(tempC, env);
-    tempB = mipsdsp_sat_abs8(tempB, env);
-    tempA = mipsdsp_sat_abs8(tempA, env);
-
-    return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
-}
-
-target_ulong helper_absq_s_ph(target_ulong rt, CPUMIPSState *env)
-{
-    uint16_t tempB, tempA;
-
-    MIPSDSP_SPLIT32_16(rt, tempB, tempA);
-
-    tempB = mipsdsp_sat_abs16 (tempB, env);
-    tempA = mipsdsp_sat_abs16 (tempA, env);
-
-    return MIPSDSP_RETURN32_16(tempB, tempA);
+    return ret;
 }
 
 #if defined(TARGET_MIPS64)
-target_ulong helper_absq_s_ob(target_ulong rt, CPUMIPSState *env)
+target_ulong helper_raddu_l_ob(target_ulong rs)
 {
-    int i;
-    int8_t temp[8];
-    uint64_t result;
+    target_ulong ret = 0;
+    DSP64Value ds;
+    unsigned int i;
 
+    ds.ul[0] = rs;
     for (i = 0; i < 8; i++) {
-        temp[i] = (rt >> (8 * i)) & MIPSDSP_Q0;
-        temp[i] = mipsdsp_sat_abs8(temp[i], env);
+        ret += ds.ub[i];
     }
-
-    for (i = 0; i < 8; i++) {
-        result = (uint64_t)(uint8_t)temp[i] << (8 * i);
-    }
-
-    return result;
-}
-
-target_ulong helper_absq_s_qh(target_ulong rt, CPUMIPSState *env)
-{
-    int16_t tempD, tempC, tempB, tempA;
-
-    MIPSDSP_SPLIT64_16(rt, tempD, tempC, tempB, tempA);
-
-    tempD = mipsdsp_sat_abs16(tempD, env);
-    tempC = mipsdsp_sat_abs16(tempC, env);
-    tempB = mipsdsp_sat_abs16(tempB, env);
-    tempA = mipsdsp_sat_abs16(tempA, env);
-
-    return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
-}
-
-target_ulong helper_absq_s_pw(target_ulong rt, CPUMIPSState *env)
-{
-    int32_t tempB, tempA;
-
-    MIPSDSP_SPLIT64_32(rt, tempB, tempA);
-
-    tempB = mipsdsp_sat_abs32(tempB, env);
-    tempA = mipsdsp_sat_abs32(tempA, env);
-
-    return MIPSDSP_RETURN64_32(tempB, tempA);
+    return ret;
 }
 #endif
 
@@ -3282,73 +3111,6 @@ PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
 #endif
 #undef PICK_INSN
 
-#define APPEND_INSN(name, ret_32) \
-target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \
-{                                                                         \
-    target_ulong temp;                                                    \
-                                                                          \
-    if (ret_32) {                                                         \
-        temp = ((rt & MIPSDSP_LLO) << sa) |                               \
-               ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1));                 \
-        temp = (target_long)(int32_t)(temp & MIPSDSP_LLO);                \
-    } else {                                                              \
-        temp = (rt << sa) | (rs & ((0x01 << sa) - 1));                    \
-    }                                                                     \
-                                                                          \
-    return temp;                                                          \
-}
-
-APPEND_INSN(append, 1);
-#ifdef TARGET_MIPS64
-APPEND_INSN(dappend, 0);
-#endif
-#undef APPEND_INSN
-
-#define PREPEND_INSN(name, or_val, ret_32)                    \
-target_ulong helper_##name(target_ulong rs, target_ulong rt,  \
-                           uint32_t sa)                       \
-{                                                             \
-    sa |= or_val;                                             \
-                                                              \
-    if (1) {                                                  \
-        return (target_long)(int32_t)(uint32_t)               \
-            (((rs & MIPSDSP_LLO) << (32 - sa)) |              \
-             ((rt & MIPSDSP_LLO) >> sa));                     \
-    } else {                                                  \
-        return (rs << (64 - sa)) | (rt >> sa);                \
-    }                                                         \
-}
-
-PREPEND_INSN(prepend, 0, 1);
-#ifdef TARGET_MIPS64
-PREPEND_INSN(prependw, 0, 0);
-PREPEND_INSN(prependd, 0x20, 0);
-#endif
-#undef PREPEND_INSN
-
-#define BALIGN_INSN(name, filter, ret32) \
-target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \
-{                                                                         \
-    bp = bp & 0x03;                                                       \
-                                                                          \
-    if ((bp & 1) == 0) {                                                  \
-        return rt;                                                        \
-    } else {                                                              \
-        if (ret32) {                                                      \
-            return (target_long)(int32_t)((rt << (8 * bp)) |              \
-                                          (rs >> (8 * (4 - bp))));        \
-        } else {                                                          \
-            return (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));             \
-        }                                                                 \
-    }                                                                     \
-}
-
-BALIGN_INSN(balign, 0x03, 1);
-#if defined(TARGET_MIPS64)
-BALIGN_INSN(dbalign, 0x07, 0);
-#endif
-#undef BALIGN_INSN
-
 target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
 {
     uint32_t rsl, rth;
@@ -4005,7 +3767,6 @@ target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
 #undef MIPSDSP_SPLIT32_8
 #undef MIPSDSP_SPLIT32_16
 
-#undef MIPSDSP_RETURN32
 #undef MIPSDSP_RETURN32_8
 #undef MIPSDSP_RETURN32_16
 
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 9ea60ec1bb..cd48738ff9 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -654,19 +654,6 @@ DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env)
 DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env)
 DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env)
 #endif
-DEF_HELPER_FLAGS_3(append, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
-#if defined(TARGET_MIPS64)
-DEF_HELPER_FLAGS_3(dappend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
-#endif
-DEF_HELPER_FLAGS_3(prepend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
-#if defined(TARGET_MIPS64)
-DEF_HELPER_FLAGS_3(prependd, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
-DEF_HELPER_FLAGS_3(prependw, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
-#endif
-DEF_HELPER_FLAGS_3(balign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
-#if defined(TARGET_MIPS64)
-DEF_HELPER_FLAGS_3(dbalign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
-#endif
 DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 #if defined(TARGET_MIPS64)
 DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 1bca4a159e..526f84f136 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2878,14 +2878,26 @@ FLOAT_BINOP(mul)
 FLOAT_BINOP(div)
 #undef FLOAT_BINOP
 
+#define UNFUSED_FMA(prefix, a, b, c, flags)                          \
+{                                                                    \
+    a = prefix##_mul(a, b, &env->active_fpu.fp_status);              \
+    if ((flags) & float_muladd_negate_c) {                           \
+        a = prefix##_sub(a, c, &env->active_fpu.fp_status);          \
+    } else {                                                         \
+        a = prefix##_add(a, c, &env->active_fpu.fp_status);          \
+    }                                                                \
+    if ((flags) & float_muladd_negate_result) {                      \
+        a = prefix##_chs(a);                                         \
+    }                                                                \
+}
+
 /* FMA based operations */
 #define FLOAT_FMA(name, type)                                        \
 uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,              \
                                      uint64_t fdt0, uint64_t fdt1,   \
                                      uint64_t fdt2)                  \
 {                                                                    \
-    fdt0 = float64_muladd(fdt0, fdt1, fdt2, type,                    \
-                         &env->active_fpu.fp_status);                \
+    UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type);                    \
     update_fcr31(env, GETPC());                                      \
     return fdt0;                                                     \
 }                                                                    \
@@ -2894,8 +2906,7 @@ uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,              \
                                      uint32_t fst0, uint32_t fst1,   \
                                      uint32_t fst2)                  \
 {                                                                    \
-    fst0 = float32_muladd(fst0, fst1, fst2, type,                    \
-                         &env->active_fpu.fp_status);                \
+    UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
     update_fcr31(env, GETPC());                                      \
     return fst0;                                                     \
 }                                                                    \
@@ -2911,10 +2922,8 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,             \
     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                               \
     uint32_t fsth2 = fdt2 >> 32;                                     \
                                                                      \
-    fst0 = float32_muladd(fst0, fst1, fst2, type,                    \
-                          &env->active_fpu.fp_status);               \
-    fsth0 = float32_muladd(fsth0, fsth1, fsth2, type,                \
-                           &env->active_fpu.fp_status);              \
+    UNFUSED_FMA(float32, fst0, fst1, fst2, type);                    \
+    UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type);                 \
     update_fcr31(env, GETPC());                                      \
     return ((uint64_t)fsth0 << 32) | fst0;                           \
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 206ba83401..3b77b53b93 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -336,7 +336,7 @@ enum {
     /* DSP Bit/Manipulation Sub-class */
     OPC_INSV_DSP       = 0x0C | OPC_SPECIAL3,
     OPC_DINSV_DSP      = 0x0D | OPC_SPECIAL3,
-    /* MIPS DSP Compare-Pick Sub-class */
+    /* MIPS DSP Append Sub-class */
     OPC_APPEND_DSP     = 0x31 | OPC_SPECIAL3,
     OPC_DAPPEND_DSP    = 0x35 | OPC_SPECIAL3,
     /* MIPS DSP Accumulator and DSPControl Access Sub-class */
@@ -543,7 +543,7 @@ enum {
 
 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
-    /* MIPS DSP Compare-Pick Sub-class */
+    /* MIPS DSP Append Sub-class */
     OPC_APPEND  = (0x00 << 6) | OPC_APPEND_DSP,
     OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
     OPC_BALIGN  = (0x10 << 6) | OPC_APPEND_DSP,
@@ -667,7 +667,7 @@ enum {
 
 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 enum {
-    /* DSP Compare-Pick Sub-class */
+    /* DSP Append Sub-class */
     OPC_DAPPEND  = (0x00 << 6) | OPC_DAPPEND_DSP,
     OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
     OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
@@ -1066,6 +1066,7 @@ typedef struct DisasContext {
     target_ulong pc, saved_pc;
     uint32_t opcode;
     int singlestep_enabled;
+    int insn_flags;
     /* Routine used to access memory */
     int mem_idx;
     uint32_t hflags, saved_hflags;
@@ -1393,23 +1394,32 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
 static inline void check_dsp(DisasContext *ctx)
 {
     if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
-        generate_exception(ctx, EXCP_DSPDIS);
+        if (ctx->insn_flags & ASE_DSP) {
+            generate_exception(ctx, EXCP_DSPDIS);
+        } else {
+            generate_exception(ctx, EXCP_RI);
+        }
     }
 }
 
 static inline void check_dspr2(DisasContext *ctx)
 {
     if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
-        generate_exception(ctx, EXCP_DSPDIS);
+        if (ctx->insn_flags & ASE_DSP) {
+            generate_exception(ctx, EXCP_DSPDIS);
+        } else {
+            generate_exception(ctx, EXCP_RI);
+        }
     }
 }
 
 /* This code generates a "reserved instruction" exception if the
    CPU does not support the instruction set corresponding to flags. */
-static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
+static inline void check_insn(DisasContext *ctx, int flags)
 {
-    if (unlikely(!(env->insn_flags & flags)))
+    if (unlikely(!(ctx->insn_flags & flags))) {
         generate_exception(ctx, EXCP_RI);
+    }
 }
 
 /* This code generates a "reserved instruction" exception if 64-bit
@@ -1576,13 +1586,13 @@ static target_ulong pc_relative_pc (DisasContext *ctx)
 }
 
 /* Load */
-static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
-                    int rt, int base, int16_t offset)
+static void gen_ld(DisasContext *ctx, uint32_t opc,
+                   int rt, int base, int16_t offset)
 {
     const char *opn = "ld";
     TCGv t0, t1, t2;
 
-    if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
+    if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
         /* Loongson CPU uses a load to zero register for prefetch.
            We emulate it as a NOP. On other CPU we must perform the
            actual memory access. */
@@ -1735,6 +1745,7 @@ static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
         tcg_temp_free(t2);
         tcg_gen_or_tl(t0, t0, t1);
         tcg_temp_free(t1);
+        tcg_gen_ext32s_tl(t0, t0);
         gen_store_gpr(t0, rt);
         opn = "lwr";
         break;
@@ -1921,8 +1932,8 @@ static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
 }
 
 /* Arithmetic with immediate operand */
-static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
-                           int rt, int rs, int16_t imm)
+static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
+                          int rt, int rs, int16_t imm)
 {
     target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
     const char *opn = "imm arith";
@@ -2009,7 +2020,7 @@ static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Logic with immediate operand */
-static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
 {
     target_ulong uimm;
@@ -2057,7 +2068,7 @@ static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Set on less than with immediate operand */
-static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
                         int rt, int rs, int16_t imm)
 {
     target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
@@ -2087,7 +2098,7 @@ static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Shifts with immediate operand */
-static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
                           int rt, int rs, int16_t imm)
 {
     target_ulong uimm = ((uint16_t)imm) & 0x1f;
@@ -2179,8 +2190,8 @@ static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Arithmetic */
-static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
-                       int rd, int rs, int rt)
+static void gen_arith(DisasContext *ctx, uint32_t opc,
+                      int rd, int rs, int rt)
 {
     const char *opn = "arith";
 
@@ -2359,7 +2370,7 @@ static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Conditional move */
-static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+static void gen_cond_move(DisasContext *ctx, uint32_t opc,
                           int rd, int rs, int rt)
 {
     const char *opn = "cond move";
@@ -2395,7 +2406,7 @@ static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Logic */
-static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+static void gen_logic(DisasContext *ctx, uint32_t opc,
                       int rd, int rs, int rt)
 {
     const char *opn = "logic";
@@ -2457,7 +2468,7 @@ static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Set on lower than */
-static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+static void gen_slt(DisasContext *ctx, uint32_t opc,
                     int rd, int rs, int rt)
 {
     const char *opn = "slt";
@@ -2490,8 +2501,8 @@ static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
 }
 
 /* Shifts */
-static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
-                       int rd, int rs, int rt)
+static void gen_shift(DisasContext *ctx, uint32_t opc,
+                      int rd, int rs, int rt)
 {
     const char *opn = "shifts";
     TCGv t0, t1;
@@ -4097,12 +4108,12 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
     tcg_gen_st_tl(arg, cpu_env, off);
 }
 
-static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
     if (sel != 0)
-        check_insn(env, ctx, ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS32);
 
     switch (reg) {
     case 0:
@@ -4112,17 +4123,17 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Index";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_mvpcontrol(arg, cpu_env);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_mvpconf0(arg, cpu_env);
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_mvpconf1(arg, cpu_env);
             rn = "MVPConf1";
             break;
@@ -4137,37 +4148,37 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Random";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
@@ -4183,37 +4194,37 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tcstatus(arg, cpu_env);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tcbind(arg, cpu_env);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tcrestart(arg, cpu_env);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tchalt(arg, cpu_env);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tccontext(arg, cpu_env);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tcschedule(arg, cpu_env);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tcschefback(arg, cpu_env);
             rn = "TCScheFBack";
             break;
@@ -4254,7 +4265,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "PageMask";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
             rn = "PageGrain";
             break;
@@ -4269,27 +4280,27 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Wired";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
             rn = "SRSConf0";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
             rn = "SRSConf1";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
             rn = "SRSConf2";
             break;
         case 4:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
             rn = "SRSConf3";
             break;
         case 5:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
             rn = "SRSConf4";
             break;
@@ -4300,7 +4311,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
     case 7:
         switch (sel) {
         case 0:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
             rn = "HWREna";
             break;
@@ -4368,17 +4379,17 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Status";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
             rn = "IntCtl";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
             rn = "SRSCtl";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             rn = "SRSMap";
             break;
@@ -4414,7 +4425,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "PRid";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
             rn = "EBase";
             break;
@@ -4488,7 +4499,7 @@ static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
         switch (sel) {
         case 0:
 #if defined(TARGET_MIPS64)
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
             tcg_gen_ext32s_tl(arg, arg);
             rn = "XContext";
@@ -4677,12 +4688,12 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
     if (sel != 0)
-        check_insn(env, ctx, ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS32);
 
     if (use_icount)
         gen_io_start();
@@ -4695,17 +4706,17 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Index";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_mvpcontrol(cpu_env, arg);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf1";
             break;
@@ -4720,37 +4731,37 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Random";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpecontrol(cpu_env, arg);
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpeconf0(cpu_env, arg);
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpeconf1(cpu_env, arg);
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_yqmask(cpu_env, arg);
             rn = "YQMask";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpeopt(cpu_env, arg);
             rn = "VPEOpt";
             break;
@@ -4765,37 +4776,37 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcstatus(cpu_env, arg);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcbind(cpu_env, arg);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcrestart(cpu_env, arg);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tchalt(cpu_env, arg);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tccontext(cpu_env, arg);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcschedule(cpu_env, arg);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcschefback(cpu_env, arg);
             rn = "TCScheFBack";
             break;
@@ -4834,7 +4845,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "PageMask";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_pagegrain(cpu_env, arg);
             rn = "PageGrain";
             break;
@@ -4849,27 +4860,27 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Wired";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf0(cpu_env, arg);
             rn = "SRSConf0";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf1(cpu_env, arg);
             rn = "SRSConf1";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf2(cpu_env, arg);
             rn = "SRSConf2";
             break;
         case 4:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf3(cpu_env, arg);
             rn = "SRSConf3";
             break;
         case 5:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf4(cpu_env, arg);
             rn = "SRSConf4";
             break;
@@ -4880,7 +4891,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
     case 7:
         switch (sel) {
         case 0:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_hwrena(cpu_env, arg);
             rn = "HWREna";
             break;
@@ -4935,21 +4946,21 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "Status";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_intctl(cpu_env, arg);
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsctl(cpu_env, arg);
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -4987,7 +4998,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
             rn = "PRid";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_ebase(cpu_env, arg);
             rn = "EBase";
             break;
@@ -5066,7 +5077,7 @@ static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, i
         switch (sel) {
         case 0:
 #if defined(TARGET_MIPS64)
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             gen_helper_mtc0_xcontext(cpu_env, arg);
             rn = "XContext";
             break;
@@ -5274,12 +5285,12 @@ die:
 }
 
 #if defined(TARGET_MIPS64)
-static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
     if (sel != 0)
-        check_insn(env, ctx, ISA_MIPS64);
+        check_insn(ctx, ISA_MIPS64);
 
     switch (reg) {
     case 0:
@@ -5289,17 +5300,17 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Index";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_mvpcontrol(arg, cpu_env);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_mvpconf0(arg, cpu_env);
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_mvpconf1(arg, cpu_env);
             rn = "MVPConf1";
             break;
@@ -5314,37 +5325,37 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Random";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
             rn = "YQMask";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
             rn = "VPEOpt";
             break;
@@ -5359,37 +5370,37 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tcstatus(arg, cpu_env);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mfc0_tcbind(arg, cpu_env);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_dmfc0_tcrestart(arg, cpu_env);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_dmfc0_tchalt(arg, cpu_env);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_dmfc0_tccontext(arg, cpu_env);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_dmfc0_tcschedule(arg, cpu_env);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_dmfc0_tcschefback(arg, cpu_env);
             rn = "TCScheFBack";
             break;
@@ -5428,7 +5439,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "PageMask";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
             rn = "PageGrain";
             break;
@@ -5443,27 +5454,27 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Wired";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
             rn = "SRSConf0";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
             rn = "SRSConf1";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
             rn = "SRSConf2";
             break;
         case 4:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
             rn = "SRSConf3";
             break;
         case 5:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
             rn = "SRSConf4";
             break;
@@ -5474,7 +5485,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
     case 7:
         switch (sel) {
         case 0:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
             rn = "HWREna";
             break;
@@ -5540,17 +5551,17 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Status";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
             rn = "IntCtl";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
             rn = "SRSCtl";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             rn = "SRSMap";
             break;
@@ -5585,7 +5596,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "PRid";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
             rn = "EBase";
             break;
@@ -5657,7 +5668,7 @@ static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
     case 20:
         switch (sel) {
         case 0:
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
             rn = "XContext";
             break;
@@ -5843,12 +5854,12 @@ die:
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
+static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 {
     const char *rn = "invalid";
 
     if (sel != 0)
-        check_insn(env, ctx, ISA_MIPS64);
+        check_insn(ctx, ISA_MIPS64);
 
     if (use_icount)
         gen_io_start();
@@ -5861,17 +5872,17 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Index";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_mvpcontrol(cpu_env, arg);
             rn = "MVPControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf1";
             break;
@@ -5886,37 +5897,37 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Random";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpecontrol(cpu_env, arg);
             rn = "VPEControl";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpeconf0(cpu_env, arg);
             rn = "VPEConf0";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpeconf1(cpu_env, arg);
             rn = "VPEConf1";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_yqmask(cpu_env, arg);
             rn = "YQMask";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
             rn = "VPESchedule";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_vpeopt(cpu_env, arg);
             rn = "VPEOpt";
             break;
@@ -5931,37 +5942,37 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "EntryLo0";
             break;
         case 1:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcstatus(cpu_env, arg);
             rn = "TCStatus";
             break;
         case 2:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcbind(cpu_env, arg);
             rn = "TCBind";
             break;
         case 3:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcrestart(cpu_env, arg);
             rn = "TCRestart";
             break;
         case 4:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tchalt(cpu_env, arg);
             rn = "TCHalt";
             break;
         case 5:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tccontext(cpu_env, arg);
             rn = "TCContext";
             break;
         case 6:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcschedule(cpu_env, arg);
             rn = "TCSchedule";
             break;
         case 7:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             gen_helper_mtc0_tcschefback(cpu_env, arg);
             rn = "TCScheFBack";
             break;
@@ -6000,7 +6011,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "PageMask";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_pagegrain(cpu_env, arg);
             rn = "PageGrain";
             break;
@@ -6015,27 +6026,27 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Wired";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf0(cpu_env, arg);
             rn = "SRSConf0";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf1(cpu_env, arg);
             rn = "SRSConf1";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf2(cpu_env, arg);
             rn = "SRSConf2";
             break;
         case 4:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf3(cpu_env, arg);
             rn = "SRSConf3";
             break;
         case 5:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsconf4(cpu_env, arg);
             rn = "SRSConf4";
             break;
@@ -6046,7 +6057,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
     case 7:
         switch (sel) {
         case 0:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_hwrena(cpu_env, arg);
             rn = "HWREna";
             break;
@@ -6105,21 +6116,21 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "Status";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_intctl(cpu_env, arg);
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_srsctl(cpu_env, arg);
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -6167,7 +6178,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
             rn = "PRid";
             break;
         case 1:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_ebase(cpu_env, arg);
             rn = "EBase";
             break;
@@ -6236,7 +6247,7 @@ static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg,
     case 20:
         switch (sel) {
         case 0:
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             gen_helper_mtc0_xcontext(cpu_env, arg);
             rn = "XContext";
             break;
@@ -6493,7 +6504,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
                 gen_helper_mftc0_tcschefback(t0, cpu_env);
                 break;
             default:
-                gen_mfc0(env, ctx, t0, rt, sel);
+                gen_mfc0(ctx, t0, rt, sel);
                 break;
             }
             break;
@@ -6503,7 +6514,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
                 gen_helper_mftc0_entryhi(t0, cpu_env);
                 break;
             default:
-                gen_mfc0(env, ctx, t0, rt, sel);
+                gen_mfc0(ctx, t0, rt, sel);
                 break;
             }
         case 12:
@@ -6512,7 +6523,7 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
                 gen_helper_mftc0_status(t0, cpu_env);
                 break;
             default:
-                gen_mfc0(env, ctx, t0, rt, sel);
+                gen_mfc0(ctx, t0, rt, sel);
                 break;
             }
         case 13:
@@ -6561,12 +6572,12 @@ static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
                 gen_helper_mftc0_debug(t0, cpu_env);
                 break;
             default:
-                gen_mfc0(env, ctx, t0, rt, sel);
+                gen_mfc0(ctx, t0, rt, sel);
                 break;
             }
             break;
         default:
-            gen_mfc0(env, ctx, t0, rt, sel);
+            gen_mfc0(ctx, t0, rt, sel);
         }
     } else switch (sel) {
     /* GPR registers. */
@@ -6711,7 +6722,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
                 gen_helper_mttc0_tcschefback(cpu_env, t0);
                 break;
             default:
-                gen_mtc0(env, ctx, t0, rd, sel);
+                gen_mtc0(ctx, t0, rd, sel);
                 break;
             }
             break;
@@ -6721,7 +6732,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
                 gen_helper_mttc0_entryhi(cpu_env, t0);
                 break;
             default:
-                gen_mtc0(env, ctx, t0, rd, sel);
+                gen_mtc0(ctx, t0, rd, sel);
                 break;
             }
         case 12:
@@ -6730,7 +6741,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
                 gen_helper_mttc0_status(cpu_env, t0);
                 break;
             default:
-                gen_mtc0(env, ctx, t0, rd, sel);
+                gen_mtc0(ctx, t0, rd, sel);
                 break;
             }
         case 13:
@@ -6759,12 +6770,12 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
                 gen_helper_mttc0_debug(cpu_env, t0);
                 break;
             default:
-                gen_mtc0(env, ctx, t0, rd, sel);
+                gen_mtc0(ctx, t0, rd, sel);
                 break;
             }
             break;
         default:
-            gen_mtc0(env, ctx, t0, rd, sel);
+            gen_mtc0(ctx, t0, rd, sel);
         }
     } else switch (sel) {
     /* GPR registers. */
@@ -6866,7 +6877,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
             /* Treat as NOP. */
             return;
         }
-        gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
+        gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
         opn = "mfc0";
         break;
     case OPC_MTC0:
@@ -6874,35 +6885,35 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
             TCGv t0 = tcg_temp_new();
 
             gen_load_gpr(t0, rt);
-            gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
+            gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
             tcg_temp_free(t0);
         }
         opn = "mtc0";
         break;
 #if defined(TARGET_MIPS64)
     case OPC_DMFC0:
-        check_insn(env, ctx, ISA_MIPS3);
+        check_insn(ctx, ISA_MIPS3);
         if (rt == 0) {
             /* Treat as NOP. */
             return;
         }
-        gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
+        gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
         opn = "dmfc0";
         break;
     case OPC_DMTC0:
-        check_insn(env, ctx, ISA_MIPS3);
+        check_insn(ctx, ISA_MIPS3);
         {
             TCGv t0 = tcg_temp_new();
 
             gen_load_gpr(t0, rt);
-            gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
+            gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
             tcg_temp_free(t0);
         }
         opn = "dmtc0";
         break;
 #endif
     case OPC_MFTR:
-        check_insn(env, ctx, ASE_MT);
+        check_insn(ctx, ASE_MT);
         if (rd == 0) {
             /* Treat as NOP. */
             return;
@@ -6912,7 +6923,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
         opn = "mftr";
         break;
     case OPC_MTTR:
-        check_insn(env, ctx, ASE_MT);
+        check_insn(ctx, ASE_MT);
         gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
                  ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
         opn = "mttr";
@@ -6943,13 +6954,13 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
         break;
     case OPC_ERET:
         opn = "eret";
-        check_insn(env, ctx, ISA_MIPS2);
+        check_insn(ctx, ISA_MIPS2);
         gen_helper_eret(cpu_env);
         ctx->bstate = BS_EXCP;
         break;
     case OPC_DERET:
         opn = "deret";
-        check_insn(env, ctx, ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS32);
         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
             MIPS_INVAL(opn);
             generate_exception(ctx, EXCP_RI);
@@ -6960,7 +6971,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
         break;
     case OPC_WAIT:
         opn = "wait";
-        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
         /* If we get an exception, we want to restart at next instruction */
         ctx->pc += 4;
         save_cpu_state(ctx, 1);
@@ -6980,15 +6991,15 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
 #endif /* !CONFIG_USER_ONLY */
 
 /* CP1 Branches (before delay slot) */
-static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
-                                 int32_t cc, int32_t offset)
+static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
+                                int32_t cc, int32_t offset)
 {
     target_ulong btarget;
     const char *opn = "cp1 cond branch";
     TCGv_i32 t0 = tcg_temp_new_i32();
 
     if (cc != 0)
-        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
 
     btarget = ctx->pc + 4 + offset;
 
@@ -9032,15 +9043,14 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
                fregnames[fs], fregnames[ft]);
 }
 
-static void
-gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
+static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
 {
     TCGv t0;
 
 #if !defined(CONFIG_USER_ONLY)
     /* The Linux kernel will emulate rdhwr if it's not supported natively.
        Therefore only check the ISA in system mode.  */
-    check_insn(env, ctx, ISA_MIPS32R2);
+    check_insn(ctx, ISA_MIPS32R2);
 #endif
     t0 = tcg_temp_new();
 
@@ -9082,8 +9092,7 @@ gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
     tcg_temp_free(t0);
 }
 
-static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
-                               int insn_bytes)
+static void handle_delay_slot(DisasContext *ctx, int insn_bytes)
 {
     if (ctx->hflags & MIPS_HFLAG_BMASK) {
         int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
@@ -9121,7 +9130,7 @@ static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
         case MIPS_HFLAG_BR:
             /* unconditional branch to register */
             MIPS_DEBUG("branch to register");
-            if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
+            if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
                 TCGv t0 = tcg_temp_new();
                 TCGv_i32 t1 = tcg_temp_new_i32();
 
@@ -9438,7 +9447,7 @@ static void gen_mips16_restore (DisasContext *ctx,
 
 #define DECR_AND_LOAD(reg) do {                   \
         tcg_gen_subi_tl(t0, t0, 4);               \
-        tcg_gen_qemu_ld32u(t1, t0, ctx->mem_idx); \
+        tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx); \
         gen_store_gpr(t1, reg);                   \
     } while (0)
 
@@ -9548,7 +9557,7 @@ static void gen_addiupc (DisasContext *ctx, int rx, int imm,
 }
 
 #if defined(TARGET_MIPS64)
-static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
+static void decode_i64_mips16 (DisasContext *ctx,
                                int ry, int funct, int16_t offset,
                                int extended)
 {
@@ -9556,7 +9565,7 @@ static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
     case I64_LDSP:
         check_mips_64(ctx);
         offset = extended ? offset : offset << 3;
-        gen_ld(env, ctx, OPC_LD, ry, 29, offset);
+        gen_ld(ctx, OPC_LD, ry, 29, offset);
         break;
     case I64_SDSP:
         check_mips_64(ctx);
@@ -9571,20 +9580,20 @@ static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
     case I64_DADJSP:
         check_mips_64(ctx);
         offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
-        gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
+        gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
         break;
     case I64_LDPC:
         if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
             generate_exception(ctx, EXCP_RI);
         } else {
             offset = extended ? offset : offset << 3;
-            gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
+            gen_ld(ctx, OPC_LDPC, ry, 0, offset);
         }
         break;
     case I64_DADDIU5:
         check_mips_64(ctx);
         offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
-        gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
+        gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
         break;
     case I64_DADDIUPC:
         check_mips_64(ctx);
@@ -9594,7 +9603,7 @@ static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
     case I64_DADDIUSP:
         check_mips_64(ctx);
         offset = extended ? offset : offset << 2;
-        gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
+        gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
         break;
     }
 }
@@ -9621,7 +9630,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
        counterparts.  */
     switch (op) {
     case M16_OPC_ADDIUSP:
-        gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
+        gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
         break;
     case M16_OPC_ADDIUPC:
         gen_addiupc(ctx, rx, imm, 0, 1);
@@ -9641,28 +9650,28 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
     case M16_OPC_SHIFT:
         switch (ctx->opcode & 0x3) {
         case 0x0:
-            gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
             break;
         case 0x1:
 #if defined(TARGET_MIPS64)
             check_mips_64(ctx);
-            gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
 #else
             generate_exception(ctx, EXCP_RI);
 #endif
             break;
         case 0x2:
-            gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
             break;
         case 0x3:
-            gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
             break;
         }
         break;
 #if defined(TARGET_MIPS64)
     case M16_OPC_LD:
             check_mips_64(ctx);
-        gen_ld(env, ctx, OPC_LD, ry, rx, offset);
+        gen_ld(ctx, OPC_LD, ry, rx, offset);
         break;
 #endif
     case M16_OPC_RRIA:
@@ -9673,22 +9682,22 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
         if ((ctx->opcode >> 4) & 0x1) {
 #if defined(TARGET_MIPS64)
             check_mips_64(ctx);
-            gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
+            gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
 #else
             generate_exception(ctx, EXCP_RI);
 #endif
         } else {
-            gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
+            gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
         }
         break;
     case M16_OPC_ADDIU8:
-        gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
+        gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
         break;
     case M16_OPC_SLTI:
-        gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
+        gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
         break;
     case M16_OPC_SLTIU:
-        gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
+        gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
         break;
     case M16_OPC_I8:
         switch (funct) {
@@ -9702,7 +9711,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             gen_st(ctx, OPC_SW, 31, 29, imm);
             break;
         case I8_ADJSP:
-            gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
+            gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
             break;
         case I8_SVRS:
             {
@@ -9742,29 +9751,29 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
         break;
 #endif
     case M16_OPC_LB:
-        gen_ld(env, ctx, OPC_LB, ry, rx, offset);
+        gen_ld(ctx, OPC_LB, ry, rx, offset);
         break;
     case M16_OPC_LH:
-        gen_ld(env, ctx, OPC_LH, ry, rx, offset);
+        gen_ld(ctx, OPC_LH, ry, rx, offset);
         break;
     case M16_OPC_LWSP:
-        gen_ld(env, ctx, OPC_LW, rx, 29, offset);
+        gen_ld(ctx, OPC_LW, rx, 29, offset);
         break;
     case M16_OPC_LW:
-        gen_ld(env, ctx, OPC_LW, ry, rx, offset);
+        gen_ld(ctx, OPC_LW, ry, rx, offset);
         break;
     case M16_OPC_LBU:
-        gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
+        gen_ld(ctx, OPC_LBU, ry, rx, offset);
         break;
     case M16_OPC_LHU:
-        gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
+        gen_ld(ctx, OPC_LHU, ry, rx, offset);
         break;
     case M16_OPC_LWPC:
-        gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
+        gen_ld(ctx, OPC_LWPC, rx, 0, offset);
         break;
 #if defined(TARGET_MIPS64)
     case M16_OPC_LWU:
-        gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
+        gen_ld(ctx, OPC_LWU, ry, rx, offset);
         break;
 #endif
     case M16_OPC_SB:
@@ -9781,7 +9790,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
         break;
 #if defined(TARGET_MIPS64)
     case M16_OPC_I64:
-        decode_i64_mips16(env, ctx, ry, funct, offset, 1);
+        decode_i64_mips16(ctx, ry, funct, offset, 1);
         break;
 #endif
     default:
@@ -9816,7 +9825,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
         {
             int16_t imm = ((uint8_t) ctx->opcode) << 2;
 
-            gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
+            gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
         }
         break;
     case M16_OPC_ADDIUPC:
@@ -9849,28 +9858,28 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
     case M16_OPC_SHIFT:
         switch (ctx->opcode & 0x3) {
         case 0x0:
-            gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
             break;
         case 0x1:
 #if defined(TARGET_MIPS64)
             check_mips_64(ctx);
-            gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
 #else
             generate_exception(ctx, EXCP_RI);
 #endif
             break;
         case 0x2:
-            gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
             break;
         case 0x3:
-            gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
+            gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
             break;
         }
         break;
 #if defined(TARGET_MIPS64)
     case M16_OPC_LD:
         check_mips_64(ctx);
-        gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
+        gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
         break;
 #endif
     case M16_OPC_RRIA:
@@ -9880,12 +9889,12 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             if ((ctx->opcode >> 4) & 1) {
 #if defined(TARGET_MIPS64)
                 check_mips_64(ctx);
-                gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
+                gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
 #else
                 generate_exception(ctx, EXCP_RI);
 #endif
             } else {
-                gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
+                gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
             }
         }
         break;
@@ -9893,19 +9902,19 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
         {
             int16_t imm = (int8_t) ctx->opcode;
 
-            gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
+            gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
         }
         break;
     case M16_OPC_SLTI:
         {
             int16_t imm = (uint8_t) ctx->opcode;
-            gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
+            gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
         }
         break;
     case M16_OPC_SLTIU:
         {
             int16_t imm = (uint8_t) ctx->opcode;
-            gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
+            gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
         }
         break;
     case M16_OPC_I8:
@@ -9926,7 +9935,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
                 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
                 break;
             case I8_ADJSP:
-                gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
+                gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
                               ((int8_t)ctx->opcode) << 3);
                 break;
             case I8_SVRS:
@@ -9957,12 +9966,12 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
 
                     reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
                         ((ctx->opcode >> 5) & 0x7);
-                    gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
+                    gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
                 }
                 break;
             case I8_MOVR32:
                 reg32 = ctx->opcode & 0x1f;
-                gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
+                gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
                 break;
             default:
                 generate_exception(ctx, EXCP_RI);
@@ -9974,13 +9983,13 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
         {
             int16_t imm = (uint8_t) ctx->opcode;
 
-            gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
+            gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
         }
         break;
     case M16_OPC_CMPI:
         {
             int16_t imm = (uint8_t) ctx->opcode;
-            gen_logic_imm(env, ctx, OPC_XORI, 24, rx, imm);
+            gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
         }
         break;
 #if defined(TARGET_MIPS64)
@@ -9990,30 +9999,30 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
         break;
 #endif
     case M16_OPC_LB:
-        gen_ld(env, ctx, OPC_LB, ry, rx, offset);
+        gen_ld(ctx, OPC_LB, ry, rx, offset);
         break;
     case M16_OPC_LH:
-        gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
+        gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
         break;
     case M16_OPC_LWSP:
-        gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
+        gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
         break;
     case M16_OPC_LW:
-        gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
+        gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
         break;
     case M16_OPC_LBU:
-        gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
+        gen_ld(ctx, OPC_LBU, ry, rx, offset);
         break;
     case M16_OPC_LHU:
-        gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
+        gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
         break;
     case M16_OPC_LWPC:
-        gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
+        gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
         break;
 #if defined (TARGET_MIPS64)
     case M16_OPC_LWU:
         check_mips_64(ctx);
-        gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
+        gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
         break;
 #endif
     case M16_OPC_SB:
@@ -10055,7 +10064,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
                 goto done;
             }
 
-            gen_arith(env, ctx, mips32_op, rz, rx, ry);
+            gen_arith(ctx, mips32_op, rz, rx, ry);
         done:
             ;
         }
@@ -10084,7 +10093,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             /* XXX: not clear which exception should be raised
              *      when in debug mode...
              */
-            check_insn(env, ctx, ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS32);
             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                 generate_exception(ctx, EXCP_DBp);
             } else {
@@ -10092,46 +10101,46 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             }
             break;
         case RR_SLT:
-            gen_slt(env, ctx, OPC_SLT, 24, rx, ry);
+            gen_slt(ctx, OPC_SLT, 24, rx, ry);
             break;
         case RR_SLTU:
-            gen_slt(env, ctx, OPC_SLTU, 24, rx, ry);
+            gen_slt(ctx, OPC_SLTU, 24, rx, ry);
             break;
         case RR_BREAK:
             generate_exception(ctx, EXCP_BREAK);
             break;
         case RR_SLLV:
-            gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
+            gen_shift(ctx, OPC_SLLV, ry, rx, ry);
             break;
         case RR_SRLV:
-            gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
+            gen_shift(ctx, OPC_SRLV, ry, rx, ry);
             break;
         case RR_SRAV:
-            gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
+            gen_shift(ctx, OPC_SRAV, ry, rx, ry);
             break;
 #if defined (TARGET_MIPS64)
         case RR_DSRL:
             check_mips_64(ctx);
-            gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
+            gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
             break;
 #endif
         case RR_CMP:
-            gen_logic(env, ctx, OPC_XOR, 24, rx, ry);
+            gen_logic(ctx, OPC_XOR, 24, rx, ry);
             break;
         case RR_NEG:
-            gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
+            gen_arith(ctx, OPC_SUBU, rx, 0, ry);
             break;
         case RR_AND:
-            gen_logic(env, ctx, OPC_AND, rx, rx, ry);
+            gen_logic(ctx, OPC_AND, rx, rx, ry);
             break;
         case RR_OR:
-            gen_logic(env, ctx, OPC_OR, rx, rx, ry);
+            gen_logic(ctx, OPC_OR, rx, rx, ry);
             break;
         case RR_XOR:
-            gen_logic(env, ctx, OPC_XOR, rx, rx, ry);
+            gen_logic(ctx, OPC_XOR, rx, rx, ry);
             break;
         case RR_NOT:
-            gen_logic(env, ctx, OPC_NOR, rx, ry, 0);
+            gen_logic(ctx, OPC_NOR, rx, ry, 0);
             break;
         case RR_MFHI:
             gen_HILO(ctx, OPC_MFHI, rx);
@@ -10171,19 +10180,19 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
 #if defined (TARGET_MIPS64)
         case RR_DSRA:
             check_mips_64(ctx);
-            gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
+            gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
             break;
         case RR_DSLLV:
             check_mips_64(ctx);
-            gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
+            gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
             break;
         case RR_DSRLV:
             check_mips_64(ctx);
-            gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
+            gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
             break;
         case RR_DSRAV:
             check_mips_64(ctx);
-            gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
+            gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
             break;
 #endif
         case RR_MULT:
@@ -10228,7 +10237,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
 #if defined(TARGET_MIPS64)
     case M16_OPC_I64:
         funct = (ctx->opcode >> 8) & 0x7;
-        decode_i64_mips16(env, ctx, ry, funct, offset, 0);
+        decode_i64_mips16(ctx, ry, funct, offset, 0);
         break;
 #endif
     default:
@@ -10730,23 +10739,23 @@ static int mmreg2 (int r)
 /* Zero-extended immediate */
 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
 
-static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
+static void gen_addiur1sp(DisasContext *ctx)
 {
     int rd = mmreg(uMIPS_RD(ctx->opcode));
 
-    gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
+    gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
 }
 
-static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
+static void gen_addiur2(DisasContext *ctx)
 {
     static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
     int rd = mmreg(uMIPS_RD(ctx->opcode));
     int rs = mmreg(uMIPS_RS(ctx->opcode));
 
-    gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
+    gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
 }
 
-static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
+static void gen_addiusp(DisasContext *ctx)
 {
     int encoded = ZIMM(ctx->opcode, 1, 9);
     int decoded;
@@ -10761,18 +10770,18 @@ static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
         decoded = encoded - 768;
     }
 
-    gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
+    gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
 }
 
-static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
+static void gen_addius5(DisasContext *ctx)
 {
     int imm = SIMM(ctx->opcode, 1, 4);
     int rd = (ctx->opcode >> 5) & 0x1f;
 
-    gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
+    gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
 }
 
-static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
+static void gen_andi16(DisasContext *ctx)
 {
     static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
                                  31, 32, 63, 64, 255, 32768, 65535 };
@@ -10780,7 +10789,7 @@ static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
     int rs = mmreg(uMIPS_RS(ctx->opcode));
     int encoded = ZIMM(ctx->opcode, 0, 4);
 
-    gen_logic_imm(env, ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
+    gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
 }
 
 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
@@ -10831,7 +10840,7 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
 }
 
 
-static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
+static void gen_pool16c_insn(DisasContext *ctx, int *is_branch)
 {
     int rd = mmreg((ctx->opcode >> 3) & 0x7);
     int rs = mmreg(ctx->opcode & 0x7);
@@ -10842,25 +10851,25 @@ static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_bran
     case NOT16 + 1:
     case NOT16 + 2:
     case NOT16 + 3:
-        gen_logic(env, ctx, OPC_NOR, rd, rs, 0);
+        gen_logic(ctx, OPC_NOR, rd, rs, 0);
         break;
     case XOR16 + 0:
     case XOR16 + 1:
     case XOR16 + 2:
     case XOR16 + 3:
-        gen_logic(env, ctx, OPC_XOR, rd, rd, rs);
+        gen_logic(ctx, OPC_XOR, rd, rd, rs);
         break;
     case AND16 + 0:
     case AND16 + 1:
     case AND16 + 2:
     case AND16 + 3:
-        gen_logic(env, ctx, OPC_AND, rd, rd, rs);
+        gen_logic(ctx, OPC_AND, rd, rd, rs);
         break;
     case OR16 + 0:
     case OR16 + 1:
     case OR16 + 2:
     case OR16 + 3:
-        gen_logic(env, ctx, OPC_OR, rd, rd, rs);
+        gen_logic(ctx, OPC_OR, rd, rd, rs);
         break;
     case LWM16 + 0:
     case LWM16 + 1:
@@ -10935,7 +10944,7 @@ static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_bran
         /* XXX: not clear which exception should be raised
          *      when in debug mode...
          */
-        check_insn(env, ctx, ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS32);
         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
             generate_exception(ctx, EXCP_DBp);
         } else {
@@ -10948,7 +10957,7 @@ static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_bran
             int imm = ZIMM(ctx->opcode, 0, 5);
 
             gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
-            gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
+            gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
             /* Let normal delay slot handling in our caller take us
                to the branch target.  */
         }
@@ -11085,7 +11094,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
             /* Treat as NOP. */
             break;
         }
-        gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
+        gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
         break;
     case MTC0:
     case MTC0 + 32:
@@ -11094,7 +11103,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
             TCGv t0 = tcg_temp_new();
 
             gen_load_gpr(t0, rt);
-            gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
+            gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
             tcg_temp_free(t0);
         }
         break;
@@ -11113,11 +11122,11 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
         case CLZ:
             mips32_op = OPC_CLZ;
         do_cl:
-            check_insn(env, ctx, ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS32);
             gen_cl(ctx, mips32_op, rt, rs);
             break;
         case RDHWR:
-            gen_rdhwr(env, ctx, rt, rs);
+            gen_rdhwr(ctx, rt, rs);
             break;
         case WSBH:
             gen_bshfl(ctx, OPC_WSBH, rs, rt);
@@ -11146,7 +11155,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
         case MSUBU:
             mips32_op = OPC_MSUBU;
         do_muldiv:
-            check_insn(env, ctx, ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS32);
             gen_muldiv(ctx, mips32_op, rs, rt);
             break;
         default:
@@ -11187,12 +11196,12 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
         switch (minor) {
         case RDPGPR:
             check_cp0_enabled(ctx);
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_load_srsgpr(rt, rs);
             break;
         case WRPGPR:
             check_cp0_enabled(ctx);
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_store_srsgpr(rt, rs);
             break;
         default:
@@ -11272,7 +11281,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
             ctx->bstate = BS_STOP;
             break;
         case SDBBP:
-            check_insn(env, ctx, ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS32);
             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                 generate_exception(ctx, EXCP_DBp);
             } else {
@@ -11329,7 +11338,7 @@ enum {
     FMT_DWL_L = 2
 };
 
-static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
+static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
 {
     int extension = (ctx->opcode >> 6) & 0x3ff;
     uint32_t mips32_op;
@@ -11614,7 +11623,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             case ROTR:
                 mips32_op = OPC_ROTR;
             do_shifti:
-                gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
+                gen_shift_imm(ctx, mips32_op, rt, rs, rd);
                 break;
             default:
                 goto pool32a_invalid;
@@ -11639,7 +11648,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             case MUL:
                 mips32_op = OPC_MUL;
             do_arith:
-                gen_arith(env, ctx, mips32_op, rd, rs, rt);
+                gen_arith(ctx, mips32_op, rd, rs, rt);
                 break;
                 /* Shifts */
             case SLLV:
@@ -11654,7 +11663,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             case ROTRV:
                 mips32_op = OPC_ROTRV;
             do_shift:
-                gen_shift(env, ctx, mips32_op, rd, rs, rt);
+                gen_shift(ctx, mips32_op, rd, rs, rt);
                 break;
                 /* Logical operations */
             case AND:
@@ -11669,7 +11678,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             case XOR32:
                 mips32_op = OPC_XOR;
             do_logic:
-                gen_logic(env, ctx, mips32_op, rd, rs, rt);
+                gen_logic(ctx, mips32_op, rd, rs, rt);
                 break;
                 /* Set less than */
             case SLT:
@@ -11678,7 +11687,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             case SLTU:
                 mips32_op = OPC_SLTU;
             do_slt:
-                gen_slt(env, ctx, mips32_op, rd, rs, rt);
+                gen_slt(ctx, mips32_op, rd, rs, rt);
                 break;
             default:
                 goto pool32a_invalid;
@@ -11694,7 +11703,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             case MOVZ:
                 mips32_op = OPC_MOVZ;
             do_cmov:
-                gen_cond_move(env, ctx, mips32_op, rd, rs, rt);
+                gen_cond_move(ctx, mips32_op, rd, rs, rt);
                 break;
             case LWXS:
                 gen_ldxs(ctx, rs, rt, rd);
@@ -11839,7 +11848,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
                 }
                 break;
             case POOL32FXF:
-                gen_pool32fxf(env, ctx, rt, rs);
+                gen_pool32fxf(ctx, rt, rs);
                 break;
             case 0x00:
                 /* PLL foo */
@@ -12107,7 +12116,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
                target. */
             break;
         case LUI:
-            gen_logic_imm(env, ctx, OPC_LUI, rs, -1, imm);
+            gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
             break;
         case SYNCI:
             break;
@@ -12129,10 +12138,10 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             mips32_op = OPC_BC1TANY4;
         do_cp1mips3d:
             check_cop1x(ctx);
-            check_insn(env, ctx, ASE_MIPS3D);
+            check_insn(ctx, ASE_MIPS3D);
             /* Fall through */
         do_cp1branch:
-            gen_compute_branch1(env, ctx, mips32_op,
+            gen_compute_branch1(ctx, mips32_op,
                                 (ctx->opcode >> 18) & 0x7, imm << 1);
             *is_branch = 1;
             break;
@@ -12185,7 +12194,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             mips32_op = OPC_LL;
             goto do_ld_lr;
         do_ld_lr:
-            gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
+            gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
             break;
         do_st_lr:
             gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
@@ -12213,7 +12222,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
     case ADDIU32:
         mips32_op = OPC_ADDIU;
     do_addi:
-        gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
+        gen_arith_imm(ctx, mips32_op, rt, rs, imm);
         break;
 
         /* Logical operations */
@@ -12226,7 +12235,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
     case ANDI32:
         mips32_op = OPC_ANDI;
     do_logici:
-        gen_logic_imm(env, ctx, mips32_op, rt, rs, imm);
+        gen_logic_imm(ctx, mips32_op, rt, rs, imm);
         break;
 
         /* Set less than immediate */
@@ -12236,7 +12245,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
     case SLTIU32:
         mips32_op = OPC_SLTIU;
     do_slti:
-        gen_slt_imm(env, ctx, mips32_op, rt, rs, imm);
+        gen_slt_imm(ctx, mips32_op, rt, rs, imm);
         break;
     case JALX32:
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
@@ -12323,7 +12332,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
         mips32_op = OPC_SW;
         goto do_st;
     do_ld:
-        gen_ld(env, ctx, mips32_op, rt, rs, imm);
+        gen_ld(ctx, mips32_op, rt, rs, imm);
         break;
     do_st:
         gen_st(ctx, mips32_op, rt, rs, imm);
@@ -12443,7 +12452,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
                 break;
             }
 
-            gen_arith(env, ctx, opc, rd, rs1, rs2);
+            gen_arith(ctx, opc, rd, rs1, rs2);
         }
         break;
     case POOL16B:
@@ -12463,11 +12472,11 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
                 break;
             }
 
-            gen_shift_imm(env, ctx, opc, rd, rs, amount);
+            gen_shift_imm(ctx, opc, rd, rs, amount);
         }
         break;
     case POOL16C:
-        gen_pool16c_insn(env, ctx, is_branch);
+        gen_pool16c_insn(ctx, is_branch);
         break;
     case LWGP16:
         {
@@ -12475,7 +12484,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
             int rb = 28;            /* GP */
             int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
 
-            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
+            gen_ld(ctx, OPC_LW, rd, rb, offset);
         }
         break;
     case POOL16F:
@@ -12496,8 +12505,8 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
             rs = rs_rt_enc[enc_rs];
             rt = rs_rt_enc[enc_rt];
 
-            gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
-            gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
+            gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
+            gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
         }
         break;
     case LBU16:
@@ -12507,7 +12516,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
             int16_t offset = ZIMM(ctx->opcode, 0, 4);
             offset = (offset == 0xf ? -1 : offset);
 
-            gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
+            gen_ld(ctx, OPC_LBU, rd, rb, offset);
         }
         break;
     case LHU16:
@@ -12516,7 +12525,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
             int rb = mmreg(uMIPS_RS(ctx->opcode));
             int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
 
-            gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
+            gen_ld(ctx, OPC_LHU, rd, rb, offset);
         }
         break;
     case LWSP16:
@@ -12525,7 +12534,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
             int rb = 29;            /* SP */
             int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
 
-            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
+            gen_ld(ctx, OPC_LW, rd, rb, offset);
         }
         break;
     case LW16:
@@ -12534,7 +12543,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
             int rb = mmreg(uMIPS_RS(ctx->opcode));
             int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
 
-            gen_ld(env, ctx, OPC_LW, rd, rb, offset);
+            gen_ld(ctx, OPC_LW, rd, rb, offset);
         }
         break;
     case SB16:
@@ -12578,29 +12587,29 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
             int rd = uMIPS_RD5(ctx->opcode);
             int rs = uMIPS_RS5(ctx->opcode);
 
-            gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
+            gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
         }
         break;
     case ANDI16:
-        gen_andi16(env, ctx);
+        gen_andi16(ctx);
         break;
     case POOL16D:
         switch (ctx->opcode & 0x1) {
         case ADDIUS5:
-            gen_addius5(env, ctx);
+            gen_addius5(ctx);
             break;
         case ADDIUSP:
-            gen_addiusp(env, ctx);
+            gen_addiusp(ctx);
             break;
         }
         break;
     case POOL16E:
         switch (ctx->opcode & 0x1) {
         case ADDIUR2:
-            gen_addiur2(env, ctx);
+            gen_addiur2(ctx);
             break;
         case ADDIUR1SP:
-            gen_addiur1sp(env, ctx);
+            gen_addiur1sp(ctx);
             break;
         }
         break;
@@ -12651,17 +12660,12 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b
 #endif
 
 /* MIPSDSP functions. */
-static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
+static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
                            int rd, int base, int offset)
 {
     const char *opn = "ldx";
     TCGv t0;
 
-    if (rd == 0) {
-        MIPS_DEBUG("NOP");
-        return;
-    }
-
     check_dsp(ctx);
     t0 = tcg_temp_new();
 
@@ -13717,8 +13721,7 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
 
 }
 
-static void gen_mipsdsp_bitinsn(CPUMIPSState *env, DisasContext *ctx,
-                                uint32_t op1, uint32_t op2,
+static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
                                 int ret, int val)
 {
     const char *opn = "mipsdsp Bit/ Manipulation";
@@ -13866,7 +13869,6 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
                                      int ret, int v1, int v2, int check_ret)
 {
     const char *opn = "mipsdsp add compare pick";
-    TCGv_i32 t0;
     TCGv t1;
     TCGv v1_t;
     TCGv v2_t;
@@ -13877,7 +13879,6 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
         return;
     }
 
-    t0 = tcg_temp_new_i32();
     t1 = tcg_temp_new();
     v1_t = tcg_temp_new();
     v2_t = tcg_temp_new();
@@ -13886,26 +13887,6 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
     gen_load_gpr(v2_t, v2);
 
     switch (op1) {
-    case OPC_APPEND_DSP:
-        switch (op2) {
-        case OPC_APPEND:
-            tcg_gen_movi_i32(t0, v2);
-            gen_helper_append(cpu_gpr[ret], cpu_gpr[ret], v1_t, t0);
-            break;
-        case OPC_PREPEND:
-            tcg_gen_movi_i32(t0, v2);
-            gen_helper_prepend(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
-            break;
-        case OPC_BALIGN:
-            tcg_gen_movi_i32(t0, v2);
-            gen_helper_balign(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
-            break;
-        default:            /* Invid */
-            MIPS_INVAL("MASK APPEND");
-            generate_exception(ctx, EXCP_RI);
-            break;
-        }
-        break;
     case OPC_CMPU_EQ_QB_DSP:
         switch (op2) {
         case OPC_CMPU_EQ_QB:
@@ -14063,23 +14044,95 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
             break;
         }
         break;
+#endif
+    }
+
+    tcg_temp_free(t1);
+    tcg_temp_free(v1_t);
+    tcg_temp_free(v2_t);
+
+    (void)opn; /* avoid a compiler warning */
+    MIPS_DEBUG("%s", opn);
+}
+
+static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
+                               uint32_t op1, int rt, int rs, int sa)
+{
+    const char *opn = "mipsdsp append/dappend";
+    TCGv t0;
+
+    check_dspr2(ctx);
+
+    if (rt == 0) {
+        /* Treat as NOP. */
+        MIPS_DEBUG("NOP");
+        return;
+    }
+
+    t0 = tcg_temp_new();
+    gen_load_gpr(t0, rs);
+
+    switch (op1) {
+    case OPC_APPEND_DSP:
+        switch (MASK_APPEND(ctx->opcode)) {
+        case OPC_APPEND:
+            if (sa != 0) {
+                tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
+            }
+            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
+            break;
+        case OPC_PREPEND:
+            if (sa != 0) {
+                tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
+                tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
+                tcg_gen_shli_tl(t0, t0, 32 - sa);
+                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
+            }
+            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
+            break;
+        case OPC_BALIGN:
+            sa &= 3;
+            if (sa != 0 && sa != 2) {
+                tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
+                tcg_gen_ext32u_tl(t0, t0);
+                tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
+                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
+            }
+            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
+            break;
+        default:            /* Invalid */
+            MIPS_INVAL("MASK APPEND");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+#ifdef TARGET_MIPS64
     case OPC_DAPPEND_DSP:
-        switch (op2) {
+        switch (MASK_DAPPEND(ctx->opcode)) {
         case OPC_DAPPEND:
-            tcg_gen_movi_i32(t0, v2);
-            gen_helper_dappend(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
+            if (sa != 0) {
+                tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
+            }
             break;
         case OPC_PREPENDD:
-            tcg_gen_movi_i32(t0, v2);
-            gen_helper_prependd(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
+            tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
+            tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
+            tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
             break;
         case OPC_PREPENDW:
-            tcg_gen_movi_i32(t0, v2);
-            gen_helper_prependw(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
+            if (sa != 0) {
+                tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
+                tcg_gen_shli_tl(t0, t0, 64 - sa);
+                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
+            }
             break;
         case OPC_DBALIGN:
-            tcg_gen_movi_i32(t0, v2);
-            gen_helper_dbalign(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
+            sa &= 7;
+            if (sa != 0 && sa != 2 && sa != 4) {
+                tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
+                tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
+                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
+            }
             break;
         default:            /* Invalid */
             MIPS_INVAL("MASK DAPPEND");
@@ -14089,12 +14142,7 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
         break;
 #endif
     }
-
-    tcg_temp_free_i32(t0);
-    tcg_temp_free(t1);
-    tcg_temp_free(v1_t);
-    tcg_temp_free(v2_t);
-
+    tcg_temp_free(t0);
     (void)opn; /* avoid a compiler warning */
     MIPS_DEBUG("%s", opn);
 }
@@ -14372,18 +14420,18 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         switch (op1) {
         case OPC_SLL:          /* Shift with immediate */
         case OPC_SRA:
-            gen_shift_imm(env, ctx, op1, rd, rt, sa);
+            gen_shift_imm(ctx, op1, rd, rt, sa);
             break;
         case OPC_SRL:
             switch ((ctx->opcode >> 21) & 0x1f) {
             case 1:
                 /* rotr is decoded as srl on non-R2 CPUs */
-                if (env->insn_flags & ISA_MIPS32R2) {
+                if (ctx->insn_flags & ISA_MIPS32R2) {
                     op1 = OPC_ROTR;
                 }
                 /* Fallthrough */
             case 0:
-                gen_shift_imm(env, ctx, op1, rd, rt, sa);
+                gen_shift_imm(ctx, op1, rd, rt, sa);
                 break;
             default:
                 generate_exception(ctx, EXCP_RI);
@@ -14392,27 +14440,27 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_MOVN:         /* Conditional move */
         case OPC_MOVZ:
-            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
+            check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
                                  INSN_LOONGSON2E | INSN_LOONGSON2F);
-            gen_cond_move(env, ctx, op1, rd, rs, rt);
+            gen_cond_move(ctx, op1, rd, rs, rt);
             break;
         case OPC_ADD ... OPC_SUBU:
-            gen_arith(env, ctx, op1, rd, rs, rt);
+            gen_arith(ctx, op1, rd, rs, rt);
             break;
         case OPC_SLLV:         /* Shifts */
         case OPC_SRAV:
-            gen_shift(env, ctx, op1, rd, rs, rt);
+            gen_shift(ctx, op1, rd, rs, rt);
             break;
         case OPC_SRLV:
             switch ((ctx->opcode >> 6) & 0x1f) {
             case 1:
                 /* rotrv is decoded as srlv on non-R2 CPUs */
-                if (env->insn_flags & ISA_MIPS32R2) {
+                if (ctx->insn_flags & ISA_MIPS32R2) {
                     op1 = OPC_ROTRV;
                 }
                 /* Fallthrough */
             case 0:
-                gen_shift(env, ctx, op1, rd, rs, rt);
+                gen_shift(ctx, op1, rd, rs, rt);
                 break;
             default:
                 generate_exception(ctx, EXCP_RI);
@@ -14421,17 +14469,17 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_SLT:          /* Set on less than */
         case OPC_SLTU:
-            gen_slt(env, ctx, op1, rd, rs, rt);
+            gen_slt(ctx, op1, rd, rs, rt);
             break;
         case OPC_AND:          /* Logic*/
         case OPC_OR:
         case OPC_NOR:
         case OPC_XOR:
-            gen_logic(env, ctx, op1, rd, rs, rt);
+            gen_logic(ctx, op1, rd, rs, rt);
             break;
         case OPC_MULT ... OPC_DIVU:
             if (sa) {
-                check_insn(env, ctx, INSN_VR54XX);
+                check_insn(ctx, INSN_VR54XX);
                 op1 = MASK_MUL_VR54XX(ctx->opcode);
                 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
             } else
@@ -14483,7 +14531,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
 
         case OPC_MOVCI:
-            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
             if (env->CP0_Config1 & (1 << CP0C1_FP)) {
                 check_cp1_enabled(ctx);
                 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
@@ -14499,22 +14547,22 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_DSRA:
         case OPC_DSLL32:
         case OPC_DSRA32:
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             check_mips_64(ctx);
-            gen_shift_imm(env, ctx, op1, rd, rt, sa);
+            gen_shift_imm(ctx, op1, rd, rt, sa);
             break;
         case OPC_DSRL:
             switch ((ctx->opcode >> 21) & 0x1f) {
             case 1:
                 /* drotr is decoded as dsrl on non-R2 CPUs */
-                if (env->insn_flags & ISA_MIPS32R2) {
+                if (ctx->insn_flags & ISA_MIPS32R2) {
                     op1 = OPC_DROTR;
                 }
                 /* Fallthrough */
             case 0:
-                check_insn(env, ctx, ISA_MIPS3);
+                check_insn(ctx, ISA_MIPS3);
                 check_mips_64(ctx);
-                gen_shift_imm(env, ctx, op1, rd, rt, sa);
+                gen_shift_imm(ctx, op1, rd, rt, sa);
                 break;
             default:
                 generate_exception(ctx, EXCP_RI);
@@ -14525,14 +14573,14 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             switch ((ctx->opcode >> 21) & 0x1f) {
             case 1:
                 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
-                if (env->insn_flags & ISA_MIPS32R2) {
+                if (ctx->insn_flags & ISA_MIPS32R2) {
                     op1 = OPC_DROTR32;
                 }
                 /* Fallthrough */
             case 0:
-                check_insn(env, ctx, ISA_MIPS3);
+                check_insn(ctx, ISA_MIPS3);
                 check_mips_64(ctx);
-                gen_shift_imm(env, ctx, op1, rd, rt, sa);
+                gen_shift_imm(ctx, op1, rd, rt, sa);
                 break;
             default:
                 generate_exception(ctx, EXCP_RI);
@@ -14540,28 +14588,28 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             }
             break;
         case OPC_DADD ... OPC_DSUBU:
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             check_mips_64(ctx);
-            gen_arith(env, ctx, op1, rd, rs, rt);
+            gen_arith(ctx, op1, rd, rs, rt);
             break;
         case OPC_DSLLV:
         case OPC_DSRAV:
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             check_mips_64(ctx);
-            gen_shift(env, ctx, op1, rd, rs, rt);
+            gen_shift(ctx, op1, rd, rs, rt);
             break;
         case OPC_DSRLV:
             switch ((ctx->opcode >> 6) & 0x1f) {
             case 1:
                 /* drotrv is decoded as dsrlv on non-R2 CPUs */
-                if (env->insn_flags & ISA_MIPS32R2) {
+                if (ctx->insn_flags & ISA_MIPS32R2) {
                     op1 = OPC_DROTRV;
                 }
                 /* Fallthrough */
             case 0:
-                check_insn(env, ctx, ISA_MIPS3);
+                check_insn(ctx, ISA_MIPS3);
                 check_mips_64(ctx);
-                gen_shift(env, ctx, op1, rd, rs, rt);
+                gen_shift(ctx, op1, rd, rs, rt);
                 break;
             default:
                 generate_exception(ctx, EXCP_RI);
@@ -14569,7 +14617,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             }
             break;
         case OPC_DMULT ... OPC_DDIVU:
-            check_insn(env, ctx, ISA_MIPS3);
+            check_insn(ctx, ISA_MIPS3);
             check_mips_64(ctx);
             gen_muldiv(ctx, op1, rs, rt);
             break;
@@ -14585,22 +14633,22 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         switch (op1) {
         case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
         case OPC_MSUB ... OPC_MSUBU:
-            check_insn(env, ctx, ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS32);
             gen_muldiv(ctx, op1, rs, rt);
             break;
         case OPC_MUL:
-            gen_arith(env, ctx, op1, rd, rs, rt);
+            gen_arith(ctx, op1, rd, rs, rt);
             break;
         case OPC_CLO:
         case OPC_CLZ:
-            check_insn(env, ctx, ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS32);
             gen_cl(ctx, op1, rd, rs);
             break;
         case OPC_SDBBP:
             /* XXX: not clear which exception should be raised
              *      when in debug mode...
              */
-            check_insn(env, ctx, ISA_MIPS32);
+            check_insn(ctx, ISA_MIPS32);
             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                 generate_exception(ctx, EXCP_DBp);
             } else {
@@ -14614,13 +14662,13 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_MULTU_G_2F:
         case OPC_MOD_G_2F:
         case OPC_MODU_G_2F:
-            check_insn(env, ctx, INSN_LOONGSON2F);
+            check_insn(ctx, INSN_LOONGSON2F);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
 #if defined(TARGET_MIPS64)
         case OPC_DCLO:
         case OPC_DCLZ:
-            check_insn(env, ctx, ISA_MIPS64);
+            check_insn(ctx, ISA_MIPS64);
             check_mips_64(ctx);
             gen_cl(ctx, op1, rd, rs);
             break;
@@ -14630,7 +14678,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_DDIVU_G_2F:
         case OPC_DMOD_G_2F:
         case OPC_DMODU_G_2F:
-            check_insn(env, ctx, INSN_LOONGSON2F);
+            check_insn(ctx, INSN_LOONGSON2F);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
 #endif
@@ -14645,19 +14693,19 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         switch (op1) {
         case OPC_EXT:
         case OPC_INS:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_bitops(ctx, op1, rt, rs, sa, rd);
             break;
         case OPC_BSHFL:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             op2 = MASK_BSHFL(ctx->opcode);
             gen_bshfl(ctx, op2, rt, rd);
             break;
         case OPC_RDHWR:
-            gen_rdhwr(env, ctx, rt, rd);
+            gen_rdhwr(ctx, rt, rd);
             break;
         case OPC_FORK:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             {
                 TCGv t0 = tcg_temp_new();
                 TCGv t1 = tcg_temp_new();
@@ -14670,7 +14718,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             }
             break;
         case OPC_YIELD:
-            check_insn(env, ctx, ASE_MT);
+            check_insn(ctx, ASE_MT);
             {
                 TCGv t0 = tcg_temp_new();
 
@@ -14686,7 +14734,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
         /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
          * the same mask and op1. */
-            if ((env->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
+            if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
                 op2 = MASK_ADDUH_QB(ctx->opcode);
                 switch (op2) {
                 case OPC_ADDUH_QB:
@@ -14714,7 +14762,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                     generate_exception(ctx, EXCP_RI);
                     break;
                 }
-            } else if (env->insn_flags & INSN_LOONGSON2E) {
+            } else if (ctx->insn_flags & INSN_LOONGSON2E) {
                 gen_loongson_integer(ctx, op1, rd, rs, rt);
             } else {
                 generate_exception(ctx, EXCP_RI);
@@ -14729,7 +14777,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_LBUX:
             case OPC_LHX:
             case OPC_LWX:
-                gen_mipsdsp_ld(env, ctx, op2, rd, rs, rt);
+                gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
                 break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK LX");
@@ -14760,7 +14808,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_REPLV_QB:
             case OPC_REPL_PH:
             case OPC_REPLV_PH:
-                gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt);
+                gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
                 break;
             default:
                 MIPS_INVAL("MASK ABSQ_S.PH");
@@ -14913,9 +14961,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             }
             break;
         case OPC_APPEND_DSP:
-            check_dspr2(ctx);
-            op2 = MASK_APPEND(ctx->opcode);
-            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
+            gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
             break;
         case OPC_EXTR_W_DSP:
             op2 = MASK_EXTR_W(ctx->opcode);
@@ -14952,12 +14998,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 #if defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
-            check_insn(env, ctx, ISA_MIPS64R2);
+            check_insn(ctx, ISA_MIPS64R2);
             check_mips_64(ctx);
             gen_bitops(ctx, op1, rt, rs, sa, rd);
             break;
         case OPC_DBSHFL:
-            check_insn(env, ctx, ISA_MIPS64R2);
+            check_insn(ctx, ISA_MIPS64R2);
             check_mips_64(ctx);
             op2 = MASK_DBSHFL(ctx->opcode);
             gen_bshfl(ctx, op2, rt, rd);
@@ -14965,7 +15011,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
         case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
         case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
-            check_insn(env, ctx, INSN_LOONGSON2E);
+            check_insn(ctx, INSN_LOONGSON2E);
             gen_loongson_integer(ctx, op1, rd, rs, rt);
             break;
         case OPC_ABSQ_S_QH_DSP:
@@ -14996,7 +15042,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             case OPC_REPLV_OB:
             case OPC_REPLV_PW:
             case OPC_REPLV_QH:
-                gen_mipsdsp_bitinsn(env, ctx, op1, op2, rd, rt);
+                gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
                 break;
             default:            /* Invalid */
                 MIPS_INVAL("MASK ABSQ_S.QH");
@@ -15089,9 +15135,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             }
             break;
         case OPC_DAPPEND_DSP:
-            check_dspr2(ctx);
-            op2 = MASK_DAPPEND(ctx->opcode);
-            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
+            gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
             break;
         case OPC_DEXTR_W_DSP:
             op2 = MASK_DEXTR_W(ctx->opcode);
@@ -15217,7 +15261,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             gen_trap(ctx, op1, rs, -1, imm);
             break;
         case OPC_SYNCI:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             /* Treat as NOP. */
             break;
         case OPC_BPOSGE32:    /* MIPS DSP branch */
@@ -15263,27 +15307,27 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                 op2 = MASK_MFMC0(ctx->opcode);
                 switch (op2) {
                 case OPC_DMT:
-                    check_insn(env, ctx, ASE_MT);
+                    check_insn(ctx, ASE_MT);
                     gen_helper_dmt(t0);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_EMT:
-                    check_insn(env, ctx, ASE_MT);
+                    check_insn(ctx, ASE_MT);
                     gen_helper_emt(t0);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_DVPE:
-                    check_insn(env, ctx, ASE_MT);
+                    check_insn(ctx, ASE_MT);
                     gen_helper_dvpe(t0, cpu_env);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_EVPE:
-                    check_insn(env, ctx, ASE_MT);
+                    check_insn(ctx, ASE_MT);
                     gen_helper_evpe(t0, cpu_env);
                     gen_store_gpr(t0, rt);
                     break;
                 case OPC_DI:
-                    check_insn(env, ctx, ISA_MIPS32R2);
+                    check_insn(ctx, ISA_MIPS32R2);
                     save_cpu_state(ctx, 1);
                     gen_helper_di(t0, cpu_env);
                     gen_store_gpr(t0, rt);
@@ -15291,7 +15335,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
                     ctx->bstate = BS_STOP;
                     break;
                 case OPC_EI:
-                    check_insn(env, ctx, ISA_MIPS32R2);
+                    check_insn(ctx, ISA_MIPS32R2);
                     save_cpu_state(ctx, 1);
                     gen_helper_ei(t0, cpu_env);
                     gen_store_gpr(t0, rt);
@@ -15308,11 +15352,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 #endif /* !CONFIG_USER_ONLY */
             break;
         case OPC_RDPGPR:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_load_srsgpr(rt, rd);
             break;
         case OPC_WRPGPR:
-            check_insn(env, ctx, ISA_MIPS32R2);
+            check_insn(ctx, ISA_MIPS32R2);
             gen_store_srsgpr(rt, rd);
             break;
         default:
@@ -15323,17 +15367,17 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         break;
     case OPC_ADDI: /* Arithmetic with immediate opcode */
     case OPC_ADDIU:
-         gen_arith_imm(env, ctx, op, rt, rs, imm);
+         gen_arith_imm(ctx, op, rt, rs, imm);
          break;
     case OPC_SLTI: /* Set on less than with immediate opcode */
     case OPC_SLTIU:
-         gen_slt_imm(env, ctx, op, rt, rs, imm);
+         gen_slt_imm(ctx, op, rt, rs, imm);
          break;
     case OPC_ANDI: /* Arithmetic with immediate opcode */
     case OPC_LUI:
     case OPC_ORI:
     case OPC_XORI:
-         gen_logic_imm(env, ctx, op, rt, rs, imm);
+         gen_logic_imm(ctx, op, rt, rs, imm);
          break;
     case OPC_J ... OPC_JAL: /* Jump */
          offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
@@ -15347,7 +15391,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
          break;
     case OPC_LB ... OPC_LWR: /* Load and stores */
     case OPC_LL:
-         gen_ld(env, ctx, op, rt, rs, imm);
+         gen_ld(ctx, op, rt, rs, imm);
          break;
     case OPC_SB ... OPC_SW:
     case OPC_SWR:
@@ -15358,11 +15402,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
          break;
     case OPC_CACHE:
         check_cp0_enabled(ctx);
-        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
         /* Treat as NOP. */
         break;
     case OPC_PREF:
-        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
+        check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
         /* Treat as NOP. */
         break;
 
@@ -15381,7 +15425,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             switch (op1) {
             case OPC_MFHC1:
             case OPC_MTHC1:
-                check_insn(env, ctx, ISA_MIPS32R2);
+                check_insn(ctx, ISA_MIPS32R2);
             case OPC_MFC1:
             case OPC_CFC1:
             case OPC_MTC1:
@@ -15391,17 +15435,17 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 #if defined(TARGET_MIPS64)
             case OPC_DMFC1:
             case OPC_DMTC1:
-                check_insn(env, ctx, ISA_MIPS3);
+                check_insn(ctx, ISA_MIPS3);
                 gen_cp1(ctx, op1, rt, rd);
                 break;
 #endif
             case OPC_BC1ANY2:
             case OPC_BC1ANY4:
                 check_cop1x(ctx);
-                check_insn(env, ctx, ASE_MIPS3D);
+                check_insn(ctx, ASE_MIPS3D);
                 /* fall through */
             case OPC_BC1:
-                gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
+                gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
                                     (rt >> 2) & 0x7, imm << 2);
                 *is_branch = 1;
                 break;
@@ -15432,7 +15476,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         generate_exception_err(ctx, EXCP_CpU, 2);
         break;
     case OPC_CP2:
-        check_insn(env, ctx, INSN_LOONGSON2F);
+        check_insn(ctx, INSN_LOONGSON2F);
         /* Note that these instructions use different fields.  */
         gen_loongson_multimedia(ctx, sa, rd, rt);
         break;
@@ -15484,36 +15528,36 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
     case OPC_LDL ... OPC_LDR:
     case OPC_LLD:
     case OPC_LD:
-        check_insn(env, ctx, ISA_MIPS3);
+        check_insn(ctx, ISA_MIPS3);
         check_mips_64(ctx);
-        gen_ld(env, ctx, op, rt, rs, imm);
+        gen_ld(ctx, op, rt, rs, imm);
         break;
     case OPC_SDL ... OPC_SDR:
     case OPC_SD:
-        check_insn(env, ctx, ISA_MIPS3);
+        check_insn(ctx, ISA_MIPS3);
         check_mips_64(ctx);
         gen_st(ctx, op, rt, rs, imm);
         break;
     case OPC_SCD:
-        check_insn(env, ctx, ISA_MIPS3);
+        check_insn(ctx, ISA_MIPS3);
         check_mips_64(ctx);
         gen_st_cond(ctx, op, rt, rs, imm);
         break;
     case OPC_DADDI:
     case OPC_DADDIU:
-        check_insn(env, ctx, ISA_MIPS3);
+        check_insn(ctx, ISA_MIPS3);
         check_mips_64(ctx);
-        gen_arith_imm(env, ctx, op, rt, rs, imm);
+        gen_arith_imm(ctx, op, rt, rs, imm);
         break;
 #endif
     case OPC_JALX:
-        check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
+        check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
         gen_compute_branch(ctx, op, 4, rs, rt, offset);
         *is_branch = 1;
         break;
     case OPC_MDMX:
-        check_insn(env, ctx, ASE_MDMX);
+        check_insn(ctx, ASE_MDMX);
         /* MDMX: Not implemented. */
     default:            /* Invalid */
         MIPS_INVAL("major opcode");
@@ -15544,6 +15588,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
     ctx.pc = pc_start;
     ctx.saved_pc = -1;
     ctx.singlestep_enabled = env->singlestep_enabled;
+    ctx.insn_flags = env->insn_flags;
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
     /* Restore delay slot state from the tb context.  */
@@ -15596,10 +15641,10 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
             ctx.opcode = cpu_ldl_code(env, ctx.pc);
             insn_bytes = 4;
             decode_opc(env, &ctx, &is_branch);
-        } else if (env->insn_flags & ASE_MICROMIPS) {
+        } else if (ctx.insn_flags & ASE_MICROMIPS) {
             ctx.opcode = cpu_lduw_code(env, ctx.pc);
             insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
-        } else if (env->insn_flags & ASE_MIPS16) {
+        } else if (ctx.insn_flags & ASE_MIPS16) {
             ctx.opcode = cpu_lduw_code(env, ctx.pc);
             insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
         } else {
@@ -15608,7 +15653,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
             break;
         }
         if (!is_branch) {
-            handle_delay_slot(env, &ctx, insn_bytes);
+            handle_delay_slot(&ctx, insn_bytes);
         }
         ctx.pc += insn_bytes;
 
@@ -15933,10 +15978,8 @@ void cpu_state_reset(CPUMIPSState *env)
     if (env->CP0_Config1 & (1 << CP0C1_FP)) {
         env->CP0_Status |= (1 << CP0St_CU1);
     }
-    if (env->cpu_model->insn_flags & ASE_DSPR2) {
-        env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
-    } else if (env->cpu_model->insn_flags & ASE_DSP) {
-        env->hflags |= MIPS_HFLAG_DSP;
+    if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
+        env->CP0_Status |= (1 << CP0St_MX);
     }
 #else
     if (env->hflags & MIPS_HFLAG_BMASK) {
diff --git a/tests/tcg/mips/mips32-dsp/mthlip.c b/tests/tcg/mips/mips32-dsp/mthlip.c
index 9549aae36a..85f94d8450 100644
--- a/tests/tcg/mips/mips32-dsp/mthlip.c
+++ b/tests/tcg/mips/mips32-dsp/mthlip.c
@@ -30,7 +30,7 @@ int main()
     assert(ach == resulth);
     assert(acl == resultl);
 
-    dsp = 0x3f;
+    dsp = 0x1f;
     ach = 0x05;
     acl = 0xB4CB;
     rs  = 0x00FFBBAA;
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index 27fe26b5c2..dde9d5784e 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -4,24 +4,24 @@
 # Auto-generated header for tracing routines
 
 $(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
+	@cmp -s $< $@ || cp $< $@
 $(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
 	$(call quiet-command,$(TRACETOOL) \
 		--format=h \
 		--backend=$(TRACE_BACKEND) \
 		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
-	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
 
 ######################################################################
 # Auto-generated tracing routines (non-DTrace)
 
 ifneq ($(TRACE_BACKEND),dtrace)
 $(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
+	@cmp -s $< $@ || cp $< $@
 $(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
 	$(call quiet-command,$(TRACETOOL) \
 		--format=c \
 		--backend=$(TRACE_BACKEND) \
 		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
-	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
 
 $(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h
 endif