summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--block-migration.c30
-rw-r--r--block.c69
-rw-r--r--block/cloop.c12
-rw-r--r--block/curl.c2
-rw-r--r--block/iscsi.c2
-rw-r--r--block/mirror.c5
-rw-r--r--block/qed.c16
-rw-r--r--block/vmdk.c23
-rw-r--r--block/vvfat.c2
-rw-r--r--blockdev.c15
-rw-r--r--hw/block/xen_disk.c7
-rw-r--r--include/block/block.h5
-rw-r--r--linux-headers/asm-s390/kvm.h24
-rw-r--r--linux-headers/linux/kvm.h17
-rw-r--r--linux-headers/linux/vfio.h6
-rw-r--r--qemu-img.c116
-rw-r--r--qemu-io.c2
-rw-r--r--qemu-nbd.c3
-rw-r--r--target-alpha/fpu_helper.c7
-rw-r--r--target-alpha/helper.h1
-rw-r--r--target-alpha/translate.c2363
-rw-r--r--target-s390x/cpu.h3
-rw-r--r--target-s390x/kvm.c175
-rw-r--r--tests/qemu-iotests/084.out5
-rwxr-xr-xtests/qemu-iotests/08785
-rw-r--r--tests/qemu-iotests/087.out18
-rw-r--r--trace-events4
27 files changed, 1332 insertions, 1685 deletions
diff --git a/block-migration.c b/block-migration.c
index 897fdbabb5..56951e09ae 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -310,13 +310,28 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
 
 /* Called with iothread lock taken.  */
 
-static void set_dirty_tracking(void)
+static int set_dirty_tracking(void)
 {
     BlkMigDevState *bmds;
+    int ret;
 
     QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
-        bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE);
+        bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,
+                                                      NULL);
+        if (!bmds->dirty_bitmap) {
+            ret = -errno;
+            goto fail;
+        }
     }
+    return 0;
+
+fail:
+    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
+        if (bmds->dirty_bitmap) {
+            bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
+        }
+    }
+    return ret;
 }
 
 static void unset_dirty_tracking(void)
@@ -611,10 +626,17 @@ static int block_save_setup(QEMUFile *f, void *opaque)
             block_mig_state.submitted, block_mig_state.transferred);
 
     qemu_mutex_lock_iothread();
-    init_blk_migration(f);
 
     /* start track dirty blocks */
-    set_dirty_tracking();
+    ret = set_dirty_tracking();
+
+    if (ret) {
+        qemu_mutex_unlock_iothread();
+        return ret;
+    }
+
+    init_blk_migration(f);
+
     qemu_mutex_unlock_iothread();
 
     ret = flush_blks(f);
diff --git a/block.c b/block.c
index 990a7542a9..fc2edd33ae 100644
--- a/block.c
+++ b/block.c
@@ -332,10 +332,21 @@ void bdrv_register(BlockDriver *bdrv)
 }
 
 /* create a new block device (by default it is empty) */
-BlockDriverState *bdrv_new(const char *device_name)
+BlockDriverState *bdrv_new(const char *device_name, Error **errp)
 {
     BlockDriverState *bs;
 
+    if (bdrv_find(device_name)) {
+        error_setg(errp, "Device with id '%s' already exists",
+                   device_name);
+        return NULL;
+    }
+    if (bdrv_find_node(device_name)) {
+        error_setg(errp, "Device with node-name '%s' already exists",
+                   device_name);
+        return NULL;
+    }
+
     bs = g_malloc0(sizeof(BlockDriverState));
     QLIST_INIT(&bs->dirty_bitmaps);
     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
@@ -788,38 +799,36 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
     return open_flags;
 }
 
-static int bdrv_assign_node_name(BlockDriverState *bs,
-                                 const char *node_name,
-                                 Error **errp)
+static void bdrv_assign_node_name(BlockDriverState *bs,
+                                  const char *node_name,
+                                  Error **errp)
 {
     if (!node_name) {
-        return 0;
+        return;
     }
 
     /* empty string node name is invalid */
     if (node_name[0] == '\0') {
         error_setg(errp, "Empty node name");
-        return -EINVAL;
+        return;
     }
 
     /* takes care of avoiding namespaces collisions */
     if (bdrv_find(node_name)) {
         error_setg(errp, "node-name=%s is conflicting with a device id",
                    node_name);
-        return -EINVAL;
+        return;
     }
 
     /* takes care of avoiding duplicates node names */
     if (bdrv_find_node(node_name)) {
         error_setg(errp, "Duplicate node name");
-        return -EINVAL;
+        return;
     }
 
     /* copy node name into the bs and insert it into the graph list */
     pstrcpy(bs->node_name, sizeof(bs->node_name), node_name);
     QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs, node_list);
-
-    return 0;
 }
 
 /*
@@ -854,9 +863,10 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
 
     node_name = qdict_get_try_str(options, "node-name");
-    ret = bdrv_assign_node_name(bs, node_name, errp);
-    if (ret < 0) {
-        return ret;
+    bdrv_assign_node_name(bs, node_name, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        return -EINVAL;
     }
     qdict_del(options, "node-name");
 
@@ -1221,7 +1231,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
     qdict_put(snapshot_options, "file.filename",
               qstring_from_str(tmp_filename));
 
-    bs_snapshot = bdrv_new("");
+    bs_snapshot = bdrv_new("", &error_abort);
     bs_snapshot->is_temporary = 1;
 
     ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
@@ -1288,7 +1298,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
     if (*pbs) {
         bs = *pbs;
     } else {
-        bs = bdrv_new("");
+        bs = bdrv_new("", &error_abort);
     }
 
     /* NULL means an empty set of options */
@@ -2581,6 +2591,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
 {
     int64_t len;
 
+    if (size > INT_MAX) {
+        return -EIO;
+    }
+
     if (!bdrv_is_inserted(bs))
         return -ENOMEDIUM;
 
@@ -2601,7 +2615,7 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
 static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
                               int nb_sectors)
 {
-    if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
+    if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
         return -EIO;
     }
 
@@ -2686,6 +2700,10 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
         .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
     };
 
+    if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
+        return -EINVAL;
+    }
+
     qemu_iovec_init_external(&qiov, &iov, 1);
     return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
                         &qiov, is_write, flags);
@@ -2741,10 +2759,16 @@ int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
  */
 int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
 {
-    int64_t target_size = bdrv_getlength(bs) / BDRV_SECTOR_SIZE;
+    int64_t target_size;
     int64_t ret, nb_sectors, sector_num = 0;
     int n;
 
+    target_size = bdrv_getlength(bs);
+    if (target_size < 0) {
+        return target_size;
+    }
+    target_size /= BDRV_SECTOR_SIZE;
+
     for (;;) {
         nb_sectors = target_size - sector_num;
         if (nb_sectors <= 0) {
@@ -5096,7 +5120,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
     return true;
 }
 
-BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
+BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
+                                          Error **errp)
 {
     int64_t bitmap_size;
     BdrvDirtyBitmap *bitmap;
@@ -5105,7 +5130,13 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
 
     granularity >>= BDRV_SECTOR_BITS;
     assert(granularity);
-    bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
+    bitmap_size = bdrv_getlength(bs);
+    if (bitmap_size < 0) {
+        error_setg_errno(errp, -bitmap_size, "could not get length of device");
+        errno = -bitmap_size;
+        return NULL;
+    }
+    bitmap_size >>= BDRV_SECTOR_BITS;
     bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
     bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
diff --git a/block/cloop.c b/block/cloop.c
index b6ad50fbb4..8457737922 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -72,7 +72,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
     }
     s->block_size = be32_to_cpu(s->block_size);
     if (s->block_size % 512) {
-        error_setg(errp, "block_size %u must be a multiple of 512",
+        error_setg(errp, "block_size %" PRIu32 " must be a multiple of 512",
                    s->block_size);
         return -EINVAL;
     }
@@ -86,7 +86,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
      * need a buffer this big.
      */
     if (s->block_size > MAX_BLOCK_SIZE) {
-        error_setg(errp, "block_size %u must be %u MB or less",
+        error_setg(errp, "block_size %" PRIu32 " must be %u MB or less",
                    s->block_size,
                    MAX_BLOCK_SIZE / (1024 * 1024));
         return -EINVAL;
@@ -101,7 +101,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
     /* read offsets */
     if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
         /* Prevent integer overflow */
-        error_setg(errp, "n_blocks %u must be %zu or less",
+        error_setg(errp, "n_blocks %" PRIu32 " must be %zu or less",
                    s->n_blocks,
                    (UINT32_MAX - 1) / sizeof(uint64_t));
         return -EINVAL;
@@ -133,7 +133,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
 
         if (s->offsets[i] < s->offsets[i - 1]) {
             error_setg(errp, "offsets not monotonically increasing at "
-                       "index %u, image file is corrupt", i);
+                       "index %" PRIu32 ", image file is corrupt", i);
             ret = -EINVAL;
             goto fail;
         }
@@ -146,8 +146,8 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
          * ridiculous s->compressed_block allocation.
          */
         if (size > 2 * MAX_BLOCK_SIZE) {
-            error_setg(errp, "invalid compressed block size at index %u, "
-                       "image file is corrupt", i);
+            error_setg(errp, "invalid compressed block size at index %" PRIu32
+                       ", image file is corrupt", i);
             ret = -EINVAL;
             goto fail;
         }
diff --git a/block/curl.c b/block/curl.c
index 1b9b1f6341..6731d2891f 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -543,7 +543,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
     return 0;
 
 out:
-    fprintf(stderr, "CURL: Error opening file: %s\n", state->errmsg);
+    error_setg(errp, "CURL: Error opening file: %s", state->errmsg);
     curl_easy_cleanup(state->curl);
     state->curl = NULL;
 out_noclean:
diff --git a/block/iscsi.c b/block/iscsi.c
index f425573df8..a636ea4f53 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1401,7 +1401,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
     IscsiLun *iscsilun = NULL;
     QDict *bs_options;
 
-    bs = bdrv_new("");
+    bs = bdrv_new("", &error_abort);
 
     /* Read out options */
     while (options && options->name) {
diff --git a/block/mirror.c b/block/mirror.c
index 0ef41f999e..2618c3763c 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -605,7 +605,10 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
     s->granularity = granularity;
     s->buf_size = MAX(buf_size, granularity);
 
-    s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity);
+    s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, errp);
+    if (!s->dirty_bitmap) {
+        return;
+    }
     bdrv_set_enable_write_cache(s->target, true);
     bdrv_set_on_error(s->target, on_target_error, on_target_error);
     bdrv_iostatus_enable(s->target);
diff --git a/block/qed.c b/block/qed.c
index 3bd9db9c85..c130e42d0d 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -650,19 +650,21 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options,
     }
 
     if (!qed_is_cluster_size_valid(cluster_size)) {
-        fprintf(stderr, "QED cluster size must be within range [%u, %u] and power of 2\n",
-                QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
+        error_setg(errp, "QED cluster size must be within range [%u, %u] "
+                         "and power of 2",
+                   QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
         return -EINVAL;
     }
     if (!qed_is_table_size_valid(table_size)) {
-        fprintf(stderr, "QED table size must be within range [%u, %u] and power of 2\n",
-                QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
+        error_setg(errp, "QED table size must be within range [%u, %u] "
+                         "and power of 2",
+                   QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
         return -EINVAL;
     }
     if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) {
-        fprintf(stderr, "QED image size must be a non-zero multiple of "
-                        "cluster size and less than %" PRIu64 " bytes\n",
-                qed_max_image_size(cluster_size, table_size));
+        error_setg(errp, "QED image size must be a non-zero multiple of "
+                         "cluster size and less than %" PRIu64 " bytes",
+                   qed_max_image_size(cluster_size, table_size));
         return -EINVAL;
     }
 
diff --git a/block/vmdk.c b/block/vmdk.c
index b69988d169..06a1f9f93b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -262,7 +262,7 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
     p_name = strstr(desc, cid_str);
     if (p_name != NULL) {
         p_name += cid_str_size;
-        sscanf(p_name, "%x", &cid);
+        sscanf(p_name, "%" SCNx32, &cid);
     }
 
     return cid;
@@ -290,7 +290,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
     p_name = strstr(desc, "CID");
     if (p_name != NULL) {
         p_name += sizeof("CID");
-        snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
+        snprintf(p_name, sizeof(desc) - (p_name - desc), "%" PRIx32 "\n", cid);
         pstrcat(desc, sizeof(desc), tmp_desc);
     }
 
@@ -640,7 +640,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
 
     if (le32_to_cpu(header.version) > 3) {
         char buf[64];
-        snprintf(buf, sizeof(buf), "VMDK version %d",
+        snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
                  le32_to_cpu(header.version));
         error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
                   bs->device_name, "vmdk", buf);
@@ -671,8 +671,9 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
     }
     if (bdrv_getlength(file) <
             le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) {
-        error_setg(errp, "File truncated, expecting at least %lld bytes",
-                   le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE);
+        error_setg(errp, "File truncated, expecting at least %" PRId64 " bytes",
+                   (int64_t)(le64_to_cpu(header.grain_offset)
+                             * BDRV_SECTOR_SIZE));
         return -EINVAL;
     }
 
@@ -1707,8 +1708,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
     const char desc_template[] =
         "# Disk DescriptorFile\n"
         "version=1\n"
-        "CID=%x\n"
-        "parentCID=%x\n"
+        "CID=%" PRIx32 "\n"
+        "parentCID=%" PRIx32 "\n"
         "createType=\"%s\"\n"
         "%s"
         "\n"
@@ -1720,7 +1721,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
         "\n"
         "ddb.virtualHWVersion = \"%d\"\n"
         "ddb.geometry.cylinders = \"%" PRId64 "\"\n"
-        "ddb.geometry.heads = \"%d\"\n"
+        "ddb.geometry.heads = \"%" PRIu32 "\"\n"
         "ddb.geometry.sectors = \"63\"\n"
         "ddb.adapterType = \"%s\"\n";
 
@@ -1780,9 +1781,9 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
              strcmp(fmt, "twoGbMaxExtentFlat"));
     compress = !strcmp(fmt, "streamOptimized");
     if (flat) {
-        desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
+        desc_extent_line = "RW %" PRId64 " FLAT \"%s\" 0\n";
     } else {
-        desc_extent_line = "RW %lld SPARSE \"%s\"\n";
+        desc_extent_line = "RW %" PRId64 " SPARSE \"%s\"\n";
     }
     if (flat && backing_file) {
         error_setg(errp, "Flat image can't have backing file");
@@ -1850,7 +1851,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
     }
     /* generate descriptor file */
     desc = g_strdup_printf(desc_template,
-                           (unsigned int)time(NULL),
+                           (uint32_t)time(NULL),
                            parent_cid,
                            fmt,
                            parent_desc_line,
diff --git a/block/vvfat.c b/block/vvfat.c
index 1978c9ed62..c3af7ff4c5 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2947,7 +2947,7 @@ static int enable_write_target(BDRVVVFATState *s)
     unlink(s->qcow_filename);
 #endif
 
-    s->bs->backing_hd = bdrv_new("");
+    s->bs->backing_hd = bdrv_new("", &error_abort);
     s->bs->backing_hd->drv = &vvfat_write_target;
     s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
     *(void**)s->bs->backing_hd->opaque = s;
diff --git a/blockdev.c b/blockdev.c
index 5dd01ea147..09826f10cf 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -452,16 +452,14 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
         }
     }
 
-    if (bdrv_find_node(qemu_opts_id(opts))) {
-        error_setg(errp, "device id=%s is conflicting with a node-name",
-                   qemu_opts_id(opts));
-        goto early_err;
-    }
-
     /* init */
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
-    dinfo->bdrv = bdrv_new(dinfo->id);
+    dinfo->bdrv = bdrv_new(dinfo->id, &error);
+    if (error) {
+        error_propagate(errp, error);
+        goto bdrv_new_err;
+    }
     dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
     dinfo->bdrv->read_only = ro;
     dinfo->refcount = 1;
@@ -523,8 +521,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
 
 err:
     bdrv_unref(dinfo->bdrv);
-    g_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
+bdrv_new_err:
+    g_free(dinfo->id);
     g_free(dinfo);
 early_err:
     QDECREF(bs_opts);
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index bc061e6403..a8fea72edf 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -817,11 +817,14 @@ static int blk_connect(struct XenDevice *xendev)
     index = (blkdev->xendev.dev - 202 * 256) / 16;
     blkdev->dinfo = drive_get(IF_XEN, 0, index);
     if (!blkdev->dinfo) {
+        Error *local_err = NULL;
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
-        blkdev->bs = bdrv_new(blkdev->dev);
+        blkdev->bs = bdrv_new(blkdev->dev, &local_err);
+        if (local_err) {
+            blkdev->bs = NULL;
+        }
         if (blkdev->bs) {
-            Error *local_err = NULL;
             BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
                                                            readonly);
             if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
diff --git a/include/block/block.h b/include/block/block.h
index b3230a25f6..c12808a252 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -180,7 +180,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
     QEMUOptionParameter *options, Error **errp);
 int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
                      Error **errp);
-BlockDriverState *bdrv_new(const char *device_name);
+BlockDriverState *bdrv_new(const char *device_name, Error **errp);
 void bdrv_make_anon(BlockDriverState *bs);
 void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
 void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
@@ -429,7 +429,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
 
 struct HBitmapIter;
 typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
-BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity);
+BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
+                                          Error **errp);
 void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
 BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
 int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index cb4c1eb8a0..c003c6a73b 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -22,6 +22,8 @@
 #define KVM_DEV_FLIC_CLEAR_IRQS		3
 #define KVM_DEV_FLIC_APF_ENABLE		4
 #define KVM_DEV_FLIC_APF_DISABLE_WAIT	5
+#define KVM_DEV_FLIC_ADAPTER_REGISTER	6
+#define KVM_DEV_FLIC_ADAPTER_MODIFY	7
 /*
  * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
  * as well as up  to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
@@ -32,6 +34,26 @@
 #define KVM_S390_MAX_FLOAT_IRQS	266250
 #define KVM_S390_FLIC_MAX_BUFFER	0x2000000
 
+struct kvm_s390_io_adapter {
+	__u32 id;
+	__u8 isc;
+	__u8 maskable;
+	__u8 swap;
+	__u8 pad;
+};
+
+#define KVM_S390_IO_ADAPTER_MASK 1
+#define KVM_S390_IO_ADAPTER_MAP 2
+#define KVM_S390_IO_ADAPTER_UNMAP 3
+
+struct kvm_s390_io_adapter_req {
+	__u32 id;
+	__u8 type;
+	__u8 mask;
+	__u16 pad0;
+	__u64 addr;
+};
+
 /* for KVM_GET_REGS and KVM_SET_REGS */
 struct kvm_regs {
 	/* general purpose regs for s390 */
@@ -76,4 +98,6 @@ struct kvm_sync_regs {
 #define KVM_REG_S390_PFTOKEN	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5)
 #define KVM_REG_S390_PFCOMPARE	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6)
 #define KVM_REG_S390_PFSELECT	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_S390_PP		(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_S390_GBEA	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x9)
 #endif
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index e27a4b33cf..b278ab3326 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -740,6 +740,9 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_SPAPR_MULTITCE 94
 #define KVM_CAP_EXT_EMUL_CPUID 95
 #define KVM_CAP_HYPERV_TIME 96
+#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
+#define KVM_CAP_ENABLE_CAP_VM 98
+#define KVM_CAP_S390_IRQCHIP 99
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -755,9 +758,18 @@ struct kvm_irq_routing_msi {
 	__u32 pad;
 };
 
+struct kvm_irq_routing_s390_adapter {
+	__u64 ind_addr;
+	__u64 summary_addr;
+	__u64 ind_offset;
+	__u32 summary_offset;
+	__u32 adapter_id;
+};
+
 /* gsi routing entry types */
 #define KVM_IRQ_ROUTING_IRQCHIP 1
 #define KVM_IRQ_ROUTING_MSI 2
+#define KVM_IRQ_ROUTING_S390_ADAPTER 3
 
 struct kvm_irq_routing_entry {
 	__u32 gsi;
@@ -767,6 +779,7 @@ struct kvm_irq_routing_entry {
 	union {
 		struct kvm_irq_routing_irqchip irqchip;
 		struct kvm_irq_routing_msi msi;
+		struct kvm_irq_routing_s390_adapter adapter;
 		__u32 pad[8];
 	} u;
 };
@@ -1075,6 +1088,10 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_DEBUGREGS */
 #define KVM_GET_DEBUGREGS         _IOR(KVMIO,  0xa1, struct kvm_debugregs)
 #define KVM_SET_DEBUGREGS         _IOW(KVMIO,  0xa2, struct kvm_debugregs)
+/*
+ * vcpu version available with KVM_ENABLE_CAP
+ * vm version available with KVM_CAP_ENABLE_CAP_VM
+ */
 #define KVM_ENABLE_CAP            _IOW(KVMIO,  0xa3, struct kvm_enable_cap)
 /* Available with KVM_CAP_XSAVE */
 #define KVM_GET_XSAVE		  _IOR(KVMIO,  0xa4, struct kvm_xsave)
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 17c58e0ede..26c218e692 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -23,6 +23,12 @@
 
 #define VFIO_TYPE1_IOMMU		1
 #define VFIO_SPAPR_TCE_IOMMU		2
+#define VFIO_TYPE1v2_IOMMU		3
+/*
+ * IOMMU enforces DMA cache coherence (ex. PCIe NoSnoop stripping).  This
+ * capability is subject to change as groups are added or removed.
+ */
+#define VFIO_DMA_CC_IOMMU		4
 
 /*
  * The IOCTL interface is designed for extensibility by embedding the
diff --git a/qemu-img.c b/qemu-img.c
index 8455994c65..4dae84a182 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -57,8 +57,22 @@ static void format_print(void *opaque, const char *name)
     printf(" %s", name);
 }
 
+static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
+{
+    va_list ap;
+
+    error_printf("qemu-img: ");
+
+    va_start(ap, fmt);
+    error_vprintf(fmt, ap);
+    va_end(ap);
+
+    error_printf("\nTry 'qemu-img --help' for more information\n");
+    exit(EXIT_FAILURE);
+}
+
 /* Please keep in synch with qemu-img.texi */
-static void help(void)
+static void QEMU_NORETURN help(void)
 {
     const char *help_msg =
            "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
@@ -129,7 +143,7 @@ static void help(void)
     printf("%s\nSupported formats:", help_msg);
     bdrv_iterate_format(format_print, NULL);
     printf("\n");
-    exit(1);
+    exit(EXIT_SUCCESS);
 }
 
 static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
@@ -262,7 +276,8 @@ static int print_block_option_help(const char *filename, const char *fmt)
     return 0;
 }
 
-static BlockDriverState *bdrv_new_open(const char *filename,
+static BlockDriverState *bdrv_new_open(const char *id,
+                                       const char *filename,
                                        const char *fmt,
                                        int flags,
                                        bool require_io,
@@ -274,7 +289,7 @@ static BlockDriverState *bdrv_new_open(const char *filename,
     Error *local_err = NULL;
     int ret;
 
-    bs = bdrv_new("image");
+    bs = bdrv_new(id, &error_abort);
 
     if (fmt) {
         drv = bdrv_find_format(fmt);
@@ -398,7 +413,7 @@ static int img_create(int argc, char **argv)
     }
 
     if (optind >= argc) {
-        help();
+        error_exit("Expecting image file name");
     }
     optind++;
 
@@ -421,7 +436,7 @@ static int img_create(int argc, char **argv)
         img_size = (uint64_t)sval;
     }
     if (optind != argc) {
-        help();
+        error_exit("Unexpected argument: %s", argv[optind]);
     }
 
     bdrv_img_create(filename, fmt, base_filename, base_fmt,
@@ -590,7 +605,8 @@ static int img_check(int argc, char **argv)
             } else if (!strcmp(optarg, "all")) {
                 fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
             } else {
-                help();
+                error_exit("Unknown option value for -r "
+                           "(expecting 'leaks' or 'all'): %s", optarg);
             }
             break;
         case OPTION_OUTPUT:
@@ -602,7 +618,7 @@ static int img_check(int argc, char **argv)
         }
     }
     if (optind != argc - 1) {
-        help();
+        error_exit("Expecting one image file name");
     }
     filename = argv[optind++];
 
@@ -615,7 +631,7 @@ static int img_check(int argc, char **argv)
         return 1;
     }
 
-    bs = bdrv_new_open(filename, fmt, flags, true, quiet);
+    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         return 1;
     }
@@ -713,7 +729,7 @@ static int img_commit(int argc, char **argv)
         }
     }
     if (optind != argc - 1) {
-        help();
+        error_exit("Expecting one image file name");
     }
     filename = argv[optind++];
 
@@ -724,7 +740,7 @@ static int img_commit(int argc, char **argv)
         return -1;
     }
 
-    bs = bdrv_new_open(filename, fmt, flags, true, quiet);
+    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         return 1;
     }
@@ -959,7 +975,7 @@ static int img_compare(int argc, char **argv)
 
 
     if (optind != argc - 2) {
-        help();
+        error_exit("Expecting two image file names");
     }
     filename1 = argv[optind++];
     filename2 = argv[optind++];
@@ -967,14 +983,14 @@ static int img_compare(int argc, char **argv)
     /* Initialize before goto out */
     qemu_progress_init(progress, 2.0);
 
-    bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
+    bs1 = bdrv_new_open("image 1", filename1, fmt1, BDRV_O_FLAGS, true, quiet);
     if (!bs1) {
         error_report("Can't open file %s", filename1);
         ret = 2;
         goto out3;
     }
 
-    bs2 = bdrv_new_open(filename2, fmt2, BDRV_O_FLAGS, true, quiet);
+    bs2 = bdrv_new_open("image 2", filename2, fmt2, BDRV_O_FLAGS, true, quiet);
     if (!bs2) {
         error_report("Can't open file %s", filename2);
         ret = 2;
@@ -1275,7 +1291,7 @@ static int img_convert(int argc, char **argv)
     }
 
     if (bs_n < 1) {
-        help();
+        error_exit("Must specify image file name");
     }
 
 
@@ -1292,8 +1308,11 @@ static int img_convert(int argc, char **argv)
 
     total_sectors = 0;
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
-        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true,
-                                 quiet);
+        char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
+                            : g_strdup("source");
+        bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, BDRV_O_FLAGS,
+                                 true, quiet);
+        g_free(id);
         if (!bs[bs_i]) {
             error_report("Could not open '%s'", argv[optind + bs_i]);
             ret = -1;
@@ -1416,7 +1435,7 @@ static int img_convert(int argc, char **argv)
         return -1;
     }
 
-    out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
+    out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
     if (!out_bs) {
         ret = -1;
         goto out;
@@ -1799,8 +1818,8 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         }
         g_hash_table_insert(filenames, (gpointer)filename, NULL);
 
-        bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
-                           false, false);
+        bs = bdrv_new_open("image", filename, fmt,
+                           BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
         if (!bs) {
             goto err;
         }
@@ -1882,7 +1901,7 @@ static int img_info(int argc, char **argv)
         }
     }
     if (optind != argc - 1) {
-        help();
+        error_exit("Expecting one image file name");
     }
     filename = argv[optind++];
 
@@ -2046,10 +2065,10 @@ static int img_map(int argc, char **argv)
             break;
         }
     }
-    if (optind >= argc) {
-        help();
+    if (optind != argc - 1) {
+        error_exit("Expecting one image file name");
     }
-    filename = argv[optind++];
+    filename = argv[optind];
 
     if (output && !strcmp(output, "json")) {
         output_format = OFORMAT_JSON;
@@ -2060,7 +2079,7 @@ static int img_map(int argc, char **argv)
         return 1;
     }
 
-    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS, true, false);
+    bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
     if (!bs) {
         return 1;
     }
@@ -2138,7 +2157,7 @@ static int img_snapshot(int argc, char **argv)
             return 0;
         case 'l':
             if (action) {
-                help();
+                error_exit("Cannot mix '-l', '-a', '-c', '-d'");
                 return 0;
             }
             action = SNAPSHOT_LIST;
@@ -2146,7 +2165,7 @@ static int img_snapshot(int argc, char **argv)
             break;
         case 'a':
             if (action) {
-                help();
+                error_exit("Cannot mix '-l', '-a', '-c', '-d'");
                 return 0;
             }
             action = SNAPSHOT_APPLY;
@@ -2154,7 +2173,7 @@ static int img_snapshot(int argc, char **argv)
             break;
         case 'c':
             if (action) {
-                help();
+                error_exit("Cannot mix '-l', '-a', '-c', '-d'");
                 return 0;
             }
             action = SNAPSHOT_CREATE;
@@ -2162,7 +2181,7 @@ static int img_snapshot(int argc, char **argv)
             break;
         case 'd':
             if (action) {
-                help();
+                error_exit("Cannot mix '-l', '-a', '-c', '-d'");
                 return 0;
             }
             action = SNAPSHOT_DELETE;
@@ -2175,12 +2194,12 @@ static int img_snapshot(int argc, char **argv)
     }
 
     if (optind != argc - 1) {
-        help();
+        error_exit("Expecting one image file name");
     }
     filename = argv[optind++];
 
     /* Open the image */
-    bs = bdrv_new_open(filename, NULL, bdrv_oflags, true, quiet);
+    bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
     if (!bs) {
         return 1;
     }
@@ -2288,8 +2307,11 @@ static int img_rebase(int argc, char **argv)
         progress = 0;
     }
 
-    if ((optind != argc - 1) || (!unsafe && !out_baseimg)) {
-        help();
+    if (optind != argc - 1) {
+        error_exit("Expecting one image file name");
+    }
+    if (!unsafe && !out_baseimg) {
+        error_exit("Must specify backing file (-b) or use unsafe mode (-u)");
     }
     filename = argv[optind++];
 
@@ -2309,7 +2331,7 @@ static int img_rebase(int argc, char **argv)
      * Ignore the old backing file for unsafe rebase in case we want to correct
      * the reference to a renamed or moved backing file.
      */
-    bs = bdrv_new_open(filename, fmt, flags, true, quiet);
+    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         return 1;
     }
@@ -2344,7 +2366,7 @@ static int img_rebase(int argc, char **argv)
     } else {
         char backing_name[1024];
 
-        bs_old_backing = bdrv_new("old_backing");
+        bs_old_backing = bdrv_new("old_backing", &error_abort);
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
         ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, BDRV_O_FLAGS,
                         old_backing_drv, &local_err);
@@ -2355,7 +2377,7 @@ static int img_rebase(int argc, char **argv)
             goto out;
         }
         if (out_baseimg[0]) {
-            bs_new_backing = bdrv_new("new_backing");
+            bs_new_backing = bdrv_new("new_backing", &error_abort);
             ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL,
                             BDRV_O_FLAGS, new_backing_drv, &local_err);
             if (ret) {
@@ -2549,7 +2571,7 @@ static int img_resize(int argc, char **argv)
     /* Remove size from argv manually so that negative numbers are not treated
      * as options by getopt. */
     if (argc < 3) {
-        help();
+        error_exit("Not enough arguments");
         return 1;
     }
 
@@ -2576,7 +2598,7 @@ static int img_resize(int argc, char **argv)
         }
     }
     if (optind != argc - 1) {
-        help();
+        error_exit("Expecting one image file name");
     }
     filename = argv[optind++];
 
@@ -2606,7 +2628,8 @@ static int img_resize(int argc, char **argv)
     n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
     qemu_opts_del(param);
 
-    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
+    bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
+                       true, quiet);
     if (!bs) {
         ret = -1;
         goto out;
@@ -2692,7 +2715,7 @@ static int img_amend(int argc, char **argv)
     }
 
     if (!options) {
-        help();
+        error_exit("Must specify options (-o)");
     }
 
     filename = (optind == argc - 1) ? argv[argc - 1] : NULL;
@@ -2704,10 +2727,11 @@ static int img_amend(int argc, char **argv)
     }
 
     if (optind != argc - 1) {
-        help();
+        error_exit("Expecting one image file name");
     }
 
-    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
+    bs = bdrv_new_open("image", filename, fmt,
+                       BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
     if (!bs) {
         error_report("Could not open image '%s'", filename);
         ret = -1;
@@ -2775,8 +2799,9 @@ int main(int argc, char **argv)
 
     qemu_init_main_loop();
     bdrv_init();
-    if (argc < 2)
-        help();
+    if (argc < 2) {
+        error_exit("Not enough arguments");
+    }
     cmdname = argv[1];
     argc--; argv++;
 
@@ -2788,6 +2813,5 @@ int main(int argc, char **argv)
     }
 
     /* not found */
-    help();
-    return 0;
+    error_exit("Command not found: %s", cmdname);
 }
diff --git a/qemu-io.c b/qemu-io.c
index 5d7b53f756..9fcd72bb10 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -67,7 +67,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
             return 1;
         }
     } else {
-        qemuio_bs = bdrv_new("hda");
+        qemuio_bs = bdrv_new("hda", &error_abort);
 
         if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err)
             < 0)
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 899e67cfd7..eed79fa15e 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -657,7 +657,8 @@ int main(int argc, char **argv)
         drv = NULL;
     }
 
-    bs = bdrv_new("hda");
+    bs = bdrv_new("hda", &error_abort);
+
     srcpath = argv[optind];
     ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
     if (ret < 0) {
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index fad3575549..ee731555d3 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -820,3 +820,10 @@ uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
     fr = int64_to_float64(a, &FP_STATUS);
     return float64_to_g(fr);
 }
+
+void helper_fcvtql_v_input(CPUAlphaState *env, uint64_t val)
+{
+    if (val != (int32_t)val) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 4f127c49c5..2389e96ea3 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -96,6 +96,7 @@ DEF_HELPER_FLAGS_3(fp_exc_raise_s, TCG_CALL_NO_WG, void, env, i32, i32)
 
 DEF_HELPER_FLAGS_2(ieee_input, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
+DEF_HELPER_FLAGS_2(fcvtql_v_input, TCG_CALL_NO_WG, void, env, i64)
 
 #if !defined (CONFIG_USER_ONLY)
 DEF_HELPER_2(hw_ret, void, env, i64)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index e7e319b31d..d0357ff114 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -49,6 +49,12 @@ struct DisasContext {
     /* implver value for this CPU.  */
     int implver;
 
+    /* Temporaries for $31 and $f31 as source and destination.  */
+    TCGv zero;
+    TCGv sink;
+    /* Temporary for immediate constants.  */
+    TCGv lit;
+
     bool singlestep_enabled;
 };
 
@@ -83,64 +89,128 @@ static TCGv cpu_pc;
 static TCGv cpu_lock_addr;
 static TCGv cpu_lock_st_addr;
 static TCGv cpu_lock_value;
-static TCGv cpu_unique;
-#ifndef CONFIG_USER_ONLY
-static TCGv cpu_sysval;
-static TCGv cpu_usp;
-#endif
-
-/* register names */
-static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
 
 #include "exec/gen-icount.h"
 
 void alpha_translate_init(void)
 {
+#define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
+
+    typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
+    static const GlobalVar vars[] = {
+        DEF_VAR(pc),
+        DEF_VAR(lock_addr),
+        DEF_VAR(lock_st_addr),
+        DEF_VAR(lock_value),
+    };
+
+#undef DEF_VAR
+
+    /* Use the symbolic register names that match the disassembler.  */
+    static const char greg_names[31][4] = {
+        "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
+        "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
+        "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
+        "t10", "t11", "ra", "t12", "at", "gp", "sp"
+    };
+    static const char freg_names[31][4] = {
+        "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+        "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+        "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+        "f24", "f25", "f26", "f27", "f28", "f29", "f30"
+    };
+
+    static bool done_init = 0;
     int i;
-    char *p;
-    static int done_init = 0;
 
-    if (done_init)
+    if (done_init) {
         return;
+    }
+    done_init = 1;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 
-    p = cpu_reg_names;
     for (i = 0; i < 31; i++) {
-        sprintf(p, "ir%d", i);
         cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                           offsetof(CPUAlphaState, ir[i]), p);
-        p += (i < 10) ? 4 : 5;
+                                           offsetof(CPUAlphaState, ir[i]),
+                                           greg_names[i]);
+    }
 
-        sprintf(p, "fir%d", i);
+    for (i = 0; i < 31; i++) {
         cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                            offsetof(CPUAlphaState, fir[i]), p);
-        p += (i < 10) ? 5 : 6;
+                                            offsetof(CPUAlphaState, fir[i]),
+                                            freg_names[i]);
     }
 
-    cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
-                                    offsetof(CPUAlphaState, pc), "pc");
-
-    cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
-					   offsetof(CPUAlphaState, lock_addr),
-					   "lock_addr");
-    cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
-					      offsetof(CPUAlphaState, lock_st_addr),
-					      "lock_st_addr");
-    cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
-					    offsetof(CPUAlphaState, lock_value),
-					    "lock_value");
-
-    cpu_unique = tcg_global_mem_new_i64(TCG_AREG0,
-                                        offsetof(CPUAlphaState, unique), "unique");
-#ifndef CONFIG_USER_ONLY
-    cpu_sysval = tcg_global_mem_new_i64(TCG_AREG0,
-                                        offsetof(CPUAlphaState, sysval), "sysval");
-    cpu_usp = tcg_global_mem_new_i64(TCG_AREG0,
-                                     offsetof(CPUAlphaState, usp), "usp");
-#endif
+    for (i = 0; i < ARRAY_SIZE(vars); ++i) {
+        const GlobalVar *v = &vars[i];
+        *v->var = tcg_global_mem_new_i64(TCG_AREG0, v->ofs, v->name);
+    }
+}
 
-    done_init = 1;
+static TCGv load_zero(DisasContext *ctx)
+{
+    if (TCGV_IS_UNUSED_I64(ctx->zero)) {
+        ctx->zero = tcg_const_i64(0);
+    }
+    return ctx->zero;
+}
+
+static TCGv dest_sink(DisasContext *ctx)
+{
+    if (TCGV_IS_UNUSED_I64(ctx->sink)) {
+        ctx->sink = tcg_temp_new();
+    }
+    return ctx->sink;
+}
+
+static TCGv load_gpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_ir[reg];
+    } else {
+        return load_zero(ctx);
+    }
+}
+
+static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
+                         uint8_t lit, bool islit)
+{
+    if (islit) {
+        ctx->lit = tcg_const_i64(lit);
+        return ctx->lit;
+    } else if (likely(reg < 31)) {
+        return cpu_ir[reg];
+    } else {
+        return load_zero(ctx);
+    }
+}
+
+static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_ir[reg];
+    } else {
+        return dest_sink(ctx);
+    }
+}
+
+static TCGv load_fpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_fir[reg];
+    } else {
+        return load_zero(ctx);
+    }
+}
+
+static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
+{
+    if (likely(reg < 31)) {
+        return cpu_fir[reg];
+    } else {
+        return dest_sink(ctx);
+    }
 }
 
 static void gen_excp_1(int exception, int error_code)
@@ -207,10 +277,10 @@ static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
 static inline void gen_load_mem(DisasContext *ctx,
                                 void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
                                                           int flags),
-                                int ra, int rb, int32_t disp16, int fp,
-                                int clear)
+                                int ra, int rb, int32_t disp16, bool fp,
+                                bool clear)
 {
-    TCGv addr, va;
+    TCGv tmp, addr, va;
 
     /* LDQ_U with ra $31 is UNOP.  Other various loads are forms of
        prefetches, which we can treat as nops.  No worries about
@@ -219,23 +289,22 @@ static inline void gen_load_mem(DisasContext *ctx,
         return;
     }
 
-    addr = tcg_temp_new();
-    if (rb != 31) {
-        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-        if (clear) {
-            tcg_gen_andi_i64(addr, addr, ~0x7);
-        }
-    } else {
-        if (clear) {
-            disp16 &= ~0x7;
-        }
-        tcg_gen_movi_i64(addr, disp16);
+    tmp = tcg_temp_new();
+    addr = load_gpr(ctx, rb);
+
+    if (disp16) {
+        tcg_gen_addi_i64(tmp, addr, disp16);
+        addr = tmp;
+    }
+    if (clear) {
+        tcg_gen_andi_i64(tmp, addr, ~0x7);
+        addr = tmp;
     }
 
     va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
     tcg_gen_qemu_load(va, addr, ctx->mem_idx);
 
-    tcg_temp_free(addr);
+    tcg_temp_free(tmp);
 }
 
 static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
@@ -265,35 +334,27 @@ static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
 static inline void gen_store_mem(DisasContext *ctx,
                                  void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
                                                             int flags),
-                                 int ra, int rb, int32_t disp16, int fp,
-                                 int clear)
+                                 int ra, int rb, int32_t disp16, bool fp,
+                                 bool clear)
 {
-    TCGv addr, va;
+    TCGv tmp, addr, va;
 
-    addr = tcg_temp_new();
-    if (rb != 31) {
-        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-        if (clear) {
-            tcg_gen_andi_i64(addr, addr, ~0x7);
-        }
-    } else {
-        if (clear) {
-            disp16 &= ~0x7;
-        }
-        tcg_gen_movi_i64(addr, disp16);
-    }
+    tmp = tcg_temp_new();
+    addr = load_gpr(ctx, rb);
 
-    if (ra == 31) {
-        va = tcg_const_i64(0);
-    } else {
-        va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
+    if (disp16) {
+        tcg_gen_addi_i64(tmp, addr, disp16);
+        addr = tmp;
     }
+    if (clear) {
+        tcg_gen_andi_i64(tmp, addr, ~0x7);
+        addr = tmp;
+    }
+
+    va = (fp ? load_fpr(ctx, ra) : load_gpr(ctx, ra));
     tcg_gen_qemu_store(va, addr, ctx->mem_idx);
 
-    tcg_temp_free(addr);
-    if (ra == 31) {
-        tcg_temp_free(va);
-    }
+    tcg_temp_free(tmp);
 }
 
 static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
@@ -313,11 +374,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
     addr = tcg_temp_local_new();
 #endif
 
-    if (rb != 31) {
-        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-    } else {
-        tcg_gen_movi_i64(addr, disp16);
-    }
+    tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
 
 #if defined(CONFIG_USER_ONLY)
     /* ??? This is handled via a complicated version of compare-and-swap
@@ -367,7 +424,8 @@ static bool in_superpage(DisasContext *ctx, int64_t addr)
 static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
 {
     /* Suppress goto_tb in the case of single-steping and IO.  */
-    if (ctx->singlestep_enabled || (ctx->tb->cflags & CF_LAST_IO)) {
+    if ((ctx->tb->cflags & CF_LAST_IO)
+        || ctx->singlestep_enabled || singlestep) {
         return false;
     }
     /* If the destination is in the superpage, the page perms can't change.  */
@@ -438,15 +496,11 @@ static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
 {
     TCGv cmp_tmp;
 
-    if (unlikely(ra == 31)) {
-        cmp_tmp = tcg_const_i64(0);
-    } else {
+    if (mask) {
         cmp_tmp = tcg_temp_new();
-        if (mask) {
-            tcg_gen_andi_i64(cmp_tmp, cpu_ir[ra], 1);
-        } else {
-            tcg_gen_mov_i64(cmp_tmp, cpu_ir[ra]);
-        }
+        tcg_gen_andi_i64(cmp_tmp, load_gpr(ctx, ra), 1);
+    } else {
+        cmp_tmp = load_gpr(ctx, ra);
     }
 
     return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
@@ -487,83 +541,23 @@ static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
 static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
                              int32_t disp)
 {
-    TCGv cmp_tmp;
-
-    if (unlikely(ra == 31)) {
-        /* Very uncommon case, but easier to optimize it to an integer
-           comparison than continuing with the floating point comparison.  */
-        return gen_bcond(ctx, cond, ra, disp, 0);
-    }
-
-    cmp_tmp = tcg_temp_new();
-    gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
+    TCGv cmp_tmp = tcg_temp_new();
+    gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
     return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
 }
 
-static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
-                     int islit, uint8_t lit, int mask)
-{
-    TCGv_i64 c1, z, v1;
-
-    if (unlikely(rc == 31)) {
-        return;
-    }
-
-    if (ra == 31) {
-        /* Very uncommon case - Do not bother to optimize.  */
-        c1 = tcg_const_i64(0);
-    } else if (mask) {
-        c1 = tcg_const_i64(1);
-        tcg_gen_and_i64(c1, c1, cpu_ir[ra]);
-    } else {
-        c1 = cpu_ir[ra];
-    }
-    if (islit) {
-        v1 = tcg_const_i64(lit);
-    } else {
-        v1 = cpu_ir[rb];
-    }
-    z = tcg_const_i64(0);
-
-    tcg_gen_movcond_i64(cond, cpu_ir[rc], c1, z, v1, cpu_ir[rc]);
-
-    tcg_temp_free_i64(z);
-    if (ra == 31 || mask) {
-        tcg_temp_free_i64(c1);
-    }
-    if (islit) {
-        tcg_temp_free_i64(v1);
-    }
-}
-
-static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
+static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
 {
-    TCGv_i64 c1, z, v1;
-
-    if (unlikely(rc == 31)) {
-        return;
-    }
+    TCGv_i64 va, vb, z;
 
-    c1 = tcg_temp_new_i64();
-    if (unlikely(ra == 31)) {
-        tcg_gen_movi_i64(c1, 0);
-    } else {
-        gen_fold_mzero(cond, c1, cpu_fir[ra]);
-    }
-    if (rb == 31) {
-        v1 = tcg_const_i64(0);
-    } else {
-        v1 = cpu_fir[rb];
-    }
-    z = tcg_const_i64(0);
+    z = load_zero(ctx);
+    vb = load_fpr(ctx, rb);
+    va = tcg_temp_new();
+    gen_fold_mzero(cond, va, load_fpr(ctx, ra));
 
-    tcg_gen_movcond_i64(cond, cpu_fir[rc], c1, z, v1, cpu_fir[rc]);
+    tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc));
 
-    tcg_temp_free_i64(z);
-    tcg_temp_free_i64(c1);
-    if (rb == 31) {
-        tcg_temp_free_i64(v1);
-    }
+    tcg_temp_free(va);
 }
 
 #define QUAL_RM_N       0x080   /* Round mode nearest even */
@@ -647,21 +641,21 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
     tcg_temp_free_i32(tmp);
 }
 
-static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
+static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
 {
     TCGv val;
-    if (reg == 31) {
-        val = tcg_const_i64(0);
+
+    if (unlikely(reg == 31)) {
+        val = load_zero(ctx);
     } else {
+        val = cpu_fir[reg];
         if ((fn11 & QUAL_S) == 0) {
             if (is_cmp) {
-                gen_helper_ieee_input_cmp(cpu_env, cpu_fir[reg]);
+                gen_helper_ieee_input_cmp(cpu_env, val);
             } else {
-                gen_helper_ieee_input(cpu_env, cpu_fir[reg]);
+                gen_helper_ieee_input(cpu_env, val);
             }
         }
-        val = tcg_temp_new();
-        tcg_gen_mov_i64(val, cpu_fir[reg]);
     }
     return val;
 }
@@ -721,105 +715,46 @@ static inline void gen_fp_exc_raise(int rc, int fn11)
     gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
 }
 
-static void gen_fcvtlq(int rb, int rc)
+static void gen_fcvtlq(TCGv vc, TCGv vb)
 {
-    if (unlikely(rc == 31)) {
-        return;
-    }
-    if (unlikely(rb == 31)) {
-        tcg_gen_movi_i64(cpu_fir[rc], 0);
-    } else {
-        TCGv tmp = tcg_temp_new();
+    TCGv tmp = tcg_temp_new();
 
-        /* The arithmetic right shift here, plus the sign-extended mask below
-           yields a sign-extended result without an explicit ext32s_i64.  */
-        tcg_gen_sari_i64(tmp, cpu_fir[rb], 32);
-        tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
-        tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
-        tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff);
-        tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
+    /* The arithmetic right shift here, plus the sign-extended mask below
+       yields a sign-extended result without an explicit ext32s_i64.  */
+    tcg_gen_sari_i64(tmp, vb, 32);
+    tcg_gen_shri_i64(vc, vb, 29);
+    tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
+    tcg_gen_andi_i64(vc, vc, 0x3fffffff);
+    tcg_gen_or_i64(vc, vc, tmp);
 
-        tcg_temp_free(tmp);
-    }
+    tcg_temp_free(tmp);
 }
 
-static void gen_fcvtql(int rb, int rc)
+static void gen_fcvtql(TCGv vc, TCGv vb)
 {
-    if (unlikely(rc == 31)) {
-        return;
-    }
-    if (unlikely(rb == 31)) {
-        tcg_gen_movi_i64(cpu_fir[rc], 0);
-    } else {
-        TCGv tmp = tcg_temp_new();
+    TCGv tmp = tcg_temp_new();
 
-        tcg_gen_andi_i64(tmp, cpu_fir[rb], 0xC0000000);
-        tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rb], 0x3FFFFFFF);
-        tcg_gen_shli_i64(tmp, tmp, 32);
-        tcg_gen_shli_i64(cpu_fir[rc], cpu_fir[rc], 29);
-        tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
+    tcg_gen_andi_i64(tmp, vb, (int32_t)0xc0000000);
+    tcg_gen_andi_i64(vc, vb, 0x3FFFFFFF);
+    tcg_gen_shli_i64(tmp, tmp, 32);
+    tcg_gen_shli_i64(vc, vc, 29);
+    tcg_gen_or_i64(vc, vc, tmp);
 
-        tcg_temp_free(tmp);
-    }
+    tcg_temp_free(tmp);
 }
 
-static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
-{
-    if (rb != 31) {
-        int lab = gen_new_label();
-        TCGv tmp = tcg_temp_new();
-
-        tcg_gen_ext32s_i64(tmp, cpu_fir[rb]);
-        tcg_gen_brcond_i64(TCG_COND_EQ, tmp, cpu_fir[rb], lab);
-        gen_excp(ctx, EXCP_ARITH, EXC_M_IOV);
-
-        gen_set_label(lab);
-    }
-    gen_fcvtql(rb, rc);
-}
-
-#define FARITH2(name)                                                   \
-    static inline void glue(gen_f, name)(int rb, int rc)                \
-    {                                                                   \
-        if (unlikely(rc == 31)) {                                       \
-            return;                                                     \
-        }                                                               \
-        if (rb != 31) {                                                 \
-            gen_helper_ ## name(cpu_fir[rc], cpu_env, cpu_fir[rb]);     \
-        } else {                                                        \
-            TCGv tmp = tcg_const_i64(0);                                \
-            gen_helper_ ## name(cpu_fir[rc], cpu_env, tmp);             \
-            tcg_temp_free(tmp);                                         \
-        }                                                               \
-    }
-
-/* ??? VAX instruction qualifiers ignored.  */
-FARITH2(sqrtf)
-FARITH2(sqrtg)
-FARITH2(cvtgf)
-FARITH2(cvtgq)
-FARITH2(cvtqf)
-FARITH2(cvtqg)
-
 static void gen_ieee_arith2(DisasContext *ctx,
                             void (*helper)(TCGv, TCGv_ptr, TCGv),
                             int rb, int rc, int fn11)
 {
     TCGv vb;
 
-    /* ??? This is wrong: the instruction is not a nop, it still may
-       raise exceptions.  */
-    if (unlikely(rc == 31)) {
-        return;
-    }
-
     gen_qual_roundmode(ctx, fn11);
     gen_qual_flushzero(ctx, fn11);
     gen_fp_exc_clear();
 
-    vb = gen_ieee_input(rb, fn11, 0);
-    helper(cpu_fir[rc], cpu_env, vb);
-    tcg_temp_free(vb);
+    vb = gen_ieee_input(ctx, rb, fn11, 0);
+    helper(dest_fpr(ctx, rc), cpu_env, vb);
 
     gen_fp_exc_raise(rc, fn11);
 }
@@ -837,40 +772,34 @@ IEEE_ARITH2(cvtts)
 
 static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
 {
-    TCGv vb;
+    TCGv vb, vc;
     int ignore = 0;
 
-    /* ??? This is wrong: the instruction is not a nop, it still may
-       raise exceptions.  */
-    if (unlikely(rc == 31)) {
-        return;
-    }
-
     /* No need to set flushzero, since we have an integer output.  */
     gen_fp_exc_clear();
-    vb = gen_ieee_input(rb, fn11, 0);
+    vb = gen_ieee_input(ctx, rb, fn11, 0);
+    vc = dest_fpr(ctx, rc);
 
     /* Almost all integer conversions use cropped rounding, and most
        also do not have integer overflow enabled.  Special case that.  */
     switch (fn11) {
     case QUAL_RM_C:
-        gen_helper_cvttq_c(cpu_fir[rc], cpu_env, vb);
+        gen_helper_cvttq_c(vc, cpu_env, vb);
         break;
     case QUAL_V | QUAL_RM_C:
     case QUAL_S | QUAL_V | QUAL_RM_C:
         ignore = float_flag_inexact;
         /* FALLTHRU */
     case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
-        gen_helper_cvttq_svic(cpu_fir[rc], cpu_env, vb);
+        gen_helper_cvttq_svic(vc, cpu_env, vb);
         break;
     default:
         gen_qual_roundmode(ctx, fn11);
-        gen_helper_cvttq(cpu_fir[rc], cpu_env, vb);
+        gen_helper_cvttq(vc, cpu_env, vb);
         ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
         ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
         break;
     }
-    tcg_temp_free(vb);
 
     gen_fp_exc_raise_ignore(rc, fn11, ignore);
 }
@@ -879,35 +808,21 @@ static void gen_ieee_intcvt(DisasContext *ctx,
                             void (*helper)(TCGv, TCGv_ptr, TCGv),
 			    int rb, int rc, int fn11)
 {
-    TCGv vb;
-
-    /* ??? This is wrong: the instruction is not a nop, it still may
-       raise exceptions.  */
-    if (unlikely(rc == 31)) {
-        return;
-    }
+    TCGv vb, vc;
 
     gen_qual_roundmode(ctx, fn11);
-
-    if (rb == 31) {
-        vb = tcg_const_i64(0);
-    } else {
-        vb = cpu_fir[rb];
-    }
+    vb = load_fpr(ctx, rb);
+    vc = dest_fpr(ctx, rc);
 
     /* The only exception that can be raised by integer conversion
        is inexact.  Thus we only need to worry about exceptions when
        inexact handling is requested.  */
     if (fn11 & QUAL_I) {
         gen_fp_exc_clear();
-        helper(cpu_fir[rc], cpu_env, vb);
+        helper(vc, cpu_env, vb);
         gen_fp_exc_raise(rc, fn11);
     } else {
-        helper(cpu_fir[rc], cpu_env, vb);
-    }
-
-    if (rb == 31) {
-        tcg_temp_free(vb);
+        helper(vc, cpu_env, vb);
     }
 }
 
@@ -920,144 +835,38 @@ static inline void glue(gen_f, name)(DisasContext *ctx,         \
 IEEE_INTCVT(cvtqs)
 IEEE_INTCVT(cvtqt)
 
-static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
+static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
 {
-    TCGv va, vb, vmask;
-    int za = 0, zb = 0;
-
-    if (unlikely(rc == 31)) {
-        return;
-    }
-
-    vmask = tcg_const_i64(mask);
-
-    TCGV_UNUSED_I64(va);
-    if (ra == 31) {
-        if (inv_a) {
-            va = vmask;
-        } else {
-            za = 1;
-        }
-    } else {
-        va = tcg_temp_new_i64();
-        tcg_gen_mov_i64(va, cpu_fir[ra]);
-        if (inv_a) {
-            tcg_gen_andc_i64(va, vmask, va);
-        } else {
-            tcg_gen_and_i64(va, va, vmask);
-        }
-    }
+    TCGv vmask = tcg_const_i64(mask);
+    TCGv tmp = tcg_temp_new_i64();
 
-    TCGV_UNUSED_I64(vb);
-    if (rb == 31) {
-        zb = 1;
+    if (inv_a) {
+        tcg_gen_andc_i64(tmp, vmask, va);
     } else {
-        vb = tcg_temp_new_i64();
-        tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
+        tcg_gen_and_i64(tmp, va, vmask);
     }
 
-    switch (za << 1 | zb) {
-    case 0 | 0:
-        tcg_gen_or_i64(cpu_fir[rc], va, vb);
-        break;
-    case 0 | 1:
-        tcg_gen_mov_i64(cpu_fir[rc], va);
-        break;
-    case 2 | 0:
-        tcg_gen_mov_i64(cpu_fir[rc], vb);
-        break;
-    case 2 | 1:
-        tcg_gen_movi_i64(cpu_fir[rc], 0);
-        break;
-    }
+    tcg_gen_andc_i64(vc, vb, vmask);
+    tcg_gen_or_i64(vc, vc, tmp);
 
     tcg_temp_free(vmask);
-    if (ra != 31) {
-        tcg_temp_free(va);
-    }
-    if (rb != 31) {
-        tcg_temp_free(vb);
-    }
-}
-
-static inline void gen_fcpys(int ra, int rb, int rc)
-{
-    gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
-}
-
-static inline void gen_fcpysn(int ra, int rb, int rc)
-{
-    gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
+    tcg_temp_free(tmp);
 }
 
-static inline void gen_fcpyse(int ra, int rb, int rc)
-{
-    gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
-}
-
-#define FARITH3(name)                                                   \
-    static inline void glue(gen_f, name)(int ra, int rb, int rc)        \
-    {                                                                   \
-        TCGv va, vb;                                                    \
-                                                                        \
-        if (unlikely(rc == 31)) {                                       \
-            return;                                                     \
-        }                                                               \
-        if (ra == 31) {                                                 \
-            va = tcg_const_i64(0);                                      \
-        } else {                                                        \
-            va = cpu_fir[ra];                                           \
-        }                                                               \
-        if (rb == 31) {                                                 \
-            vb = tcg_const_i64(0);                                      \
-        } else {                                                        \
-            vb = cpu_fir[rb];                                           \
-        }                                                               \
-                                                                        \
-        gen_helper_ ## name(cpu_fir[rc], cpu_env, va, vb);              \
-                                                                        \
-        if (ra == 31) {                                                 \
-            tcg_temp_free(va);                                          \
-        }                                                               \
-        if (rb == 31) {                                                 \
-            tcg_temp_free(vb);                                          \
-        }                                                               \
-    }
-
-/* ??? VAX instruction qualifiers ignored.  */
-FARITH3(addf)
-FARITH3(subf)
-FARITH3(mulf)
-FARITH3(divf)
-FARITH3(addg)
-FARITH3(subg)
-FARITH3(mulg)
-FARITH3(divg)
-FARITH3(cmpgeq)
-FARITH3(cmpglt)
-FARITH3(cmpgle)
-
 static void gen_ieee_arith3(DisasContext *ctx,
                             void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
                             int ra, int rb, int rc, int fn11)
 {
-    TCGv va, vb;
-
-    /* ??? This is wrong: the instruction is not a nop, it still may
-       raise exceptions.  */
-    if (unlikely(rc == 31)) {
-        return;
-    }
+    TCGv va, vb, vc;
 
     gen_qual_roundmode(ctx, fn11);
     gen_qual_flushzero(ctx, fn11);
     gen_fp_exc_clear();
 
-    va = gen_ieee_input(ra, fn11, 0);
-    vb = gen_ieee_input(rb, fn11, 0);
-    helper(cpu_fir[rc], cpu_env, va, vb);
-    tcg_temp_free(va);
-    tcg_temp_free(vb);
+    va = gen_ieee_input(ctx, ra, fn11, 0);
+    vb = gen_ieee_input(ctx, rb, fn11, 0);
+    vc = dest_fpr(ctx, rc);
+    helper(vc, cpu_env, va, vb);
 
     gen_fp_exc_raise(rc, fn11);
 }
@@ -1081,21 +890,14 @@ static void gen_ieee_compare(DisasContext *ctx,
                              void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
                              int ra, int rb, int rc, int fn11)
 {
-    TCGv va, vb;
-
-    /* ??? This is wrong: the instruction is not a nop, it still may
-       raise exceptions.  */
-    if (unlikely(rc == 31)) {
-        return;
-    }
+    TCGv va, vb, vc;
 
     gen_fp_exc_clear();
 
-    va = gen_ieee_input(ra, fn11, 1);
-    vb = gen_ieee_input(rb, fn11, 1);
-    helper(cpu_fir[rc], cpu_env, va, vb);
-    tcg_temp_free(va);
-    tcg_temp_free(vb);
+    va = gen_ieee_input(ctx, ra, fn11, 1);
+    vb = gen_ieee_input(ctx, rb, fn11, 1);
+    vc = dest_fpr(ctx, rc);
+    helper(vc, cpu_env, va, vb);
 
     gen_fp_exc_raise(rc, fn11);
 }
@@ -1117,8 +919,9 @@ static inline uint64_t zapnot_mask(uint8_t lit)
     int i;
 
     for (i = 0; i < 8; ++i) {
-        if ((lit >> i) & 1)
+        if ((lit >> i) & 1) {
             mask |= 0xffull << (i * 8);
+        }
     }
     return mask;
 }
@@ -1145,165 +948,111 @@ static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
         tcg_gen_mov_i64(dest, src);
         break;
     default:
-        tcg_gen_andi_i64 (dest, src, zapnot_mask (lit));
+        tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
         break;
     }
 }
 
-static inline void gen_zapnot(int ra, int rb, int rc, int islit, uint8_t lit)
-{
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit)
-        gen_zapnoti(cpu_ir[rc], cpu_ir[ra], lit);
-    else
-        gen_helper_zapnot (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-}
-
-static inline void gen_zap(int ra, int rb, int rc, int islit, uint8_t lit)
-{
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit)
-        gen_zapnoti(cpu_ir[rc], cpu_ir[ra], ~lit);
-    else
-        gen_helper_zap (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-}
-
-
 /* EXTWH, EXTLH, EXTQH */
-static void gen_ext_h(int ra, int rb, int rc, int islit,
+static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        if (islit) {
-            lit = (64 - (lit & 7) * 8) & 0x3f;
-            tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit);
-        } else {
-            TCGv tmp1 = tcg_temp_new();
-            tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(tmp1, tmp1, 3);
-            tcg_gen_neg_i64(tmp1, tmp1);
-            tcg_gen_andi_i64(tmp1, tmp1, 0x3f);
-            tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
-            tcg_temp_free(tmp1);
-        }
-        gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
+    if (islit) {
+        tcg_gen_shli_i64(vc, va, (64 - lit * 8) & 0x3f);
+    } else {
+        TCGv tmp = tcg_temp_new();
+        tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
+        tcg_gen_neg_i64(tmp, tmp);
+        tcg_gen_andi_i64(tmp, tmp, 0x3f);
+        tcg_gen_shl_i64(vc, va, tmp);
+        tcg_temp_free(tmp);
     }
+    gen_zapnoti(vc, vc, byte_mask);
 }
 
 /* EXTBL, EXTWL, EXTLL, EXTQL */
-static void gen_ext_l(int ra, int rb, int rc, int islit,
+static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        if (islit) {
-            tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], (lit & 7) * 8);
-        } else {
-            TCGv tmp = tcg_temp_new();
-            tcg_gen_andi_i64(tmp, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(tmp, tmp, 3);
-            tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], tmp);
-            tcg_temp_free(tmp);
-        }
-        gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
+    if (islit) {
+        tcg_gen_shri_i64(vc, va, (lit & 7) * 8);
+    } else {
+        TCGv tmp = tcg_temp_new();
+        tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
+        tcg_gen_shli_i64(tmp, tmp, 3);
+        tcg_gen_shr_i64(vc, va, tmp);
+        tcg_temp_free(tmp);
     }
+    gen_zapnoti(vc, vc, byte_mask);
 }
 
 /* INSWH, INSLH, INSQH */
-static void gen_ins_h(int ra, int rb, int rc, int islit,
+static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31) || (islit && (lit & 7) == 0))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        TCGv tmp = tcg_temp_new();
+    TCGv tmp = tcg_temp_new();
 
-        /* The instruction description has us left-shift the byte mask
-           and extract bits <15:8> and apply that zap at the end.  This
-           is equivalent to simply performing the zap first and shifting
-           afterward.  */
-        gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
+    /* The instruction description has us left-shift the byte mask and extract
+       bits <15:8> and apply that zap at the end.  This is equivalent to simply
+       performing the zap first and shifting afterward.  */
+    gen_zapnoti(tmp, va, byte_mask);
 
-        if (islit) {
-            /* Note that we have handled the lit==0 case above.  */
-            tcg_gen_shri_i64 (cpu_ir[rc], tmp, 64 - (lit & 7) * 8);
+    if (islit) {
+        lit &= 7;
+        if (unlikely(lit == 0)) {
+            tcg_gen_movi_i64(vc, 0);
         } else {
-            TCGv shift = tcg_temp_new();
-
-            /* If (B & 7) == 0, we need to shift by 64 and leave a zero.
-               Do this portably by splitting the shift into two parts:
-               shift_count-1 and 1.  Arrange for the -1 by using
-               ones-complement instead of twos-complement in the negation:
-               ~((B & 7) * 8) & 63.  */
-
-            tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(shift, shift, 3);
-            tcg_gen_not_i64(shift, shift);
-            tcg_gen_andi_i64(shift, shift, 0x3f);
-
-            tcg_gen_shr_i64(cpu_ir[rc], tmp, shift);
-            tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[rc], 1);
-            tcg_temp_free(shift);
+            tcg_gen_shri_i64(vc, tmp, 64 - lit * 8);
         }
-        tcg_temp_free(tmp);
+    } else {
+        TCGv shift = tcg_temp_new();
+
+        /* If (B & 7) == 0, we need to shift by 64 and leave a zero.  Do this
+           portably by splitting the shift into two parts: shift_count-1 and 1.
+           Arrange for the -1 by using ones-complement instead of
+           twos-complement in the negation: ~(B * 8) & 63.  */
+
+        tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
+        tcg_gen_not_i64(shift, shift);
+        tcg_gen_andi_i64(shift, shift, 0x3f);
+
+        tcg_gen_shr_i64(vc, tmp, shift);
+        tcg_gen_shri_i64(vc, vc, 1);
+        tcg_temp_free(shift);
     }
+    tcg_temp_free(tmp);
 }
 
 /* INSBL, INSWL, INSLL, INSQL */
-static void gen_ins_l(int ra, int rb, int rc, int islit,
+static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else {
-        TCGv tmp = tcg_temp_new();
+    TCGv tmp = tcg_temp_new();
 
-        /* The instruction description has us left-shift the byte mask
-           the same number of byte slots as the data and apply the zap
-           at the end.  This is equivalent to simply performing the zap
-           first and shifting afterward.  */
-        gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
+    /* The instruction description has us left-shift the byte mask
+       the same number of byte slots as the data and apply the zap
+       at the end.  This is equivalent to simply performing the zap
+       first and shifting afterward.  */
+    gen_zapnoti(tmp, va, byte_mask);
 
-        if (islit) {
-            tcg_gen_shli_i64(cpu_ir[rc], tmp, (lit & 7) * 8);
-        } else {
-            TCGv shift = tcg_temp_new();
-            tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
-            tcg_gen_shli_i64(shift, shift, 3);
-            tcg_gen_shl_i64(cpu_ir[rc], tmp, shift);
-            tcg_temp_free(shift);
-        }
-        tcg_temp_free(tmp);
+    if (islit) {
+        tcg_gen_shli_i64(vc, tmp, (lit & 7) * 8);
+    } else {
+        TCGv shift = tcg_temp_new();
+        tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
+        tcg_gen_shli_i64(shift, shift, 3);
+        tcg_gen_shl_i64(vc, tmp, shift);
+        tcg_temp_free(shift);
     }
+    tcg_temp_free(tmp);
 }
 
 /* MSKWH, MSKLH, MSKQH */
-static void gen_msk_h(int ra, int rb, int rc, int islit,
+static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit) {
-        gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~((byte_mask << (lit & 7)) >> 8));
+    if (islit) {
+        gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
     } else {
         TCGv shift = tcg_temp_new();
         TCGv mask = tcg_temp_new();
@@ -1315,17 +1064,16 @@ static void gen_msk_h(int ra, int rb, int rc, int islit,
            shift of 64 bits in order to generate a zero.  This is done by
            splitting the shift into two parts, the variable shift - 1
            followed by a constant 1 shift.  The code we expand below is
-           equivalent to ~((B & 7) * 8) & 63.  */
+           equivalent to ~(B * 8) & 63.  */
 
-        tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
-        tcg_gen_shli_i64(shift, shift, 3);
+        tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
         tcg_gen_not_i64(shift, shift);
         tcg_gen_andi_i64(shift, shift, 0x3f);
         tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
         tcg_gen_shr_i64(mask, mask, shift);
         tcg_gen_shri_i64(mask, mask, 1);
 
-        tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
+        tcg_gen_andc_i64(vc, va, mask);
 
         tcg_temp_free(mask);
         tcg_temp_free(shift);
@@ -1333,150 +1081,27 @@ static void gen_msk_h(int ra, int rb, int rc, int islit,
 }
 
 /* MSKBL, MSKWL, MSKLL, MSKQL */
-static void gen_msk_l(int ra, int rb, int rc, int islit,
+static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
                       uint8_t lit, uint8_t byte_mask)
 {
-    if (unlikely(rc == 31))
-        return;
-    else if (unlikely(ra == 31))
-        tcg_gen_movi_i64(cpu_ir[rc], 0);
-    else if (islit) {
-        gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~(byte_mask << (lit & 7)));
+    if (islit) {
+        gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
     } else {
         TCGv shift = tcg_temp_new();
         TCGv mask = tcg_temp_new();
 
-        tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
+        tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
         tcg_gen_shli_i64(shift, shift, 3);
-        tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
+        tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
         tcg_gen_shl_i64(mask, mask, shift);
 
-        tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
+        tcg_gen_andc_i64(vc, va, mask);
 
         tcg_temp_free(mask);
         tcg_temp_free(shift);
     }
 }
 
-/* Code to call arith3 helpers */
-#define ARITH3(name)                                                  \
-static inline void glue(gen_, name)(int ra, int rb, int rc, int islit,\
-                                    uint8_t lit)                      \
-{                                                                     \
-    if (unlikely(rc == 31))                                           \
-        return;                                                       \
-                                                                      \
-    if (ra != 31) {                                                   \
-        if (islit) {                                                  \
-            TCGv tmp = tcg_const_i64(lit);                            \
-            gen_helper_ ## name(cpu_ir[rc], cpu_ir[ra], tmp);         \
-            tcg_temp_free(tmp);                                       \
-        } else                                                        \
-            gen_helper_ ## name (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); \
-    } else {                                                          \
-        TCGv tmp1 = tcg_const_i64(0);                                 \
-        if (islit) {                                                  \
-            TCGv tmp2 = tcg_const_i64(lit);                           \
-            gen_helper_ ## name (cpu_ir[rc], tmp1, tmp2);             \
-            tcg_temp_free(tmp2);                                      \
-        } else                                                        \
-            gen_helper_ ## name (cpu_ir[rc], tmp1, cpu_ir[rb]);       \
-        tcg_temp_free(tmp1);                                          \
-    }                                                                 \
-}
-ARITH3(cmpbge)
-ARITH3(minub8)
-ARITH3(minsb8)
-ARITH3(minuw4)
-ARITH3(minsw4)
-ARITH3(maxub8)
-ARITH3(maxsb8)
-ARITH3(maxuw4)
-ARITH3(maxsw4)
-ARITH3(perr)
-
-/* Code to call arith3 helpers */
-#define ARITH3_EX(name)                                                 \
-    static inline void glue(gen_, name)(int ra, int rb, int rc,         \
-                                        int islit, uint8_t lit)         \
-    {                                                                   \
-        if (unlikely(rc == 31)) {                                       \
-            return;                                                     \
-        }                                                               \
-        if (ra != 31) {                                                 \
-            if (islit) {                                                \
-                TCGv tmp = tcg_const_i64(lit);                          \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
-                                    cpu_ir[ra], tmp);                   \
-                tcg_temp_free(tmp);                                     \
-            } else {                                                    \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
-                                    cpu_ir[ra], cpu_ir[rb]);            \
-            }                                                           \
-        } else {                                                        \
-            TCGv tmp1 = tcg_const_i64(0);                               \
-            if (islit) {                                                \
-                TCGv tmp2 = tcg_const_i64(lit);                         \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, tmp2);   \
-                tcg_temp_free(tmp2);                                    \
-            } else {                                                    \
-                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, cpu_ir[rb]); \
-            }                                                           \
-            tcg_temp_free(tmp1);                                        \
-        }                                                               \
-    }
-ARITH3_EX(addlv)
-ARITH3_EX(sublv)
-ARITH3_EX(addqv)
-ARITH3_EX(subqv)
-ARITH3_EX(mullv)
-ARITH3_EX(mulqv)
-
-#define MVIOP2(name)                                    \
-static inline void glue(gen_, name)(int rb, int rc)     \
-{                                                       \
-    if (unlikely(rc == 31))                             \
-        return;                                         \
-    if (unlikely(rb == 31))                             \
-        tcg_gen_movi_i64(cpu_ir[rc], 0);                \
-    else                                                \
-        gen_helper_ ## name (cpu_ir[rc], cpu_ir[rb]);   \
-}
-MVIOP2(pklb)
-MVIOP2(pkwb)
-MVIOP2(unpkbl)
-MVIOP2(unpkbw)
-
-static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
-                    int islit, uint8_t lit)
-{
-    TCGv va, vb;
-
-    if (unlikely(rc == 31)) {
-        return;
-    }
-
-    if (ra == 31) {
-        va = tcg_const_i64(0);
-    } else {
-        va = cpu_ir[ra];
-    }
-    if (islit) {
-        vb = tcg_const_i64(lit);
-    } else {
-        vb = cpu_ir[rb];
-    }
-
-    tcg_gen_setcond_i64(cond, cpu_ir[rc], va, vb);
-
-    if (ra == 31) {
-        tcg_temp_free(va);
-    }
-    if (islit) {
-        tcg_temp_free(vb);
-    }
-}
-
 static void gen_rx(int ra, int set)
 {
     TCGv_i32 tmp;
@@ -1504,11 +1129,13 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
             break;
         case 0x9E:
             /* RDUNIQUE */
-            tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_unique);
+            tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
+                           offsetof(CPUAlphaState, unique));
             break;
         case 0x9F:
             /* WRUNIQUE */
-            tcg_gen_mov_i64(cpu_unique, cpu_ir[IR_A0]);
+            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+                           offsetof(CPUAlphaState, unique));
             break;
         default:
             palcode &= 0xbf;
@@ -1531,15 +1158,18 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
             break;
         case 0x2D:
             /* WRVPTPTR */
-            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env, offsetof(CPUAlphaState, vptptr));
+            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+                           offsetof(CPUAlphaState, vptptr));
             break;
         case 0x31:
             /* WRVAL */
-            tcg_gen_mov_i64(cpu_sysval, cpu_ir[IR_A0]);
+            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+                           offsetof(CPUAlphaState, sysval));
             break;
         case 0x32:
             /* RDVAL */
-            tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_sysval);
+            tcg_gen_ld_i64(cpu_ir[IR_V0], cpu_env,
+                           offsetof(CPUAlphaState, sysval));
             break;
 
         case 0x35: {
@@ -1548,7 +1178,8 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
 
             /* Note that we already know we're in kernel mode, so we know
                that PS only contains the 3 IPL bits.  */
-            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUAlphaState, ps));
+            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env,
+                             offsetof(CPUAlphaState, ps));
 
             /* But make sure and store only the 3 IPL bits from the user.  */
             tmp = tcg_temp_new();
@@ -1560,15 +1191,18 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
 
         case 0x36:
             /* RDPS */
-            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUAlphaState, ps));
+            tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env,
+                             offsetof(CPUAlphaState, ps));
             break;
         case 0x38:
             /* WRUSP */
-            tcg_gen_mov_i64(cpu_usp, cpu_ir[IR_A0]);
+            tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env,
+                           offsetof(CPUAlphaState, usp));
             break;
         case 0x3A:
             /* RDUSP */
-            tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_usp);
+            tcg_gen_st_i64(cpu_ir[IR_V0], cpu_env,
+                           offsetof(CPUAlphaState, usp));
             break;
         case 0x3C:
             /* WHAMI */
@@ -1648,16 +1282,10 @@ static int cpu_pr_data(int pr)
     return 0;
 }
 
-static ExitStatus gen_mfpr(int ra, int regno)
+static ExitStatus gen_mfpr(TCGv va, int regno)
 {
     int data = cpu_pr_data(regno);
 
-    /* In our emulated PALcode, these processor registers have no
-       side effects from reading.  */
-    if (ra == 31) {
-        return NO_EXIT;
-    }
-
     /* Special help for VMTIME and WALLTIME.  */
     if (regno == 250 || regno == 249) {
 	void (*helper)(TCGv) = gen_helper_get_walltime;
@@ -1666,11 +1294,11 @@ static ExitStatus gen_mfpr(int ra, int regno)
 	}
         if (use_icount) {
             gen_io_start();
-            helper(cpu_ir[ra]);
+            helper(va);
             gen_io_end();
             return EXIT_PC_STALE;
         } else {
-            helper(cpu_ir[ra]);
+            helper(va);
             return NO_EXIT;
         }
     }
@@ -1678,28 +1306,22 @@ static ExitStatus gen_mfpr(int ra, int regno)
     /* The basic registers are data only, and unknown registers
        are read-zero, write-ignore.  */
     if (data == 0) {
-        tcg_gen_movi_i64(cpu_ir[ra], 0);
+        tcg_gen_movi_i64(va, 0);
     } else if (data & PR_BYTE) {
-        tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, data & ~PR_BYTE);
+        tcg_gen_ld8u_i64(va, cpu_env, data & ~PR_BYTE);
     } else if (data & PR_LONG) {
-        tcg_gen_ld32s_i64(cpu_ir[ra], cpu_env, data & ~PR_LONG);
+        tcg_gen_ld32s_i64(va, cpu_env, data & ~PR_LONG);
     } else {
-        tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
+        tcg_gen_ld_i64(va, cpu_env, data);
     }
     return NO_EXIT;
 }
 
-static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
+static ExitStatus gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
 {
     TCGv tmp;
     int data;
 
-    if (rb == 31) {
-        tmp = tcg_const_i64(0);
-    } else {
-        tmp = cpu_ir[rb];
-    }
-
     switch (regno) {
     case 255:
         /* TBIA */
@@ -1708,7 +1330,7 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
 
     case 254:
         /* TBIS */
-        gen_helper_tbis(cpu_env, tmp);
+        gen_helper_tbis(cpu_env, vb);
         break;
 
     case 253:
@@ -1720,17 +1342,17 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
 
     case 252:
         /* HALT */
-        gen_helper_halt(tmp);
+        gen_helper_halt(vb);
         return EXIT_PC_STALE;
 
     case 251:
         /* ALARM */
-        gen_helper_set_alarm(cpu_env, tmp);
+        gen_helper_set_alarm(cpu_env, vb);
         break;
 
     case 7:
         /* PALBR */
-        tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, palbr));
+        tcg_gen_st_i64(vb, cpu_env, offsetof(CPUAlphaState, palbr));
         /* Changing the PAL base register implies un-chaining all of the TBs
            that ended with a CALL_PAL.  Since the base register usually only
            changes during boot, flushing everything works well.  */
@@ -1743,64 +1365,70 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
         data = cpu_pr_data(regno);
         if (data != 0) {
             if (data & PR_BYTE) {
-                tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
+                tcg_gen_st8_i64(vb, cpu_env, data & ~PR_BYTE);
             } else if (data & PR_LONG) {
-                tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
+                tcg_gen_st32_i64(vb, cpu_env, data & ~PR_LONG);
             } else {
-                tcg_gen_st_i64(tmp, cpu_env, data);
+                tcg_gen_st_i64(vb, cpu_env, data);
             }
         }
         break;
     }
 
-    if (rb == 31) {
-        tcg_temp_free(tmp);
-    }
-
     return NO_EXIT;
 }
 #endif /* !USER_ONLY*/
 
+#define REQUIRE_TB_FLAG(FLAG)                   \
+    do {                                        \
+        if ((ctx->tb->flags & (FLAG)) == 0) {   \
+            goto invalid_opc;                   \
+        }                                       \
+    } while (0)
+
+#define REQUIRE_REG_31(WHICH)                   \
+    do {                                        \
+        if (WHICH != 31) {                      \
+            goto invalid_opc;                   \
+        }                                       \
+    } while (0)
+
 static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
 {
-    uint32_t palcode;
-    int32_t disp21, disp16;
-#ifndef CONFIG_USER_ONLY
-    int32_t disp12;
-#endif
+    int32_t disp21, disp16, disp12 __attribute__((unused));
     uint16_t fn11;
-    uint8_t opc, ra, rb, rc, fpfn, fn7, islit, real_islit;
-    uint8_t lit;
+    uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
+    bool islit;
+    TCGv va, vb, vc, tmp;
+    TCGv_i32 t32;
     ExitStatus ret;
 
     /* Decode all instruction fields */
-    opc = insn >> 26;
-    ra = (insn >> 21) & 0x1F;
-    rb = (insn >> 16) & 0x1F;
-    rc = insn & 0x1F;
-    real_islit = islit = (insn >> 12) & 1;
+    opc = extract32(insn, 26, 6);
+    ra = extract32(insn, 21, 5);
+    rb = extract32(insn, 16, 5);
+    rc = extract32(insn, 0, 5);
+    islit = extract32(insn, 12, 1);
+    lit = extract32(insn, 13, 8);
+
+    disp21 = sextract32(insn, 0, 21);
+    disp16 = sextract32(insn, 0, 16);
+    disp12 = sextract32(insn, 0, 12);
+
+    fn11 = extract32(insn, 5, 11);
+    fpfn = extract32(insn, 5, 6);
+    fn7 = extract32(insn, 5, 7);
+
     if (rb == 31 && !islit) {
-        islit = 1;
+        islit = true;
         lit = 0;
-    } else
-        lit = (insn >> 13) & 0xFF;
-    palcode = insn & 0x03FFFFFF;
-    disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
-    disp16 = (int16_t)(insn & 0x0000FFFF);
-#ifndef CONFIG_USER_ONLY
-    disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
-#endif
-    fn11 = (insn >> 5) & 0x000007FF;
-    fpfn = fn11 & 0x3F;
-    fn7 = (insn >> 5) & 0x0000007F;
-    LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
-              opc, ra, rb, rc, disp16);
+    }
 
     ret = NO_EXIT;
     switch (opc) {
     case 0x00:
         /* CALL_PAL */
-        ret = gen_call_pal(ctx, palcode);
+        ret = gen_call_pal(ctx, insn & 0x03ffffff);
         break;
     case 0x01:
         /* OPC01 */
@@ -1823,839 +1451,627 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     case 0x07:
         /* OPC07 */
         goto invalid_opc;
-    case 0x08:
-        /* LDA */
-        if (likely(ra != 31)) {
-            if (rb != 31)
-                tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(cpu_ir[ra], disp16);
-        }
-        break;
+
     case 0x09:
         /* LDAH */
-        if (likely(ra != 31)) {
-            if (rb != 31)
-                tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16);
-            else
-                tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16);
+        disp16 = (uint32_t)disp16 << 16;
+        /* fall through */
+    case 0x08:
+        /* LDA */
+        va = dest_gpr(ctx, ra);
+        /* It's worth special-casing immediate loads.  */
+        if (rb == 31) {
+            tcg_gen_movi_i64(va, disp16);
+        } else {
+            tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
         }
         break;
+
     case 0x0A:
         /* LDBU */
-        if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
-            gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
-            break;
-        }
-        goto invalid_opc;
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+        gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
+        break;
     case 0x0B:
         /* LDQ_U */
         gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
         break;
     case 0x0C:
         /* LDWU */
-        if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
-            gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
-            break;
-        }
-        goto invalid_opc;
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+        gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
+        break;
     case 0x0D:
         /* STW */
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
         gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
         break;
     case 0x0E:
         /* STB */
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
         gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
         break;
     case 0x0F:
         /* STQ_U */
         gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
         break;
+
     case 0x10:
+        vc = dest_gpr(ctx, rc);
+        vb = load_gpr_lit(ctx, rb, lit, islit);
+
+        if (ra == 31) {
+            if (fn7 == 0x00) {
+                /* Special case ADDL as SEXTL.  */
+                tcg_gen_ext32s_i64(vc, vb);
+                break;
+            }
+            if (fn7 == 0x29) {
+                /* Special case SUBQ as NEGQ.  */
+                tcg_gen_neg_i64(vc, vb);
+                break;
+            }
+        }
+
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x00:
             /* ADDL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit) {
-                        tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    } else {
-                        tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    }
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_add_i64(vc, va, vb);
+            tcg_gen_ext32s_i64(vc, vc);
             break;
         case 0x02:
             /* S4ADDL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_addi_i64(tmp, tmp, lit);
-                    else
-                        tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_add_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x09:
             /* SUBL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else {
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    }
-                }
-            }
+            tcg_gen_sub_i64(vc, va, vb);
+            tcg_gen_ext32s_i64(vc, vc);
             break;
         case 0x0B:
             /* S4SUBL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_subi_i64(tmp, tmp, lit);
-                    else
-                        tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else {
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    }
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_sub_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x0F:
             /* CMPBGE */
-            gen_cmpbge(ra, rb, rc, islit, lit);
+            gen_helper_cmpbge(vc, va, vb);
             break;
         case 0x12:
             /* S8ADDL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_addi_i64(tmp, tmp, lit);
-                    else
-                        tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_add_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x1B:
             /* S8SUBL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_subi_i64(tmp, tmp, lit);
-                    else
-                       tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else {
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                        tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                    }
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_sub_i64(tmp, tmp, vb);
+            tcg_gen_ext32s_i64(vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x1D:
             /* CMPULT */
-            gen_cmp(TCG_COND_LTU, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
             break;
         case 0x20:
             /* ADDQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_add_i64(vc, va, vb);
             break;
         case 0x22:
             /* S4ADDQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_add_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x29:
             /* SUBQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_sub_i64(vc, va, vb);
             break;
         case 0x2B:
             /* S4SUBQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 2);
+            tcg_gen_sub_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x2D:
             /* CMPEQ */
-            gen_cmp(TCG_COND_EQ, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
             break;
         case 0x32:
             /* S8ADDQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_add_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x3B:
             /* S8SUBQ */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv tmp = tcg_temp_new();
-                    tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
-                    if (islit)
-                        tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
-                    else
-                        tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
-                    tcg_temp_free(tmp);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], -lit);
-                    else
-                        tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_shli_i64(tmp, va, 3);
+            tcg_gen_sub_i64(vc, tmp, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x3D:
             /* CMPULE */
-            gen_cmp(TCG_COND_LEU, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
             break;
         case 0x40:
             /* ADDL/V */
-            gen_addlv(ra, rb, rc, islit, lit);
+            gen_helper_addlv(vc, cpu_env, va, vb);
             break;
         case 0x49:
             /* SUBL/V */
-            gen_sublv(ra, rb, rc, islit, lit);
+            gen_helper_sublv(vc, cpu_env, va, vb);
             break;
         case 0x4D:
             /* CMPLT */
-            gen_cmp(TCG_COND_LT, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
             break;
         case 0x60:
             /* ADDQ/V */
-            gen_addqv(ra, rb, rc, islit, lit);
+            gen_helper_addqv(vc, cpu_env, va, vb);
             break;
         case 0x69:
             /* SUBQ/V */
-            gen_subqv(ra, rb, rc, islit, lit);
+            gen_helper_subqv(vc, cpu_env, va, vb);
             break;
         case 0x6D:
             /* CMPLE */
-            gen_cmp(TCG_COND_LE, ra, rb, rc, islit, lit);
+            tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x11:
+        if (fn7 == 0x20) {
+            if (rc == 31) {
+                /* Special case BIS as NOP.  */
+                break;
+            }
+            if (ra == 31) {
+                /* Special case BIS as MOV.  */
+                vc = dest_gpr(ctx, rc);
+                if (islit) {
+                    tcg_gen_movi_i64(vc, lit);
+                } else {
+                    tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
+                }
+                break;
+            }
+        }
+
+        vc = dest_gpr(ctx, rc);
+        vb = load_gpr_lit(ctx, rb, lit, islit);
+
+        if (fn7 == 0x28 && ra == 31) {
+            /* Special case ORNOT as NOT.  */
+            tcg_gen_not_i64(vc, vb);
+            break;
+        }
+
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x00:
             /* AND */
-            if (likely(rc != 31)) {
-                if (ra == 31)
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                else if (islit)
-                    tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                else
-                    tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-            }
+            tcg_gen_and_i64(vc, va, vb);
             break;
         case 0x08:
             /* BIC */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
-                    else
-                        tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-            }
+            tcg_gen_andc_i64(vc, va, vb);
             break;
         case 0x14:
             /* CMOVLBS */
-            gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
+            tmp = tcg_temp_new();
+            tcg_gen_andi_i64(tmp, va, 1);
+            tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
+            tcg_temp_free(tmp);
             break;
         case 0x16:
             /* CMOVLBC */
-            gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
+            tmp = tcg_temp_new();
+            tcg_gen_andi_i64(tmp, va, 1);
+            tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
+            tcg_temp_free(tmp);
             break;
         case 0x20:
             /* BIS */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_or_i64(vc, va, vb);
             break;
         case 0x24:
             /* CMOVEQ */
-            gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x26:
             /* CMOVNE */
-            gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x28:
             /* ORNOT */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
-                    else
-                        tcg_gen_orc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], ~lit);
-                    else
-                        tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_orc_i64(vc, va, vb);
             break;
         case 0x40:
             /* XOR */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], lit);
-                    else
-                        tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_xor_i64(vc, va, vb);
             break;
         case 0x44:
             /* CMOVLT */
-            gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x46:
             /* CMOVGE */
-            gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x48:
             /* EQV */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
-                    else
-                        tcg_gen_eqv_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                } else {
-                    if (islit)
-                        tcg_gen_movi_i64(cpu_ir[rc], ~lit);
-                    else
-                        tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
-                }
-            }
+            tcg_gen_eqv_i64(vc, va, vb);
             break;
         case 0x61:
             /* AMASK */
-            if (likely(rc != 31)) {
+            REQUIRE_REG_31(ra);
+            {
                 uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
-
-                if (islit) {
-                    tcg_gen_movi_i64(cpu_ir[rc], lit & ~amask);
-                } else {
-                    tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[rb], ~amask);
-                }
+                tcg_gen_andi_i64(vc, vb, ~amask);
             }
             break;
         case 0x64:
             /* CMOVLE */
-            gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x66:
             /* CMOVGT */
-            gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
+            tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
+                                vb, load_gpr(ctx, rc));
             break;
         case 0x6C:
             /* IMPLVER */
-            if (rc != 31) {
-                tcg_gen_movi_i64(cpu_ir[rc], ctx->implver);
-            }
+            REQUIRE_REG_31(ra);
+            tcg_gen_movi_i64(vc, ctx->implver);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x12:
+        vc = dest_gpr(ctx, rc);
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x02:
             /* MSKBL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0x01);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
             break;
         case 0x06:
             /* EXTBL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0x01);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
             break;
         case 0x0B:
             /* INSBL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0x01);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
             break;
         case 0x12:
             /* MSKWL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0x03);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x16:
             /* EXTWL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0x03);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x1B:
             /* INSWL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0x03);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x22:
             /* MSKLL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0x0f);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x26:
             /* EXTLL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0x0f);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x2B:
             /* INSLL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0x0f);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x30:
             /* ZAP */
-            gen_zap(ra, rb, rc, islit, lit);
+            if (islit) {
+                gen_zapnoti(vc, va, ~lit);
+            } else {
+                gen_helper_zap(vc, va, load_gpr(ctx, rb));
+            }
             break;
         case 0x31:
             /* ZAPNOT */
-            gen_zapnot(ra, rb, rc, islit, lit);
+            if (islit) {
+                gen_zapnoti(vc, va, lit);
+            } else {
+                gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
+            }
             break;
         case 0x32:
             /* MSKQL */
-            gen_msk_l(ra, rb, rc, islit, lit, 0xff);
+            gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x34:
             /* SRL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
-                    else {
-                        TCGv shift = tcg_temp_new();
-                        tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
-                        tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], shift);
-                        tcg_temp_free(shift);
-                    }
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
+            if (islit) {
+                tcg_gen_shri_i64(vc, va, lit & 0x3f);
+            } else {
+                tmp = tcg_temp_new();
+                vb = load_gpr(ctx, rb);
+                tcg_gen_andi_i64(tmp, vb, 0x3f);
+                tcg_gen_shr_i64(vc, va, tmp);
+                tcg_temp_free(tmp);
             }
             break;
         case 0x36:
             /* EXTQL */
-            gen_ext_l(ra, rb, rc, islit, lit, 0xff);
+            gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x39:
             /* SLL */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
-                    else {
-                        TCGv shift = tcg_temp_new();
-                        tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
-                        tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], shift);
-                        tcg_temp_free(shift);
-                    }
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
+            if (islit) {
+                tcg_gen_shli_i64(vc, va, lit & 0x3f);
+            } else {
+                tmp = tcg_temp_new();
+                vb = load_gpr(ctx, rb);
+                tcg_gen_andi_i64(tmp, vb, 0x3f);
+                tcg_gen_shl_i64(vc, va, tmp);
+                tcg_temp_free(tmp);
             }
             break;
         case 0x3B:
             /* INSQL */
-            gen_ins_l(ra, rb, rc, islit, lit, 0xff);
+            gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x3C:
             /* SRA */
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    if (islit)
-                        tcg_gen_sari_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
-                    else {
-                        TCGv shift = tcg_temp_new();
-                        tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
-                        tcg_gen_sar_i64(cpu_ir[rc], cpu_ir[ra], shift);
-                        tcg_temp_free(shift);
-                    }
-                } else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
+            if (islit) {
+                tcg_gen_sari_i64(vc, va, lit & 0x3f);
+            } else {
+                tmp = tcg_temp_new();
+                vb = load_gpr(ctx, rb);
+                tcg_gen_andi_i64(tmp, vb, 0x3f);
+                tcg_gen_sar_i64(vc, va, tmp);
+                tcg_temp_free(tmp);
             }
             break;
         case 0x52:
             /* MSKWH */
-            gen_msk_h(ra, rb, rc, islit, lit, 0x03);
+            gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x57:
             /* INSWH */
-            gen_ins_h(ra, rb, rc, islit, lit, 0x03);
+            gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x5A:
             /* EXTWH */
-            gen_ext_h(ra, rb, rc, islit, lit, 0x03);
+            gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
             break;
         case 0x62:
             /* MSKLH */
-            gen_msk_h(ra, rb, rc, islit, lit, 0x0f);
+            gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x67:
             /* INSLH */
-            gen_ins_h(ra, rb, rc, islit, lit, 0x0f);
+            gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x6A:
             /* EXTLH */
-            gen_ext_h(ra, rb, rc, islit, lit, 0x0f);
+            gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
             break;
         case 0x72:
             /* MSKQH */
-            gen_msk_h(ra, rb, rc, islit, lit, 0xff);
+            gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x77:
             /* INSQH */
-            gen_ins_h(ra, rb, rc, islit, lit, 0xff);
+            gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         case 0x7A:
             /* EXTQH */
-            gen_ext_h(ra, rb, rc, islit, lit, 0xff);
+            gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x13:
+        vc = dest_gpr(ctx, rc);
+        vb = load_gpr_lit(ctx, rb, lit, islit);
+        va = load_gpr(ctx, ra);
         switch (fn7) {
         case 0x00:
             /* MULL */
-            if (likely(rc != 31)) {
-                if (ra == 31)
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                else {
-                    if (islit)
-                        tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                    else
-                        tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                    tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
-                }
-            }
+            tcg_gen_mul_i64(vc, va, vb);
+            tcg_gen_ext32s_i64(vc, vc);
             break;
         case 0x20:
             /* MULQ */
-            if (likely(rc != 31)) {
-                if (ra == 31)
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                else if (islit)
-                    tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
-                else
-                    tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-            }
+            tcg_gen_mul_i64(vc, va, vb);
             break;
         case 0x30:
             /* UMULH */
-            {
-                TCGv low;
-                if (unlikely(rc == 31)){
-                    break;
-                }
-                if (ra == 31) {
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-                    break;
-                }
-                low = tcg_temp_new();
-                if (islit) {
-                    tcg_gen_movi_tl(low, lit);
-                    tcg_gen_mulu2_i64(low, cpu_ir[rc], cpu_ir[ra], low);
-                } else {
-                    tcg_gen_mulu2_i64(low, cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
-                }
-                tcg_temp_free(low);
-            }
+            tmp = tcg_temp_new();
+            tcg_gen_mulu2_i64(tmp, vc, va, vb);
+            tcg_temp_free(tmp);
             break;
         case 0x40:
             /* MULL/V */
-            gen_mullv(ra, rb, rc, islit, lit);
+            gen_helper_mullv(vc, cpu_env, va, vb);
             break;
         case 0x60:
             /* MULQ/V */
-            gen_mulqv(ra, rb, rc, islit, lit);
+            gen_helper_mulqv(vc, cpu_env, va, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x14:
+        REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+        vc = dest_fpr(ctx, rc);
         switch (fpfn) { /* fn11 & 0x3F */
         case 0x04:
             /* ITOFS */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv_i32 tmp = tcg_temp_new_i32();
-                    tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
-                    gen_helper_memory_to_s(cpu_fir[rc], tmp);
-                    tcg_temp_free_i32(tmp);
-                } else
-                    tcg_gen_movi_i64(cpu_fir[rc], 0);
-            }
+            REQUIRE_REG_31(rb);
+            t32 = tcg_temp_new_i32();
+            va = load_gpr(ctx, ra);
+            tcg_gen_trunc_i64_i32(t32, va);
+            gen_helper_memory_to_s(vc, t32);
+            tcg_temp_free_i32(t32);
             break;
         case 0x0A:
             /* SQRTF */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrtf(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            vb = load_fpr(ctx, rb);
+            gen_helper_sqrtf(vc, cpu_env, vb);
+            break;
         case 0x0B:
             /* SQRTS */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrts(ctx, rb, rc, fn11);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            gen_fsqrts(ctx, rb, rc, fn11);
+            break;
         case 0x14:
             /* ITOFF */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31) {
-                    TCGv_i32 tmp = tcg_temp_new_i32();
-                    tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
-                    gen_helper_memory_to_f(cpu_fir[rc], tmp);
-                    tcg_temp_free_i32(tmp);
-                } else
-                    tcg_gen_movi_i64(cpu_fir[rc], 0);
-            }
+            REQUIRE_REG_31(rb);
+            t32 = tcg_temp_new_i32();
+            va = load_gpr(ctx, ra);
+            tcg_gen_trunc_i64_i32(t32, va);
+            gen_helper_memory_to_f(vc, t32);
+            tcg_temp_free_i32(t32);
             break;
         case 0x24:
             /* ITOFT */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31)
-                    tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
-                else
-                    tcg_gen_movi_i64(cpu_fir[rc], 0);
-            }
+            REQUIRE_REG_31(rb);
+            va = load_gpr(ctx, ra);
+            tcg_gen_mov_i64(vc, va);
             break;
         case 0x2A:
             /* SQRTG */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrtg(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            vb = load_fpr(ctx, rb);
+            gen_helper_sqrtg(vc, cpu_env, vb);
+            break;
         case 0x02B:
             /* SQRTT */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
-                gen_fsqrtt(ctx, rb, rc, fn11);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_REG_31(ra);
+            gen_fsqrtt(ctx, rb, rc, fn11);
+            break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x15:
         /* VAX floating point */
         /* XXX: rounding mode and trap are ignored (!) */
+        vc = dest_fpr(ctx, rc);
+        vb = load_fpr(ctx, rb);
+        va = load_fpr(ctx, ra);
         switch (fpfn) { /* fn11 & 0x3F */
         case 0x00:
             /* ADDF */
-            gen_faddf(ra, rb, rc);
+            gen_helper_addf(vc, cpu_env, va, vb);
             break;
         case 0x01:
             /* SUBF */
-            gen_fsubf(ra, rb, rc);
+            gen_helper_subf(vc, cpu_env, va, vb);
             break;
         case 0x02:
             /* MULF */
-            gen_fmulf(ra, rb, rc);
+            gen_helper_mulf(vc, cpu_env, va, vb);
             break;
         case 0x03:
             /* DIVF */
-            gen_fdivf(ra, rb, rc);
+            gen_helper_divf(vc, cpu_env, va, vb);
             break;
         case 0x1E:
-            /* CVTDG */
-#if 0 // TODO
-            gen_fcvtdg(rb, rc);
-#else
+            /* CVTDG -- TODO */
+            REQUIRE_REG_31(ra);
             goto invalid_opc;
-#endif
-            break;
         case 0x20:
             /* ADDG */
-            gen_faddg(ra, rb, rc);
+            gen_helper_addg(vc, cpu_env, va, vb);
             break;
         case 0x21:
             /* SUBG */
-            gen_fsubg(ra, rb, rc);
+            gen_helper_subg(vc, cpu_env, va, vb);
             break;
         case 0x22:
             /* MULG */
-            gen_fmulg(ra, rb, rc);
+            gen_helper_mulg(vc, cpu_env, va, vb);
             break;
         case 0x23:
             /* DIVG */
-            gen_fdivg(ra, rb, rc);
+            gen_helper_divg(vc, cpu_env, va, vb);
             break;
         case 0x25:
             /* CMPGEQ */
-            gen_fcmpgeq(ra, rb, rc);
+            gen_helper_cmpgeq(vc, cpu_env, va, vb);
             break;
         case 0x26:
             /* CMPGLT */
-            gen_fcmpglt(ra, rb, rc);
+            gen_helper_cmpglt(vc, cpu_env, va, vb);
             break;
         case 0x27:
             /* CMPGLE */
-            gen_fcmpgle(ra, rb, rc);
+            gen_helper_cmpgle(vc, cpu_env, va, vb);
             break;
         case 0x2C:
             /* CVTGF */
-            gen_fcvtgf(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtgf(vc, cpu_env, vb);
             break;
         case 0x2D:
-            /* CVTGD */
-#if 0 // TODO
-            gen_fcvtgd(rb, rc);
-#else
+            /* CVTGD -- TODO */
+            REQUIRE_REG_31(ra);
             goto invalid_opc;
-#endif
-            break;
         case 0x2F:
             /* CVTGQ */
-            gen_fcvtgq(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtgq(vc, cpu_env, vb);
             break;
         case 0x3C:
             /* CVTQF */
-            gen_fcvtqf(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtqf(vc, cpu_env, vb);
             break;
         case 0x3E:
             /* CVTQG */
-            gen_fcvtqg(rb, rc);
+            REQUIRE_REG_31(ra);
+            gen_helper_cvtqg(vc, cpu_env, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x16:
         /* IEEE floating-point */
         switch (fpfn) { /* fn11 & 0x3F */
@@ -2708,6 +2124,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             gen_fcmptle(ctx, ra, rb, rc, fn11);
             break;
         case 0x2C:
+            REQUIRE_REG_31(ra);
             if (fn11 == 0x2AC || fn11 == 0x6AC) {
                 /* CVTST */
                 gen_fcvtst(ctx, rb, rc, fn11);
@@ -2718,104 +2135,122 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0x2F:
             /* CVTTQ */
+            REQUIRE_REG_31(ra);
             gen_fcvttq(ctx, rb, rc, fn11);
             break;
         case 0x3C:
             /* CVTQS */
+            REQUIRE_REG_31(ra);
             gen_fcvtqs(ctx, rb, rc, fn11);
             break;
         case 0x3E:
             /* CVTQT */
+            REQUIRE_REG_31(ra);
             gen_fcvtqt(ctx, rb, rc, fn11);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x17:
         switch (fn11) {
         case 0x010:
             /* CVTLQ */
-            gen_fcvtlq(rb, rc);
+            REQUIRE_REG_31(ra);
+            vc = dest_fpr(ctx, rc);
+            vb = load_fpr(ctx, rb);
+            gen_fcvtlq(vc, vb);
             break;
         case 0x020:
-            if (likely(rc != 31)) {
+            /* CPYS */
+            if (rc == 31) {
+                /* Special case CPYS as FNOP.  */
+            } else {
+                vc = dest_fpr(ctx, rc);
+                va = load_fpr(ctx, ra);
                 if (ra == rb) {
-                    /* FMOV */
-                    if (ra == 31)
-                        tcg_gen_movi_i64(cpu_fir[rc], 0);
-                    else
-                        tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
+                    /* Special case CPYS as FMOV.  */
+                    tcg_gen_mov_i64(vc, va);
                 } else {
-                    /* CPYS */
-                    gen_fcpys(ra, rb, rc);
+                    vb = load_fpr(ctx, rb);
+                    gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL);
                 }
             }
             break;
         case 0x021:
             /* CPYSN */
-            gen_fcpysn(ra, rb, rc);
+            vc = dest_fpr(ctx, rc);
+            vb = load_fpr(ctx, rb);
+            va = load_fpr(ctx, ra);
+            gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL);
             break;
         case 0x022:
             /* CPYSE */
-            gen_fcpyse(ra, rb, rc);
+            vc = dest_fpr(ctx, rc);
+            vb = load_fpr(ctx, rb);
+            va = load_fpr(ctx, ra);
+            gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL);
             break;
         case 0x024:
             /* MT_FPCR */
-            if (likely(ra != 31))
-                gen_helper_store_fpcr(cpu_env, cpu_fir[ra]);
-            else {
-                TCGv tmp = tcg_const_i64(0);
-                gen_helper_store_fpcr(cpu_env, tmp);
-                tcg_temp_free(tmp);
-            }
+            va = load_fpr(ctx, ra);
+            gen_helper_store_fpcr(cpu_env, va);
             break;
         case 0x025:
             /* MF_FPCR */
-            if (likely(ra != 31))
-                gen_helper_load_fpcr(cpu_fir[ra], cpu_env);
+            va = dest_fpr(ctx, ra);
+            gen_helper_load_fpcr(va, cpu_env);
             break;
         case 0x02A:
             /* FCMOVEQ */
-            gen_fcmov(TCG_COND_EQ, ra, rb, rc);
+            gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc);
             break;
         case 0x02B:
             /* FCMOVNE */
-            gen_fcmov(TCG_COND_NE, ra, rb, rc);
+            gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc);
             break;
         case 0x02C:
             /* FCMOVLT */
-            gen_fcmov(TCG_COND_LT, ra, rb, rc);
+            gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc);
             break;
         case 0x02D:
             /* FCMOVGE */
-            gen_fcmov(TCG_COND_GE, ra, rb, rc);
+            gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc);
             break;
         case 0x02E:
             /* FCMOVLE */
-            gen_fcmov(TCG_COND_LE, ra, rb, rc);
+            gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc);
             break;
         case 0x02F:
             /* FCMOVGT */
-            gen_fcmov(TCG_COND_GT, ra, rb, rc);
+            gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
             break;
         case 0x030:
             /* CVTQL */
-            gen_fcvtql(rb, rc);
+            REQUIRE_REG_31(ra);
+            vc = dest_fpr(ctx, rc);
+            vb = load_fpr(ctx, rb);
+            gen_fcvtql(vc, vb);
             break;
         case 0x130:
             /* CVTQL/V */
         case 0x530:
             /* CVTQL/SV */
+            REQUIRE_REG_31(ra);
             /* ??? I'm pretty sure there's nothing that /sv needs to do that
                /v doesn't do.  The only thing I can think is that /sv is a
                valid instruction merely for completeness in the ISA.  */
-            gen_fcvtql_v(ctx, rb, rc);
+            vc = dest_fpr(ctx, rc);
+            vb = load_fpr(ctx, rb);
+            gen_helper_fcvtql_v_input(cpu_env, vb);
+            gen_fcvtql(vc, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x18:
         switch ((uint16_t)disp16) {
         case 0x0000:
@@ -2844,15 +2279,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0xC000:
             /* RPCC */
-            if (ra != 31) {
-                if (use_icount) {
-                    gen_io_start();
-                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
-                    gen_io_end();
-                    ret = EXIT_PC_STALE;
-                } else {
-                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
-                }
+            va = dest_gpr(ctx, ra);
+            if (use_icount) {
+                gen_io_start();
+                gen_helper_load_pcc(va, cpu_env);
+                gen_io_end();
+                ret = EXIT_PC_STALE;
+            } else {
+                gen_helper_load_pcc(va, cpu_env);
             }
             break;
         case 0xE000:
@@ -2874,58 +2308,55 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             goto invalid_opc;
         }
         break;
+
     case 0x19:
         /* HW_MFPR (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            return gen_mfpr(ra, insn & 0xffff);
-        }
-#endif
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        va = dest_gpr(ctx, ra);
+        ret = gen_mfpr(va, insn & 0xffff);
+        break;
+#else
         goto invalid_opc;
+#endif
+
     case 0x1A:
         /* JMP, JSR, RET, JSR_COROUTINE.  These only differ by the branch
            prediction stack action, which of course we don't implement.  */
-        if (rb != 31) {
-            tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
-        } else {
-            tcg_gen_movi_i64(cpu_pc, 0);
-        }
+        vb = load_gpr(ctx, rb);
+        tcg_gen_andi_i64(cpu_pc, vb, ~3);
         if (ra != 31) {
             tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
         }
         ret = EXIT_PC_UPDATED;
         break;
+
     case 0x1B:
         /* HW_LD (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            TCGv addr;
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        {
+            TCGv addr = tcg_temp_new();
+            vb = load_gpr(ctx, rb);
+            va = dest_gpr(ctx, ra);
 
-            if (ra == 31) {
-                break;
-            }
-
-            addr = tcg_temp_new();
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
-            else
-                tcg_gen_movi_i64(addr, disp12);
+            tcg_gen_addi_i64(addr, vb, disp12);
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access (hw_ldl/p) */
-                gen_helper_ldl_phys(cpu_ir[ra], cpu_env, addr);
+                gen_helper_ldl_phys(va, cpu_env, addr);
                 break;
             case 0x1:
                 /* Quadword physical access (hw_ldq/p) */
-                gen_helper_ldq_phys(cpu_ir[ra], cpu_env, addr);
+                gen_helper_ldq_phys(va, cpu_env, addr);
                 break;
             case 0x2:
                 /* Longword physical access with lock (hw_ldl_l/p) */
-                gen_helper_ldl_l_phys(cpu_ir[ra], cpu_env, addr);
+                gen_helper_ldl_l_phys(va, cpu_env, addr);
                 break;
             case 0x3:
                 /* Quadword physical access with lock (hw_ldq_l/p) */
-                gen_helper_ldq_l_phys(cpu_ir[ra], cpu_env, addr);
+                gen_helper_ldq_l_phys(va, cpu_env, addr);
                 break;
             case 0x4:
                 /* Longword virtual PTE fetch (hw_ldl/v) */
@@ -2948,11 +2379,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                 goto invalid_opc;
             case 0xA:
                 /* Longword virtual access with protection check (hw_ldl/w) */
-                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_KERNEL_IDX, MO_LESL);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL);
                 break;
             case 0xB:
                 /* Quadword virtual access with protection check (hw_ldq/w) */
-                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_KERNEL_IDX, MO_LEQ);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEQ);
                 break;
             case 0xC:
                 /* Longword virtual access with alt access mode (hw_ldl/a)*/
@@ -2963,282 +2394,215 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             case 0xE:
                 /* Longword virtual access with alternate access mode and
                    protection checks (hw_ldl/wa) */
-                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_USER_IDX, MO_LESL);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL);
                 break;
             case 0xF:
                 /* Quadword virtual access with alternate access mode and
                    protection checks (hw_ldq/wa) */
-                tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_USER_IDX, MO_LEQ);
+                tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEQ);
                 break;
             }
             tcg_temp_free(addr);
             break;
         }
-#endif
+#else
         goto invalid_opc;
+#endif
+
     case 0x1C:
+        vc = dest_gpr(ctx, rc);
+        if (fn7 == 0x70) {
+            /* FTOIT */
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+            REQUIRE_REG_31(rb);
+            va = load_fpr(ctx, ra);
+            tcg_gen_mov_i64(vc, va);
+            break;
+        } else if (fn7 == 0x78) {
+            /* FTOIS */
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_FIX);
+            REQUIRE_REG_31(rb);
+            t32 = tcg_temp_new_i32();
+            va = load_fpr(ctx, ra);
+            gen_helper_s_to_memory(t32, va);
+            tcg_gen_ext_i32_i64(vc, t32);
+            tcg_temp_free_i32(t32);
+            break;
+        }
+
+        vb = load_gpr_lit(ctx, rb, lit, islit);
         switch (fn7) {
         case 0x00:
             /* SEXTB */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_BWX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (islit)
-                    tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit));
-                else
-                    tcg_gen_ext8s_i64(cpu_ir[rc], cpu_ir[rb]);
-            }
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+            REQUIRE_REG_31(ra);
+            tcg_gen_ext8s_i64(vc, vb);
             break;
         case 0x01:
             /* SEXTW */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
-                    } else {
-                        tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_BWX);
+            REQUIRE_REG_31(ra);
+            tcg_gen_ext16s_i64(vc, vb);
+            break;
         case 0x30:
             /* CTPOP */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
-                    } else {
-                        gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+            REQUIRE_REG_31(ra);
+            gen_helper_ctpop(vc, vb);
+            break;
         case 0x31:
             /* PERR */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_perr(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_perr(vc, va, vb);
+            break;
         case 0x32:
             /* CTLZ */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
-                    } else {
-                        gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+            REQUIRE_REG_31(ra);
+            gen_helper_ctlz(vc, vb);
+            break;
         case 0x33:
             /* CTTZ */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
-                if (likely(rc != 31)) {
-                    if (islit) {
-                        tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
-                    } else {
-                        gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
-                    }
-                }
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
+            REQUIRE_REG_31(ra);
+            gen_helper_cttz(vc, vb);
+            break;
         case 0x34:
             /* UNPKBW */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_unpkbw(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_helper_unpkbw(vc, vb);
+            break;
         case 0x35:
             /* UNPKBL */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_unpkbl(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_helper_unpkbl(vc, vb);
+            break;
         case 0x36:
             /* PKWB */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_pkwb(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_helper_pkwb(vc, vb);
+            break;
         case 0x37:
             /* PKLB */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                if (real_islit || ra != 31) {
-                    goto invalid_opc;
-                }
-                gen_pklb(rb, rc);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            REQUIRE_REG_31(ra);
+            gen_helper_pklb(vc, vb);
+            break;
         case 0x38:
             /* MINSB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minsb8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minsb8(vc, va, vb);
+            break;
         case 0x39:
             /* MINSW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minsw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minsw4(vc, va, vb);
+            break;
         case 0x3A:
             /* MINUB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minub8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minub8(vc, va, vb);
+            break;
         case 0x3B:
             /* MINUW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_minuw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_minuw4(vc, va, vb);
+            break;
         case 0x3C:
             /* MAXUB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxub8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxub8(vc, va, vb);
+            break;
         case 0x3D:
             /* MAXUW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxuw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxuw4(vc, va, vb);
+            break;
         case 0x3E:
             /* MAXSB8 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxsb8(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxsb8(vc, va, vb);
+            break;
         case 0x3F:
             /* MAXSW4 */
-            if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
-                gen_maxsw4(ra, rb, rc, islit, lit);
-                break;
-            }
-            goto invalid_opc;
-        case 0x70:
-            /* FTOIT */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (likely(rc != 31)) {
-                if (ra != 31)
-                    tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
-                else
-                    tcg_gen_movi_i64(cpu_ir[rc], 0);
-            }
-            break;
-        case 0x78:
-            /* FTOIS */
-            if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
-                goto invalid_opc;
-            }
-            if (rc != 31) {
-                TCGv_i32 tmp1 = tcg_temp_new_i32();
-                if (ra != 31)
-                    gen_helper_s_to_memory(tmp1, cpu_fir[ra]);
-                else {
-                    TCGv tmp2 = tcg_const_i64(0);
-                    gen_helper_s_to_memory(tmp1, tmp2);
-                    tcg_temp_free(tmp2);
-                }
-                tcg_gen_ext_i32_i64(cpu_ir[rc], tmp1);
-                tcg_temp_free_i32(tmp1);
-            }
+            REQUIRE_TB_FLAG(TB_FLAGS_AMASK_MVI);
+            va = load_gpr(ctx, ra);
+            gen_helper_maxsw4(vc, va, vb);
             break;
         default:
             goto invalid_opc;
         }
         break;
+
     case 0x1D:
         /* HW_MTPR (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            return gen_mtpr(ctx, rb, insn & 0xffff);
-        }
-#endif
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        vb = load_gpr(ctx, rb);
+        ret = gen_mtpr(ctx, vb, insn & 0xffff);
+        break;
+#else
         goto invalid_opc;
+#endif
+
     case 0x1E:
         /* HW_RET (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            if (rb == 31) {
-                /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
-                   address from EXC_ADDR.  This turns out to be useful for our
-                   emulation PALcode, so continue to accept it.  */
-                TCGv tmp = tcg_temp_new();
-                tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
-                gen_helper_hw_ret(cpu_env, tmp);
-                tcg_temp_free(tmp);
-            } else {
-                gen_helper_hw_ret(cpu_env, cpu_ir[rb]);
-            }
-            ret = EXIT_PC_UPDATED;
-            break;
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        if (rb == 31) {
+            /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
+               address from EXC_ADDR.  This turns out to be useful for our
+               emulation PALcode, so continue to accept it.  */
+            tmp = tcg_temp_new();
+            tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
+            gen_helper_hw_ret(cpu_env, tmp);
+            tcg_temp_free(tmp);
+        } else {
+            gen_helper_hw_ret(cpu_env, load_gpr(ctx, rb));
         }
-#endif
+        ret = EXIT_PC_UPDATED;
+        break;
+#else
         goto invalid_opc;
+#endif
+
     case 0x1F:
         /* HW_ST (PALcode) */
 #ifndef CONFIG_USER_ONLY
-        if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            TCGv addr, val;
-            addr = tcg_temp_new();
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
-            else
-                tcg_gen_movi_i64(addr, disp12);
-            if (ra != 31)
-                val = cpu_ir[ra];
-            else {
-                val = tcg_temp_new();
-                tcg_gen_movi_i64(val, 0);
-            }
+        REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
+        {
+            TCGv addr = tcg_temp_new();
+            va = load_gpr(ctx, ra);
+            vb = load_gpr(ctx, rb);
+
+            tcg_gen_addi_i64(addr, vb, disp12);
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access */
-                gen_helper_stl_phys(cpu_env, addr, val);
+                gen_helper_stl_phys(cpu_env, addr, va);
                 break;
             case 0x1:
                 /* Quadword physical access */
-                gen_helper_stq_phys(cpu_env, addr, val);
+                gen_helper_stq_phys(cpu_env, addr, va);
                 break;
             case 0x2:
                 /* Longword physical access with lock */
-                gen_helper_stl_c_phys(val, cpu_env, addr, val);
+                gen_helper_stl_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
                 break;
             case 0x3:
                 /* Quadword physical access with lock */
-                gen_helper_stq_c_phys(val, cpu_env, addr, val);
+                gen_helper_stq_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
                 break;
             case 0x4:
                 /* Longword virtual access */
@@ -3277,13 +2641,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
                 /* Invalid */
                 goto invalid_opc;
             }
-            if (ra == 31)
-                tcg_temp_free(val);
             tcg_temp_free(addr);
             break;
         }
-#endif
+#else
         goto invalid_opc;
+#endif
     case 0x20:
         /* LDF */
         gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
@@ -3483,8 +2846,9 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
             tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
-        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
+        }
         insn = cpu_ldl_code(env, ctx.pc);
         num_insns++;
 
@@ -3492,9 +2856,24 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
             tcg_gen_debug_insn_start(ctx.pc);
         }
 
+        TCGV_UNUSED_I64(ctx.zero);
+        TCGV_UNUSED_I64(ctx.sink);
+        TCGV_UNUSED_I64(ctx.lit);
+
         ctx.pc += 4;
         ret = translate_one(ctxp, insn);
 
+        if (!TCGV_IS_UNUSED_I64(ctx.sink)) {
+            tcg_gen_discard_i64(ctx.sink);
+            tcg_temp_free(ctx.sink);
+        }
+        if (!TCGV_IS_UNUSED_I64(ctx.zero)) {
+            tcg_temp_free(ctx.zero);
+        }
+        if (!TCGV_IS_UNUSED_I64(ctx.lit)) {
+            tcg_temp_free(ctx.lit);
+        }
+
         /* If we reach a page boundary, are single stepping,
            or exhaust instruction count, stop generation.  */
         if (ret == NO_EXIT
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index f332d41b94..41903a93fb 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -126,6 +126,9 @@ typedef struct CPUS390XState {
     uint64_t pfault_compare;
     uint64_t pfault_select;
 
+    uint64_t gbea;
+    uint64_t pp;
+
     CPU_COMMON
 
     /* reset does memset(0) up to here */
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 56b9af7505..a30d1bc060 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -36,6 +36,7 @@
 #include "sysemu/device_tree.h"
 #include "qapi/qmp/qjson.h"
 #include "monitor/monitor.h"
+#include "trace.h"
 
 /* #define DEBUG_KVM */
 
@@ -128,14 +129,42 @@ void kvm_arch_reset_vcpu(CPUState *cpu)
     }
 }
 
+static int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source)
+{
+    struct kvm_one_reg reg;
+    int r;
+
+    reg.id = id;
+    reg.addr = (uint64_t) source;
+    r = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (r) {
+        trace_kvm_failed_reg_set(id, strerror(errno));
+    }
+    return r;
+}
+
+static int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target)
+{
+    struct kvm_one_reg reg;
+    int r;
+
+    reg.id = id;
+    reg.addr = (uint64_t) target;
+    r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (r) {
+        trace_kvm_failed_reg_get(id, strerror(errno));
+    }
+    return r;
+}
+
+
 int kvm_arch_put_registers(CPUState *cs, int level)
 {
     S390CPU *cpu = S390_CPU(cs);
     CPUS390XState *env = &cpu->env;
-    struct kvm_one_reg reg;
     struct kvm_sregs sregs;
     struct kvm_regs regs;
-    int ret;
+    int r;
     int i;
 
     /* always save the PSW  and the GPRS*/
@@ -151,9 +180,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         for (i = 0; i < 16; i++) {
             regs.gprs[i] = env->regs[i];
         }
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
-        if (ret < 0) {
-            return ret;
+        r = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
+        if (r < 0) {
+            return r;
         }
     }
 
@@ -162,47 +191,29 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return 0;
     }
 
-    reg.id = KVM_REG_S390_CPU_TIMER;
-    reg.addr = (__u64)&(env->cputm);
-    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
-    if (ret < 0) {
-        return ret;
-    }
-
-    reg.id = KVM_REG_S390_CLOCK_COMP;
-    reg.addr = (__u64)&(env->ckc);
-    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
-    if (ret < 0) {
-        return ret;
-    }
-
-    reg.id = KVM_REG_S390_TODPR;
-    reg.addr = (__u64)&(env->todpr);
-    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
-    if (ret < 0) {
-        return ret;
-    }
+    /*
+     * These ONE_REGS are not protected by a capability. As they are only
+     * necessary for migration we just trace a possible error, but don't
+     * return with an error return code.
+     */
+    kvm_set_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
+    kvm_set_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
+    kvm_set_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
+    kvm_set_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
+    kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp);
 
     if (cap_async_pf) {
-        reg.id = KVM_REG_S390_PFTOKEN;
-        reg.addr = (__u64)&(env->pfault_token);
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
-        if (ret < 0) {
-            return ret;
+        r = kvm_set_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
+        if (r < 0) {
+            return r;
         }
-
-        reg.id = KVM_REG_S390_PFCOMPARE;
-        reg.addr = (__u64)&(env->pfault_compare);
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
-        if (ret < 0) {
-            return ret;
+        r = kvm_set_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
+        if (r < 0) {
+            return r;
         }
-
-        reg.id = KVM_REG_S390_PFSELECT;
-        reg.addr = (__u64)&(env->pfault_select);
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
-        if (ret < 0) {
-            return ret;
+        r = kvm_set_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
+        if (r < 0) {
+            return r;
         }
     }
 
@@ -220,9 +231,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
             sregs.acrs[i] = env->aregs[i];
             sregs.crs[i] = env->cregs[i];
         }
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
-        if (ret < 0) {
-            return ret;
+        r = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
+        if (r < 0) {
+            return r;
         }
     }
 
@@ -240,7 +251,6 @@ int kvm_arch_get_registers(CPUState *cs)
 {
     S390CPU *cpu = S390_CPU(cs);
     CPUS390XState *env = &cpu->env;
-    struct kvm_one_reg reg;
     struct kvm_sregs sregs;
     struct kvm_regs regs;
     int i, r;
@@ -288,46 +298,27 @@ int kvm_arch_get_registers(CPUState *cs)
         env->psa = cs->kvm_run->s.regs.prefix;
     }
 
-    /* One Regs */
-    reg.id = KVM_REG_S390_CPU_TIMER;
-    reg.addr = (__u64)&(env->cputm);
-    r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
-    if (r < 0) {
-        return r;
-    }
-
-    reg.id = KVM_REG_S390_CLOCK_COMP;
-    reg.addr = (__u64)&(env->ckc);
-    r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
-    if (r < 0) {
-        return r;
-    }
-
-    reg.id = KVM_REG_S390_TODPR;
-    reg.addr = (__u64)&(env->todpr);
-    r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
-    if (r < 0) {
-        return r;
-    }
+    /*
+     * These ONE_REGS are not protected by a capability. As they are only
+     * necessary for migration we just trace a possible error, but don't
+     * return with an error return code.
+     */
+    kvm_get_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
+    kvm_get_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
+    kvm_get_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
+    kvm_get_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
+    kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp);
 
     if (cap_async_pf) {
-        reg.id = KVM_REG_S390_PFTOKEN;
-        reg.addr = (__u64)&(env->pfault_token);
-        r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+        r = kvm_get_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
         if (r < 0) {
             return r;
         }
-
-        reg.id = KVM_REG_S390_PFCOMPARE;
-        reg.addr = (__u64)&(env->pfault_compare);
-        r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+        r = kvm_get_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
         if (r < 0) {
             return r;
         }
-
-        reg.id = KVM_REG_S390_PFSELECT;
-        reg.addr = (__u64)&(env->pfault_select);
-        r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+        r = kvm_get_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
         if (r < 0) {
             return r;
         }
@@ -383,6 +374,26 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
     return 0;
 }
 
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type)
+{
+    return -ENOSYS;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type)
+{
+    return -ENOSYS;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+}
+
+void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
+{
+}
+
 void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
 {
 }
@@ -844,6 +855,11 @@ static int handle_tsch(S390CPU *cpu)
     return ret;
 }
 
+static int kvm_arch_handle_debug_exit(S390CPU *cpu)
+{
+    return -ENOSYS;
+}
+
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 {
     S390CPU *cpu = S390_CPU(cs);
@@ -859,6 +875,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
         case KVM_EXIT_S390_TSCH:
             ret = handle_tsch(cpu);
             break;
+        case KVM_EXIT_DEBUG:
+            ret = kvm_arch_handle_debug_exit(cpu);
+            break;
         default:
             fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
             break;
diff --git a/tests/qemu-iotests/084.out b/tests/qemu-iotests/084.out
index e681924b85..c7120d9b0b 100644
--- a/tests/qemu-iotests/084.out
+++ b/tests/qemu-iotests/084.out
@@ -4,10 +4,7 @@ QA output created by 084
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 Test 1: Maximum size (1024 TB):
-image: TEST_DIR/t.IMGFMT
-file format: IMGFMT
-virtual size: 1024T (1125899905794048 bytes)
-cluster_size: 1048576
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'TEST_DIR/t.IMGFMT': Invalid argument
 
 Test 2: Size too large (1024TB + 1)
 qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported VDI image size (size is 0x3fffffff10000, max supported is 0x3fffffff00000)
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
index a38bb702b3..82c56b1394 100755
--- a/tests/qemu-iotests/087
+++ b/tests/qemu-iotests/087
@@ -73,6 +73,91 @@ run_qemu <<EOF
 EOF
 
 echo
+echo === Duplicate ID ===
+echo
+
+run_qemu <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "blockdev-add",
+  "arguments": {
+      "options": {
+        "driver": "$IMGFMT",
+        "id": "disk",
+        "node-name": "test-node",
+        "file": {
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+      }
+    }
+  }
+{ "execute": "blockdev-add",
+  "arguments": {
+      "options": {
+        "driver": "$IMGFMT",
+        "id": "disk",
+        "file": {
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+      }
+    }
+  }
+{ "execute": "blockdev-add",
+  "arguments": {
+      "options": {
+        "driver": "$IMGFMT",
+        "id": "test-node",
+        "file": {
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+      }
+    }
+  }
+{ "execute": "blockdev-add",
+  "arguments": {
+      "options": {
+        "driver": "$IMGFMT",
+        "id": "disk2",
+        "node-name": "disk",
+        "file": {
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+      }
+    }
+  }
+{ "execute": "blockdev-add",
+  "arguments": {
+      "options": {
+        "driver": "$IMGFMT",
+        "id": "disk2",
+        "node-name": "test-node",
+        "file": {
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+      }
+    }
+  }
+{ "execute": "blockdev-add",
+  "arguments": {
+      "options": {
+        "driver": "$IMGFMT",
+        "id": "disk3",
+        "node-name": "disk3",
+        "file": {
+            "driver": "file",
+            "filename": "$TEST_IMG"
+        }
+      }
+    }
+  }
+{ "execute": "quit" }
+EOF
+
+echo
 echo === aio=native without O_DIRECT ===
 echo
 
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index e65dcdfbb3..7fbee3ff5e 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -13,6 +13,24 @@ QMP_VERSION
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
 
 
+=== Duplicate ID ===
+
+Testing:
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Device with id 'disk' already exists"}}
+{"error": {"class": "GenericError", "desc": "Device with node-name 'test-node' already exists"}}
+main-loop: WARNING: I/O thread spun for 1000 iterations
+{"error": {"class": "GenericError", "desc": "could not open disk image disk2: node-name=disk is conflicting with a device id"}}
+{"error": {"class": "GenericError", "desc": "could not open disk image disk2: Duplicate node name"}}
+{"error": {"class": "GenericError", "desc": "could not open disk image disk3: node-name=disk3 is conflicting with a device id"}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+
+
 === aio=native without O_DIRECT ===
 
 Testing:
diff --git a/trace-events b/trace-events
index 6ecaab2f27..a5218ba393 100644
--- a/trace-events
+++ b/trace-events
@@ -1243,3 +1243,7 @@ xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (ad
 # hw/pci/pci_host.c
 pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x"
 pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x"
+
+# target-s390/kvm.c
+kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s"
+kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s"