Merge remote-tracking branch 'remotes/awilliam/tags/vfio-updates-20190311.0' into staging

VFIO updates 2019-03-11

 - Resolution support for mdev displays supporting EDID interface
   (Gerd Hoffmann)

# gpg: Signature made Mon 11 Mar 2019 19:17:39 GMT
# gpg:                using RSA key 239B9B6E3BB08B22
# gpg: Good signature from "Alex Williamson <alex.williamson@redhat.com>" [full]
# gpg:                 aka "Alex Williamson <alex@shazbot.org>" [full]
# gpg:                 aka "Alex Williamson <alwillia@redhat.com>" [full]
# gpg:                 aka "Alex Williamson <alex.l.williamson@gmail.com>" [full]
# Primary key fingerprint: 42F6 C04E 540B D1A9 9E7B  8A90 239B 9B6E 3BB0 8B22

* remotes/awilliam/tags/vfio-updates-20190311.0:
  vfio/display: delay link up event
  vfio/display: add xres + yres properties
  vfio/display: add edid support.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/MAINTAINERS b/MAINTAINERS
index cf09a4c..d326756 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -984,6 +984,7 @@
 S: Odd Fixes
 F: hw/ppc/e500*
 F: hw/gpio/mpc8xxx.c
+F: hw/i2c/mpc_i2c.c
 F: hw/net/fsl_etsec/
 F: hw/pci-host/ppce500.c
 F: include/hw/ppc/ppc_e500.h
diff --git a/Makefile.objs b/Makefile.objs
index ef65a6c..31a84b7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,7 +13,7 @@
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
-block-obj-y += nbd/
+block-obj-y = nbd/
 block-obj-y += block.o blockjob.o job.o
 block-obj-y += block/ scsi/
 block-obj-y += qemu-io-cmds.o
@@ -101,7 +101,6 @@
 ######################################################################
 # tracing
 util-obj-y +=  trace/
-target-obj-y += trace/
 
 ######################################################################
 # guest agent
diff --git a/Makefile.target b/Makefile.target
index 40830c5..d8048aa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -105,6 +105,8 @@
 # Dummy command so that make thinks it has done something
 	@true
 
+obj-y += trace/
+
 #########################################################
 # cpu emulator library
 obj-y += exec.o
@@ -173,13 +175,7 @@
 dummy := $(call unnest-vars,,obj-y)
 all-obj-y := $(obj-y)
 
-target-obj-y :=
-block-obj-y :=
-common-obj-y :=
-chardev-obj-y :=
 include $(SRC_PATH)/Makefile.objs
-dummy := $(call unnest-vars,,target-obj-y)
-target-obj-y-save := $(target-obj-y)
 dummy := $(call unnest-vars,.., \
                authz-obj-y \
                block-obj-y \
@@ -191,9 +187,7 @@
                io-obj-y \
                common-obj-y \
                common-obj-m)
-target-obj-y := $(target-obj-y-save)
 all-obj-y += $(common-obj-y)
-all-obj-y += $(target-obj-y)
 all-obj-y += $(qom-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
@@ -228,6 +222,7 @@
 	rm -f *.a *~ $(PROGS)
 	rm -f $(shell find . -name '*.[od]')
 	rm -f hmp-commands.h gdbstub-xml.c
+	rm -f trace/generated-helpers.c trace/generated-helpers.c-timestamp
 ifdef CONFIG_TRACE_SYSTEMTAP
 	rm -f *.stp
 endif
diff --git a/accel/accel.c b/accel/accel.c
index 68b6d56..8deb475b 100644
--- a/accel/accel.c
+++ b/accel/accel.c
@@ -66,6 +66,7 @@
         *(acc->allowed) = false;
         object_unref(OBJECT(accel));
     }
+    object_set_accelerator_compat_props(acc->compat_props);
     return ret;
 }
 
@@ -91,7 +92,9 @@
 #elif defined(CONFIG_KVM)
             accel = "kvm";
 #else
-#error "No default accelerator available"
+            error_report("No accelerator selected and"
+                         " no default accelerator available");
+            exit(1);
 #endif
         }
     }
diff --git a/block/iscsi.c b/block/iscsi.c
index a0c0084..f31c612 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -145,6 +145,8 @@
  * unallocated. */
 #define ISCSI_CHECKALLOC_THRES 64
 
+#ifdef __linux__
+
 static void
 iscsi_bh_cb(void *p)
 {
@@ -172,6 +174,8 @@
     qemu_bh_schedule(acb->bh);
 }
 
+#endif
+
 static void iscsi_co_generic_bh_cb(void *opaque)
 {
     struct IscsiTask *iTask = opaque;
@@ -290,6 +294,8 @@
     };
 }
 
+#ifdef __linux__
+
 /* Called (via iscsi_service) with QemuMutex held. */
 static void
 iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
@@ -338,6 +344,7 @@
     .cancel_async       = iscsi_aio_cancel,
 };
 
+#endif
 
 static void iscsi_process_read(void *arg);
 static void iscsi_process_write(void *arg);
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 6d287ba..3916505 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -59,6 +59,7 @@
     QIONetListener *listener;
     GSource *hup_source;
     QCryptoTLSCreds *tls_creds;
+    char *tls_authz;
     TCPChardevState state;
     int max_size;
     int do_telnetopt;
@@ -807,7 +808,7 @@
     if (s->is_listen) {
         tioc = qio_channel_tls_new_server(
             s->ioc, s->tls_creds,
-            NULL, /* XXX Use an ACL */
+            s->tls_authz,
             &err);
     } else {
         tioc = qio_channel_tls_new_client(
@@ -1055,6 +1056,7 @@
     if (s->tls_creds) {
         object_unref(OBJECT(s->tls_creds));
     }
+    g_free(s->tls_authz);
 
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
@@ -1242,6 +1244,11 @@
         break;
     }
 
+    if (sock->has_tls_authz && !sock->has_tls_creds) {
+        error_setg(errp, "'tls_authz' option requires 'tls_creds' option");
+        return false;
+    }
+
     /* Validate any options which have a dependancy on client vs server */
     if (!sock->has_server || sock->server) {
         if (sock->has_reconnect) {
@@ -1320,6 +1327,7 @@
             }
         }
     }
+    s->tls_authz = g_strdup(sock->tls_authz);
 
     s->addr = addr = socket_address_flatten(sock->addr);
 
@@ -1399,6 +1407,8 @@
     sock->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
     sock->has_tls_creds = qemu_opt_get(opts, "tls-creds");
     sock->tls_creds = g_strdup(qemu_opt_get(opts, "tls-creds"));
+    sock->has_tls_authz = qemu_opt_get(opts, "tls-authz");
+    sock->tls_authz = g_strdup(qemu_opt_get(opts, "tls-authz"));
 
     addr = g_new0(SocketAddressLegacy, 1);
     if (path) {
diff --git a/chardev/char.c b/chardev/char.c
index f6d61fa..514cd6b 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -881,6 +881,9 @@
             .name = "tls-creds",
             .type = QEMU_OPT_STRING,
         },{
+            .name = "tls-authz",
+            .type = QEMU_OPT_STRING,
+        },{
             .name = "websocket",
             .type = QEMU_OPT_BOOL,
         },{
diff --git a/configure b/configure
index b354e74..cab830a 100755
--- a/configure
+++ b/configure
@@ -1836,7 +1836,7 @@
 # Consult white-list to determine whether to enable werror
 # by default.  Only enable by default for git builds
 if test -z "$werror" ; then
-    if test -d "$source_path/.git" && \
+    if test -e "$source_path/.git" && \
         { test "$linux" = "yes" || test "$mingw32" = "yes"; }; then
         werror="yes"
     else
@@ -5903,6 +5903,17 @@
     done
 fi
 
+# Disable OpenBSD W^X if available
+if test "$tcg" = "yes" && test "$targetos" = "OpenBSD"; then
+    cat > $TMPC <<EOF
+    int main(void) { return 0; }
+EOF
+    wx_ldflags="-Wl,-z,wxneeded"
+    if compile_prog "" "$wx_ldflags"; then
+        QEMU_LDFLAGS="$QEMU_LDFLAGS $wx_ldflags"
+    fi
+fi
+
 qemu_confdir=$sysconfdir$confsuffix
 qemu_moddir=$libdir$confsuffix
 qemu_datadir=$datadir$confsuffix
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
index 1a45eaf..1bfeb89 100644
--- a/contrib/elf2dmp/main.c
+++ b/contrib/elf2dmp/main.c
@@ -524,6 +524,12 @@
         }
     }
 
+    if (!nt_start_addr) {
+        eprintf("Failed to find NT kernel image\n");
+        err = 1;
+        goto out_ps;
+    }
+
     printf("KernBase = 0x%016"PRIx64", signature is \'%.2s\'\n", KernBase,
             (char *)nt_start_addr);
 
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 6ea36d4..bf86128 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -1,6 +1,8 @@
 # Default configuration for ppc-softmmu
 
 # For embedded PPCs:
+CONFIG_MPC_I2C=y
+CONFIG_DS1338=y
 CONFIG_E500=y
 CONFIG_PPC405=y
 CONFIG_PPC440=y
diff --git a/docs/interop/firmware.json b/docs/interop/firmware.json
index 28f9bc1..ff8c2ce 100644
--- a/docs/interop/firmware.json
+++ b/docs/interop/firmware.json
@@ -212,9 +212,13 @@
 #
 # @executable: Identifies the firmware executable. The firmware
 #              executable may be shared by multiple virtual machine
-#              definitions. The corresponding QEMU command line option
-#              is "-drive
-#              if=pflash,unit=0,readonly=on,file=@executable.@filename,format=@executable.@format".
+#              definitions. The preferred corresponding QEMU command
+#              line options are
+#                  -drive if=none,id=pflash0,readonly=on,file=@executable.@filename,format=@executable.@format
+#                  -machine pflash0=pflash0
+#              or equivalent -blockdev instead of -drive.
+#              With QEMU versions older than 4.0, you have to use
+#                  -drive if=pflash,unit=0,readonly=on,file=@executable.@filename,format=@executable.@format
 #
 # @nvram-template: Identifies the NVRAM template compatible with
 #                  @executable. Management software instantiates an
@@ -225,9 +229,13 @@
 #                  individual copies of it are. An NVRAM file is
 #                  typically used for persistently storing the
 #                  non-volatile UEFI variables of a virtual machine
-#                  definition. The corresponding QEMU command line
-#                  option is "-drive
-#                  if=pflash,unit=1,readonly=off,file=FILENAME_OF_PRIVATE_NVRAM_FILE,format=@nvram-template.@format".
+#                  definition. The preferred corresponding QEMU
+#                  command line options are
+#                      -drive if=none,id=pflash1,readonly=off,file=FILENAME_OF_PRIVATE_NVRAM_FILE,format=@nvram-template.@format
+#                      -machine pflash1=pflash1
+#                  or equivalent -blockdev instead of -drive.
+#                  With QEMU versions older than 4.0, you have to use
+#                      -drive if=pflash,unit=1,readonly=off,file=FILENAME_OF_PRIVATE_NVRAM_FILE,format=@nvram-template.@format
 #
 # Since: 3.0
 ##
diff --git a/exec.c b/exec.c
index 1d4f378..86a38d3 100644
--- a/exec.c
+++ b/exec.c
@@ -1599,35 +1599,49 @@
     phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
 }
 
+/*
+ * The range in *section* may look like this:
+ *
+ *      |s|PPPPPPP|s|
+ *
+ * where s stands for subpage and P for page.
+ */
 void flatview_add_to_dispatch(FlatView *fv, MemoryRegionSection *section)
 {
-    MemoryRegionSection now = *section, remain = *section;
+    MemoryRegionSection remain = *section;
     Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
 
-    if (now.offset_within_address_space & ~TARGET_PAGE_MASK) {
-        uint64_t left = TARGET_PAGE_ALIGN(now.offset_within_address_space)
-                       - now.offset_within_address_space;
+    /* register first subpage */
+    if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) {
+        uint64_t left = TARGET_PAGE_ALIGN(remain.offset_within_address_space)
+                        - remain.offset_within_address_space;
 
+        MemoryRegionSection now = remain;
         now.size = int128_min(int128_make64(left), now.size);
         register_subpage(fv, &now);
-    } else {
-        now.size = int128_zero();
-    }
-    while (int128_ne(remain.size, now.size)) {
+        if (int128_eq(remain.size, now.size)) {
+            return;
+        }
         remain.size = int128_sub(remain.size, now.size);
         remain.offset_within_address_space += int128_get64(now.size);
         remain.offset_within_region += int128_get64(now.size);
-        now = remain;
-        if (int128_lt(remain.size, page_size)) {
-            register_subpage(fv, &now);
-        } else if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) {
-            now.size = page_size;
-            register_subpage(fv, &now);
-        } else {
-            now.size = int128_and(now.size, int128_neg(page_size));
-            register_multipage(fv, &now);
-        }
     }
+
+    /* register whole pages */
+    if (int128_ge(remain.size, page_size)) {
+        MemoryRegionSection now = remain;
+        now.size = int128_and(now.size, int128_neg(page_size));
+        register_multipage(fv, &now);
+        if (int128_eq(remain.size, now.size)) {
+            return;
+        }
+        remain.size = int128_sub(remain.size, now.size);
+        remain.offset_within_address_space += int128_get64(now.size);
+        remain.offset_within_region += int128_get64(now.size);
+    }
+
+    /* register last subpage */
+    register_subpage(fv, &remain);
 }
 
 void qemu_flush_coalesced_mmio_buffer(void)
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 8fd25a5..7b98121 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -28,7 +28,6 @@
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
 #include "qemu/range.h"
-#include "hw/nvram/fw_cfg.h"
 #include "exec/address-spaces.h"
 #include "hw/acpi/piix4.h"
 #include "hw/acpi/pcihp.h"
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
index 3ca4e07..d12604c 100644
--- a/hw/arm/collie.c
+++ b/hw/arm/collie.c
@@ -9,6 +9,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 #include "qemu/osdep.h"
+#include "qemu/units.h"
 #include "hw/hw.h"
 #include "hw/sysbus.h"
 #include "hw/boards.h"
@@ -35,14 +36,14 @@
     s = sa1110_init(sysmem, collie_binfo.ram_size, machine->cpu_type);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
+    pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000,
                     dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                    (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+                    64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
     dinfo = drive_get(IF_PFLASH, 0, 1);
-    pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
+    pflash_cfi01_register(SA_CS1, "collie.fl2", 0x02000000,
                     dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                    (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+                    64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
     sysbus_create_simple("scoop", 0x40800000, NULL);
 
diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
index 9f11dcd..304e4d1 100644
--- a/hw/arm/digic_boards.c
+++ b/hw/arm/digic_boards.c
@@ -129,9 +129,8 @@
 #define FLASH_K8P3215UQB_SIZE (4 * 1024 * 1024)
 #define FLASH_K8P3215UQB_SECTOR_SIZE (64 * 1024)
 
-    pflash_cfi02_register(addr, NULL, "pflash", FLASH_K8P3215UQB_SIZE,
+    pflash_cfi02_register(addr, "pflash", FLASH_K8P3215UQB_SIZE,
                           NULL, FLASH_K8P3215UQB_SECTOR_SIZE,
-                          FLASH_K8P3215UQB_SIZE / FLASH_K8P3215UQB_SECTOR_SIZE,
                           DIGIC4_ROM_MAX_SIZE / FLASH_K8P3215UQB_SIZE,
                           4,
                           0x00EC, 0x007E, 0x0003, 0x0001,
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
index 56cb763..79886ce 100644
--- a/hw/arm/gumstix.c
+++ b/hw/arm/gumstix.c
@@ -72,10 +72,9 @@
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
+    if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
                                dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                               sector_len, connex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
+                               sector_len, 2, 0, 0, 0, 0, be)) {
         error_report("Error registering flash memory");
         exit(1);
     }
@@ -109,10 +108,9 @@
 #else
     be = 0;
 #endif
-    if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
+    if (!pflash_cfi01_register(0x00000000, "verdex.rom", verdex_rom,
                                dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                               sector_len, verdex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
+                               sector_len, 2, 0, 0, 0, 0, be)) {
         error_report("Error registering flash memory");
         exit(1);
     }
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index 0beb5c4..e96738a 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -148,12 +148,11 @@
             exit(1);
         }
 
-        if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
+        if (!pflash_cfi01_register(mainstone_flash_base[i],
                                    i ? "mainstone.flash1" : "mainstone.flash0",
                                    MAINSTONE_FLASH,
                                    blk_by_legacy_dinfo(dinfo),
-                                   sector_len, MAINSTONE_FLASH / sector_len,
-                                   4, 0, 0, 0, 0, be)) {
+                                   sector_len, 4, 0, 0, 0, 0, be)) {
             error_report("Error registering flash memory");
             exit(1);
         }
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index de4a12e..93ec3c5 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1635,16 +1635,16 @@
          * image is smaller than 32 MB.
          */
 #ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
+        pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
                               "musicpal.flash", flash_size,
-                              blk, 0x10000, (flash_size + 0xffff) >> 16,
+                              blk, 0x10000,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
-        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
+        pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
                               "musicpal.flash", flash_size,
-                              blk, 0x10000, (flash_size + 0xffff) >> 16,
+                              blk, 0x10000,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 0);
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
index 84550f0..95a4fe7 100644
--- a/hw/arm/omap_sx1.c
+++ b/hw/arm/omap_sx1.c
@@ -152,11 +152,10 @@
 #endif
 
     if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
+        if (!pflash_cfi01_register(OMAP_CS0_BASE,
                                    "omap_sx1.flash0-1", flash_size,
                                    blk_by_legacy_dinfo(dinfo),
-                                   sector_size, flash_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
+                                   sector_size, 4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
         }
@@ -176,11 +175,10 @@
         memory_region_add_subregion(address_space,
                                 OMAP_CS1_BASE + flash1_size, &cs[1]);
 
-        if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
+        if (!pflash_cfi01_register(OMAP_CS1_BASE,
                                    "omap_sx1.flash1-1", flash1_size,
                                    blk_by_legacy_dinfo(dinfo),
-                                   sector_size, flash1_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
+                                   sector_size, 4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
         }
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 22b09a1..d671818 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -365,11 +365,10 @@
     /* 0x34000000 NOR Flash */
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
+    if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
                           VERSATILE_FLASH_SIZE,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           VERSATILE_FLASH_SECT_SIZE,
-                          VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
                           4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
     }
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index c02d18e..f07134c 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -512,10 +512,10 @@
 /* Open code a private version of pflash registration since we
  * need to set non-default device width for VExpress platform.
  */
-static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
-                                          DriveInfo *di)
+static PFlashCFI01 *ve_pflash_cfi01_register(hwaddr base, const char *name,
+                                             DriveInfo *di)
 {
-    DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
+    DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
 
     if (di) {
         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di),
@@ -536,7 +536,7 @@
     qdev_init_nofail(dev);
 
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-    return OBJECT_CHECK(pflash_t, (dev), "cfi.pflash01");
+    return PFLASH_CFI01(dev);
 }
 
 static void vexpress_common_init(MachineState *machine)
@@ -548,7 +548,7 @@
     qemu_irq pic[64];
     uint32_t sys_id;
     DriveInfo *dinfo;
-    pflash_t *pflash0;
+    PFlashCFI01 *pflash0;
     I2CBus *i2c;
     ram_addr_t vram_size, sram_size;
     MemoryRegion *sysmem = get_system_memory();
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7f66dda..ce2664a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -35,6 +35,7 @@
 #include "hw/arm/arm.h"
 #include "hw/arm/primecell.h"
 #include "hw/arm/virt.h"
+#include "hw/block/flash.h"
 #include "hw/vfio/vfio-calxeda-xgmac.h"
 #include "hw/vfio/vfio-amd-xgbe.h"
 #include "hw/display/ramfb.h"
@@ -878,7 +879,7 @@
      * parameters as the flash devices on the Versatile Express board.
      */
     DriveInfo *dinfo = drive_get_next(IF_PFLASH);
-    DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
+    DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     const uint64_t sectorlength = 256 * 1024;
 
@@ -1281,10 +1282,6 @@
     size_t smbios_tables_len, smbios_anchor_len;
     const char *product = "QEMU Virtual Machine";
 
-    if (!vms->fw_cfg) {
-        return;
-    }
-
     if (kvm_enabled()) {
         product = "KVM Virtual Machine";
     }
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 57497b0..b3b8215 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -205,12 +205,11 @@
     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
 
     /* AMD */
-    pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
+    pflash_cfi02_register(0xe2000000, "zynq.pflash", FLASH_SIZE,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          FLASH_SECTOR_SIZE,
-                          FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
+                          FLASH_SECTOR_SIZE, 1,
                           1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
-                              0);
+                          0);
 
     dev = qdev_create(NULL, "xilinx,zynq_slcr");
     qdev_init_nofail(dev);
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 3b75d4b..1f906ef 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -323,11 +323,9 @@
         exit(1);
     }
 
-    if (!pflash_cfi01_register(Z2_FLASH_BASE,
-                               NULL, "z2.flash0", Z2_FLASH_SIZE,
+    if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
                                dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                               sector_len, Z2_FLASH_SIZE / sector_len,
-                               4, 0, 0, 0, 0, be)) {
+                               sector_len, 4, 0, 0, 0, 0, be)) {
         error_report("Error registering flash memory");
         exit(1);
     }
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index bffb4c4..125f70b 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -49,12 +49,6 @@
 #include "sysemu/sysemu.h"
 #include "trace.h"
 
-#define PFLASH_BUG(fmt, ...) \
-do { \
-    fprintf(stderr, "PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \
-    exit(1); \
-} while(0)
-
 /* #define PFLASH_DEBUG */
 #ifdef PFLASH_DEBUG
 #define DPRINTF(fmt, ...)                                   \
@@ -65,12 +59,10 @@
 #define DPRINTF(fmt, ...) do { } while (0)
 #endif
 
-#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
-
 #define PFLASH_BE          0
 #define PFLASH_SECURE      1
 
-struct pflash_t {
+struct PFlashCFI01 {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -109,17 +101,17 @@
     .minimum_version_id = 1,
     .post_load = pflash_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT8(wcycle, pflash_t),
-        VMSTATE_UINT8(cmd, pflash_t),
-        VMSTATE_UINT8(status, pflash_t),
-        VMSTATE_UINT64(counter, pflash_t),
+        VMSTATE_UINT8(wcycle, PFlashCFI01),
+        VMSTATE_UINT8(cmd, PFlashCFI01),
+        VMSTATE_UINT8(status, PFlashCFI01),
+        VMSTATE_UINT64(counter, PFlashCFI01),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static void pflash_timer (void *opaque)
 {
-    pflash_t *pfl = opaque;
+    PFlashCFI01 *pfl = opaque;
 
     trace_pflash_timer_expired(pfl->cmd);
     /* Reset flash */
@@ -133,7 +125,7 @@
  * If this code is called we know we have a device_width set for
  * this flash.
  */
-static uint32_t pflash_cfi_query(pflash_t *pfl, hwaddr offset)
+static uint32_t pflash_cfi_query(PFlashCFI01 *pfl, hwaddr offset)
 {
     int i;
     uint32_t resp = 0;
@@ -193,7 +185,7 @@
 
 
 /* Perform a device id query based on the bank width of the flash. */
-static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
+static uint32_t pflash_devid_query(PFlashCFI01 *pfl, hwaddr offset)
 {
     int i;
     uint32_t resp;
@@ -241,7 +233,7 @@
     return resp;
 }
 
-static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
+static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset,
                                  int width, int be)
 {
     uint8_t *p;
@@ -284,8 +276,8 @@
     return ret;
 }
 
-static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
-                             int width, int be)
+static uint32_t pflash_read(PFlashCFI01 *pfl, hwaddr offset,
+                            int width, int be)
 {
     hwaddr boff;
     uint32_t ret;
@@ -398,7 +390,7 @@
 }
 
 /* update flash content on disk */
-static void pflash_update(pflash_t *pfl, int offset,
+static void pflash_update(PFlashCFI01 *pfl, int offset,
                           int size)
 {
     int offset_end;
@@ -412,7 +404,7 @@
     }
 }
 
-static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
+static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
                                      uint32_t value, int width, int be)
 {
     uint8_t *p = pfl->storage;
@@ -448,7 +440,7 @@
 
 }
 
-static void pflash_write(pflash_t *pfl, hwaddr offset,
+static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
                          uint32_t value, int width, int be)
 {
     uint8_t *p;
@@ -507,6 +499,10 @@
             break;
         case 0xe8: /* Write to buffer */
             DPRINTF("%s: Write to buffer\n", __func__);
+            /* FIXME should save @offset, @width for case 1+ */
+            qemu_log_mask(LOG_UNIMP,
+                          "%s: Write to buffer emulation is flawed\n",
+                          __func__);
             pfl->status |= 0x80; /* Ready! */
             break;
         case 0xf0: /* Probe for AMD flash */
@@ -550,6 +546,7 @@
             /* Mask writeblock size based on device width, or bank width if
              * device width not specified.
              */
+            /* FIXME check @offset, @width */
             if (pfl->device_width) {
                 value = extract32(value, 0, pfl->device_width * 8);
             } else {
@@ -587,7 +584,13 @@
     case 2:
         switch (pfl->cmd) {
         case 0xe8: /* Block write */
+            /* FIXME check @offset, @width */
             if (!pfl->ro) {
+                /*
+                 * FIXME writing straight to memory is *wrong*.  We
+                 * should write to a buffer, and flush it to memory
+                 * only on confirm command (see below).
+                 */
                 pflash_data_write(pfl, offset, value, width, be);
             } else {
                 pfl->status |= 0x10; /* Programming error */
@@ -603,6 +606,7 @@
                 pfl->wcycle++;
                 if (!pfl->ro) {
                     /* Flush the entire write buffer onto backing storage.  */
+                    /* FIXME premature! */
                     pflash_update(pfl, offset & mask, pfl->writeblock_size);
                 } else {
                     pfl->status |= 0x10; /* Programming error */
@@ -619,11 +623,15 @@
         switch (pfl->cmd) {
         case 0xe8: /* Block write */
             if (cmd == 0xd0) {
+                /* FIXME this is where we should write out the buffer */
                 pfl->wcycle = 0;
                 pfl->status |= 0x80;
             } else {
-                DPRINTF("%s: unknown command for \"write block\"\n", __func__);
-                PFLASH_BUG("Write block confirm");
+                qemu_log_mask(LOG_UNIMP,
+                    "%s: Aborting write to buffer not implemented,"
+                    " the data is already written to storage!\n"
+                    "Flash device reset into READ mode.\n",
+                    __func__);
                 goto reset_flash;
             }
             break;
@@ -654,7 +662,7 @@
 static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
                                               unsigned len, MemTxAttrs attrs)
 {
-    pflash_t *pfl = opaque;
+    PFlashCFI01 *pfl = opaque;
     bool be = !!(pfl->features & (1 << PFLASH_BE));
 
     if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
@@ -668,7 +676,7 @@
 static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
                                                unsigned len, MemTxAttrs attrs)
 {
-    pflash_t *pfl = opaque;
+    PFlashCFI01 *pfl = opaque;
     bool be = !!(pfl->features & (1 << PFLASH_BE));
 
     if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
@@ -687,7 +695,7 @@
 
 static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
 {
-    pflash_t *pfl = CFI_PFLASH01(dev);
+    PFlashCFI01 *pfl = PFLASH_CFI01(dev);
     uint64_t total_len;
     int ret;
     uint64_t blocks_per_device, sector_len_per_device, device_len;
@@ -864,14 +872,14 @@
 }
 
 static Property pflash_cfi01_properties[] = {
-    DEFINE_PROP_DRIVE("drive", struct pflash_t, blk),
+    DEFINE_PROP_DRIVE("drive", PFlashCFI01, blk),
     /* num-blocks is the number of blocks actually visible to the guest,
      * ie the total size of the device divided by the sector length.
      * If we're emulating flash devices wired in parallel the actual
      * number of blocks per indvidual device will differ.
      */
-    DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
-    DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
+    DEFINE_PROP_UINT32("num-blocks", PFlashCFI01, nb_blocs, 0),
+    DEFINE_PROP_UINT64("sector-length", PFlashCFI01, sector_len, 0),
     /* width here is the overall width of this QEMU device in bytes.
      * The QEMU device may be emulating a number of flash devices
      * wired up in parallel; the width of each individual flash
@@ -888,17 +896,17 @@
      * 16 bit devices making up a 32 bit wide QEMU device. This
      * is deprecated for new uses of this device.
      */
-    DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0),
-    DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
-    DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0),
-    DEFINE_PROP_BIT("big-endian", struct pflash_t, features, PFLASH_BE, 0),
-    DEFINE_PROP_BIT("secure", struct pflash_t, features, PFLASH_SECURE, 0),
-    DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
-    DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
-    DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
-    DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
-    DEFINE_PROP_STRING("name", struct pflash_t, name),
-    DEFINE_PROP_BOOL("old-multiple-chip-handling", struct pflash_t,
+    DEFINE_PROP_UINT8("width", PFlashCFI01, bank_width, 0),
+    DEFINE_PROP_UINT8("device-width", PFlashCFI01, device_width, 0),
+    DEFINE_PROP_UINT8("max-device-width", PFlashCFI01, max_device_width, 0),
+    DEFINE_PROP_BIT("big-endian", PFlashCFI01, features, PFLASH_BE, 0),
+    DEFINE_PROP_BIT("secure", PFlashCFI01, features, PFLASH_SECURE, 0),
+    DEFINE_PROP_UINT16("id0", PFlashCFI01, ident0, 0),
+    DEFINE_PROP_UINT16("id1", PFlashCFI01, ident1, 0),
+    DEFINE_PROP_UINT16("id2", PFlashCFI01, ident2, 0),
+    DEFINE_PROP_UINT16("id3", PFlashCFI01, ident3, 0),
+    DEFINE_PROP_STRING("name", PFlashCFI01, name),
+    DEFINE_PROP_BOOL("old-multiple-chip-handling", PFlashCFI01,
                      old_multiple_chip_handling, false),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -915,9 +923,9 @@
 
 
 static const TypeInfo pflash_cfi01_info = {
-    .name           = TYPE_CFI_PFLASH01,
+    .name           = TYPE_PFLASH_CFI01,
     .parent         = TYPE_SYS_BUS_DEVICE,
-    .instance_size  = sizeof(struct pflash_t),
+    .instance_size  = sizeof(PFlashCFI01),
     .class_init     = pflash_cfi01_class_init,
 };
 
@@ -928,20 +936,23 @@
 
 type_init(pflash_cfi01_register_types)
 
-pflash_t *pflash_cfi01_register(hwaddr base,
-                                DeviceState *qdev, const char *name,
-                                hwaddr size,
-                                BlockBackend *blk,
-                                uint32_t sector_len, int nb_blocs,
-                                int bank_width, uint16_t id0, uint16_t id1,
-                                uint16_t id2, uint16_t id3, int be)
+PFlashCFI01 *pflash_cfi01_register(hwaddr base,
+                                   const char *name,
+                                   hwaddr size,
+                                   BlockBackend *blk,
+                                   uint32_t sector_len,
+                                   int bank_width,
+                                   uint16_t id0, uint16_t id1,
+                                   uint16_t id2, uint16_t id3,
+                                   int be)
 {
-    DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
+    DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
 
     if (blk) {
         qdev_prop_set_drive(dev, "drive", blk, &error_abort);
     }
-    qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
+    assert(size % sector_len == 0);
+    qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
     qdev_prop_set_uint64(dev, "sector-length", sector_len);
     qdev_prop_set_uint8(dev, "width", bank_width);
     qdev_prop_set_bit(dev, "big-endian", !!be);
@@ -953,17 +964,22 @@
     qdev_init_nofail(dev);
 
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-    return CFI_PFLASH01(dev);
+    return PFLASH_CFI01(dev);
 }
 
-MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl)
+BlockBackend *pflash_cfi01_get_blk(PFlashCFI01 *fl)
+{
+    return fl->blk;
+}
+
+MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl)
 {
     return &fl->mem;
 }
 
 static void postload_update_cb(void *opaque, int running, RunState state)
 {
-    pflash_t *pfl = opaque;
+    PFlashCFI01 *pfl = opaque;
 
     /* This is called after bdrv_invalidate_cache_all.  */
     qemu_del_vm_change_state_handler(pfl->vmstate);
@@ -975,7 +991,7 @@
 
 static int pflash_post_load(void *opaque, int version_id)
 {
-    pflash_t *pfl = opaque;
+    PFlashCFI01 *pfl = opaque;
 
     if (!pfl->ro) {
         pfl->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 1588aef..c9db430 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -57,9 +57,7 @@
 
 #define PFLASH_LAZY_ROMD_THRESHOLD 42
 
-#define CFI_PFLASH02(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH02)
-
-struct pflash_t {
+struct PFlashCFI02 {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
@@ -101,7 +99,7 @@
 /*
  * Set up replicated mappings of the same region.
  */
-static void pflash_setup_mappings(pflash_t *pfl)
+static void pflash_setup_mappings(PFlashCFI02 *pfl)
 {
     unsigned i;
     hwaddr size = memory_region_size(&pfl->orig_mem);
@@ -115,7 +113,7 @@
     }
 }
 
-static void pflash_register_memory(pflash_t *pfl, int rom_mode)
+static void pflash_register_memory(PFlashCFI02 *pfl, int rom_mode)
 {
     memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode);
     pfl->rom_mode = rom_mode;
@@ -123,7 +121,7 @@
 
 static void pflash_timer (void *opaque)
 {
-    pflash_t *pfl = opaque;
+    PFlashCFI02 *pfl = opaque;
 
     trace_pflash_timer_expired(pfl->cmd);
     /* Reset flash */
@@ -137,8 +135,8 @@
     pfl->cmd = 0;
 }
 
-static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
-                             int width, int be)
+static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset,
+                            int width, int be)
 {
     hwaddr boff;
     uint32_t ret;
@@ -246,7 +244,7 @@
 }
 
 /* update flash content on disk */
-static void pflash_update(pflash_t *pfl, int offset,
+static void pflash_update(PFlashCFI02 *pfl, int offset,
                           int size)
 {
     int offset_end;
@@ -260,8 +258,8 @@
     }
 }
 
-static void pflash_write (pflash_t *pfl, hwaddr offset,
-                          uint32_t value, int width, int be)
+static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
+                         uint32_t value, int width, int be)
 {
     hwaddr boff;
     uint8_t *p;
@@ -533,7 +531,7 @@
 
 static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
 {
-    pflash_t *pfl = CFI_PFLASH02(dev);
+    PFlashCFI02 *pfl = PFLASH_CFI02(dev);
     uint32_t chip_len;
     int ret;
     Error *local_err = NULL;
@@ -679,25 +677,25 @@
 }
 
 static Property pflash_cfi02_properties[] = {
-    DEFINE_PROP_DRIVE("drive", struct pflash_t, blk),
-    DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
-    DEFINE_PROP_UINT32("sector-length", struct pflash_t, sector_len, 0),
-    DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
-    DEFINE_PROP_UINT8("mappings", struct pflash_t, mappings, 0),
-    DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
-    DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
-    DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
-    DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
-    DEFINE_PROP_UINT16("id3", struct pflash_t, ident3, 0),
-    DEFINE_PROP_UINT16("unlock-addr0", struct pflash_t, unlock_addr0, 0),
-    DEFINE_PROP_UINT16("unlock-addr1", struct pflash_t, unlock_addr1, 0),
-    DEFINE_PROP_STRING("name", struct pflash_t, name),
+    DEFINE_PROP_DRIVE("drive", PFlashCFI02, blk),
+    DEFINE_PROP_UINT32("num-blocks", PFlashCFI02, nb_blocs, 0),
+    DEFINE_PROP_UINT32("sector-length", PFlashCFI02, sector_len, 0),
+    DEFINE_PROP_UINT8("width", PFlashCFI02, width, 0),
+    DEFINE_PROP_UINT8("mappings", PFlashCFI02, mappings, 0),
+    DEFINE_PROP_UINT8("big-endian", PFlashCFI02, be, 0),
+    DEFINE_PROP_UINT16("id0", PFlashCFI02, ident0, 0),
+    DEFINE_PROP_UINT16("id1", PFlashCFI02, ident1, 0),
+    DEFINE_PROP_UINT16("id2", PFlashCFI02, ident2, 0),
+    DEFINE_PROP_UINT16("id3", PFlashCFI02, ident3, 0),
+    DEFINE_PROP_UINT16("unlock-addr0", PFlashCFI02, unlock_addr0, 0),
+    DEFINE_PROP_UINT16("unlock-addr1", PFlashCFI02, unlock_addr1, 0),
+    DEFINE_PROP_STRING("name", PFlashCFI02, name),
     DEFINE_PROP_END_OF_LIST(),
 };
 
 static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp)
 {
-    pflash_t *pfl = CFI_PFLASH02(dev);
+    PFlashCFI02 *pfl = PFLASH_CFI02(dev);
     timer_del(&pfl->timer);
 }
 
@@ -712,9 +710,9 @@
 }
 
 static const TypeInfo pflash_cfi02_info = {
-    .name           = TYPE_CFI_PFLASH02,
+    .name           = TYPE_PFLASH_CFI02,
     .parent         = TYPE_SYS_BUS_DEVICE,
-    .instance_size  = sizeof(struct pflash_t),
+    .instance_size  = sizeof(PFlashCFI02),
     .class_init     = pflash_cfi02_class_init,
 };
 
@@ -725,22 +723,25 @@
 
 type_init(pflash_cfi02_register_types)
 
-pflash_t *pflash_cfi02_register(hwaddr base,
-                                DeviceState *qdev, const char *name,
-                                hwaddr size,
-                                BlockBackend *blk, uint32_t sector_len,
-                                int nb_blocs, int nb_mappings, int width,
-                                uint16_t id0, uint16_t id1,
-                                uint16_t id2, uint16_t id3,
-                                uint16_t unlock_addr0, uint16_t unlock_addr1,
-                                int be)
+PFlashCFI02 *pflash_cfi02_register(hwaddr base,
+                                   const char *name,
+                                   hwaddr size,
+                                   BlockBackend *blk,
+                                   uint32_t sector_len,
+                                   int nb_mappings, int width,
+                                   uint16_t id0, uint16_t id1,
+                                   uint16_t id2, uint16_t id3,
+                                   uint16_t unlock_addr0,
+                                   uint16_t unlock_addr1,
+                                   int be)
 {
-    DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH02);
+    DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI02);
 
     if (blk) {
         qdev_prop_set_drive(dev, "drive", blk, &error_abort);
     }
-    qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
+    assert(size % sector_len == 0);
+    qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
     qdev_prop_set_uint32(dev, "sector-length", sector_len);
     qdev_prop_set_uint8(dev, "width", width);
     qdev_prop_set_uint8(dev, "mappings", nb_mappings);
@@ -755,5 +756,5 @@
     qdev_init_nofail(dev);
 
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-    return CFI_PFLASH02(dev);
+    return PFLASH_CFI02(dev);
 }
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 6748334..617303d 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -10,27 +10,27 @@
 
 #define VTERM_BUFSIZE   16
 
-typedef struct VIOsPAPRVTYDevice {
-    VIOsPAPRDevice sdev;
+typedef struct SpaprVioVty {
+    SpaprVioDevice sdev;
     CharBackend chardev;
     uint32_t in, out;
     uint8_t buf[VTERM_BUFSIZE];
-} VIOsPAPRVTYDevice;
+} SpaprVioVty;
 
 #define TYPE_VIO_SPAPR_VTY_DEVICE "spapr-vty"
 #define VIO_SPAPR_VTY_DEVICE(obj) \
-     OBJECT_CHECK(VIOsPAPRVTYDevice, (obj), TYPE_VIO_SPAPR_VTY_DEVICE)
+     OBJECT_CHECK(SpaprVioVty, (obj), TYPE_VIO_SPAPR_VTY_DEVICE)
 
 static int vty_can_receive(void *opaque)
 {
-    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
+    SpaprVioVty *dev = VIO_SPAPR_VTY_DEVICE(opaque);
 
     return VTERM_BUFSIZE - (dev->in - dev->out);
 }
 
 static void vty_receive(void *opaque, const uint8_t *buf, int size)
 {
-    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
+    SpaprVioVty *dev = VIO_SPAPR_VTY_DEVICE(opaque);
     int i;
 
     if ((dev->in == dev->out) && size) {
@@ -51,9 +51,9 @@
     }
 }
 
-static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
+static int vty_getchars(SpaprVioDevice *sdev, uint8_t *buf, int max)
 {
-    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
+    SpaprVioVty *dev = VIO_SPAPR_VTY_DEVICE(sdev);
     int n = 0;
 
     while ((n < max) && (dev->out != dev->in)) {
@@ -83,18 +83,18 @@
     return n;
 }
 
-void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
+void vty_putchars(SpaprVioDevice *sdev, uint8_t *buf, int len)
 {
-    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
+    SpaprVioVty *dev = VIO_SPAPR_VTY_DEVICE(sdev);
 
     /* XXX this blocks entire thread. Rewrite to use
      * qemu_chr_fe_write and background I/O callbacks */
     qemu_chr_fe_write_all(&dev->chardev, buf, len);
 }
 
-static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
+static void spapr_vty_realize(SpaprVioDevice *sdev, Error **errp)
 {
-    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
+    SpaprVioVty *dev = VIO_SPAPR_VTY_DEVICE(sdev);
 
     if (!qemu_chr_fe_backend_connected(&dev->chardev)) {
         error_setg(errp, "chardev property not set");
@@ -106,14 +106,14 @@
 }
 
 /* Forward declaration */
-static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_put_term_char(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong len = args[1];
     target_ulong char0_7 = args[2];
     target_ulong char8_15 = args[3];
-    VIOsPAPRDevice *sdev;
+    SpaprVioDevice *sdev;
     uint8_t buf[16];
 
     sdev = vty_lookup(spapr, reg);
@@ -133,14 +133,14 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_get_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_get_term_char(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong *len = args + 0;
     target_ulong *char0_7 = args + 1;
     target_ulong *char8_15 = args + 2;
-    VIOsPAPRDevice *sdev;
+    SpaprVioDevice *sdev;
     uint8_t buf[16];
 
     sdev = vty_lookup(spapr, reg);
@@ -159,7 +159,7 @@
     return H_SUCCESS;
 }
 
-void spapr_vty_create(VIOsPAPRBus *bus, Chardev *chardev)
+void spapr_vty_create(SpaprVioBus *bus, Chardev *chardev)
 {
     DeviceState *dev;
 
@@ -169,8 +169,8 @@
 }
 
 static Property spapr_vty_properties[] = {
-    DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev),
-    DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
+    DEFINE_SPAPR_PROPERTIES(SpaprVioVty, sdev),
+    DEFINE_PROP_CHR("chardev", SpaprVioVty, chardev),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -179,11 +179,11 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_SPAPR_VIO(sdev, VIOsPAPRVTYDevice),
+        VMSTATE_SPAPR_VIO(sdev, SpaprVioVty),
 
-        VMSTATE_UINT32(in, VIOsPAPRVTYDevice),
-        VMSTATE_UINT32(out, VIOsPAPRVTYDevice),
-        VMSTATE_BUFFER(buf, VIOsPAPRVTYDevice),
+        VMSTATE_UINT32(in, SpaprVioVty),
+        VMSTATE_UINT32(out, SpaprVioVty),
+        VMSTATE_BUFFER(buf, SpaprVioVty),
         VMSTATE_END_OF_LIST()
     },
 };
@@ -191,7 +191,7 @@
 static void spapr_vty_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+    SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
 
     k->realize = spapr_vty_realize;
     k->dt_name = "vty";
@@ -205,13 +205,13 @@
 static const TypeInfo spapr_vty_info = {
     .name          = TYPE_VIO_SPAPR_VTY_DEVICE,
     .parent        = TYPE_VIO_SPAPR_DEVICE,
-    .instance_size = sizeof(VIOsPAPRVTYDevice),
+    .instance_size = sizeof(SpaprVioVty),
     .class_init    = spapr_vty_class_init,
 };
 
-VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
+SpaprVioDevice *spapr_vty_get_default(SpaprVioBus *bus)
 {
-    VIOsPAPRDevice *sdev, *selected;
+    SpaprVioDevice *sdev, *selected;
     BusChild *kid;
 
     /*
@@ -246,9 +246,9 @@
     return selected;
 }
 
-VIOsPAPRDevice *vty_lookup(sPAPRMachineState *spapr, target_ulong reg)
+SpaprVioDevice *vty_lookup(SpaprMachineState *spapr, target_ulong reg)
 {
-    VIOsPAPRDevice *sdev;
+    SpaprVioDevice *sdev;
 
     sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
     if (!sdev && reg == 0) {
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 512ce7c..f9b6efe 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -978,25 +978,12 @@
     QLIST_INIT(&dev->gpios);
 }
 
-void object_apply_compat_props(Object *obj)
-{
-    if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) {
-        MachineState *m = MACHINE(qdev_get_machine());
-        MachineClass *mc = MACHINE_GET_CLASS(m);
-
-        if (m->accelerator) {
-            AccelClass *ac = ACCEL_GET_CLASS(m->accelerator);
-
-            if (ac->compat_props) {
-                object_apply_global_props(obj, ac->compat_props, &error_abort);
-            }
-        }
-        object_apply_global_props(obj, mc->compat_props, &error_abort);
-    }
-}
-
 static void device_post_init(Object *obj)
 {
+    /*
+     * Note: ordered so that the user's global properties take
+     * precedence.
+     */
     object_apply_compat_props(obj);
     qdev_prop_set_globals(DEVICE(obj));
 }
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index 9f9edbc..307cf90 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -357,9 +357,6 @@
     qbus_create_inplace(main_system_bus, system_bus_info.instance_size,
                         TYPE_SYSTEM_BUS, NULL, "main-system-bus");
     OBJECT(main_system_bus)->free = g_free;
-    object_property_add_child(container_get(qdev_get_machine(),
-                                            "/unattached"),
-                              "sysbus", OBJECT(main_system_bus), NULL);
 }
 
 BusState *sysbus_get_default(void)
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
index ef1caa6..820b24d 100644
--- a/hw/i2c/Kconfig
+++ b/hw/i2c/Kconfig
@@ -25,3 +25,7 @@
 config IMX_I2C
     bool
     select I2C
+
+config MPC_I2C
+    bool
+    select I2C
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index 2a3c106..5f76b6a 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -9,5 +9,6 @@
 common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
 common-obj-$(CONFIG_NRF51_SOC) += microbit_i2c.o
+common-obj-$(CONFIG_MPC_I2C) += mpc_i2c.o
 obj-$(CONFIG_OMAP) += omap_i2c.o
 obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c
new file mode 100644
index 0000000..693ca7e
--- /dev/null
+++ b/hw/i2c/mpc_i2c.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Amit Tomar, <Amit.Tomar@freescale.com>
+ *
+ * Description:
+ * This file is derived from IMX I2C controller,
+ * by Jean-Christophe DUBOIS .
+ *
+ * Thanks to Scott Wood and Alexander Graf for their kind help on this.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 or later,
+ * as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/i2c/i2c.h"
+#include "qemu/log.h"
+#include "hw/sysbus.h"
+
+/* #define DEBUG_I2C */
+
+#ifdef DEBUG_I2C
+#define DPRINTF(fmt, ...)              \
+    do { fprintf(stderr, "mpc_i2c[%s]: " fmt, __func__, ## __VA_ARGS__); \
+    } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+
+#define TYPE_MPC_I2C "mpc-i2c"
+#define MPC_I2C(obj) \
+    OBJECT_CHECK(MPCI2CState, (obj), TYPE_MPC_I2C)
+
+#define MPC_I2C_ADR   0x00
+#define MPC_I2C_FDR   0x04
+#define MPC_I2C_CR    0x08
+#define MPC_I2C_SR    0x0c
+#define MPC_I2C_DR    0x10
+#define MPC_I2C_DFSRR 0x14
+
+#define CCR_MEN  (1 << 7)
+#define CCR_MIEN (1 << 6)
+#define CCR_MSTA (1 << 5)
+#define CCR_MTX  (1 << 4)
+#define CCR_TXAK (1 << 3)
+#define CCR_RSTA (1 << 2)
+#define CCR_BCST (1 << 0)
+
+#define CSR_MCF  (1 << 7)
+#define CSR_MAAS (1 << 6)
+#define CSR_MBB  (1 << 5)
+#define CSR_MAL  (1 << 4)
+#define CSR_SRW  (1 << 2)
+#define CSR_MIF  (1 << 1)
+#define CSR_RXAK (1 << 0)
+
+#define CADR_MASK 0xFE
+#define CFDR_MASK 0x3F
+#define CCR_MASK  0xFC
+#define CSR_MASK  0xED
+#define CDR_MASK  0xFF
+
+#define CYCLE_RESET 0xFF
+
+typedef struct MPCI2CState {
+    SysBusDevice parent_obj;
+
+    I2CBus *bus;
+    qemu_irq irq;
+    MemoryRegion iomem;
+
+    uint8_t address;
+    uint8_t adr;
+    uint8_t fdr;
+    uint8_t cr;
+    uint8_t sr;
+    uint8_t dr;
+    uint8_t dfssr;
+} MPCI2CState;
+
+static bool mpc_i2c_is_enabled(MPCI2CState *s)
+{
+    return s->cr & CCR_MEN;
+}
+
+static bool mpc_i2c_is_master(MPCI2CState *s)
+{
+    return s->cr & CCR_MSTA;
+}
+
+static bool mpc_i2c_direction_is_tx(MPCI2CState *s)
+{
+    return s->cr & CCR_MTX;
+}
+
+static bool mpc_i2c_irq_pending(MPCI2CState *s)
+{
+    return s->sr & CSR_MIF;
+}
+
+static bool mpc_i2c_irq_is_enabled(MPCI2CState *s)
+{
+    return s->cr & CCR_MIEN;
+}
+
+static void mpc_i2c_reset(DeviceState *dev)
+{
+    MPCI2CState *i2c = MPC_I2C(dev);
+
+    i2c->address = 0xFF;
+    i2c->adr = 0x00;
+    i2c->fdr = 0x00;
+    i2c->cr =  0x00;
+    i2c->sr =  0x81;
+    i2c->dr =  0x00;
+}
+
+static void mpc_i2c_irq(MPCI2CState *s)
+{
+    bool irq_active = false;
+
+    if (mpc_i2c_is_enabled(s) && mpc_i2c_irq_is_enabled(s)
+                              && mpc_i2c_irq_pending(s)) {
+        irq_active = true;
+    }
+
+    if (irq_active) {
+        qemu_irq_raise(s->irq);
+    } else {
+        qemu_irq_lower(s->irq);
+    }
+}
+
+static void mpc_i2c_soft_reset(MPCI2CState *s)
+{
+    /* This is a soft reset. ADR is preserved during soft resets */
+    uint8_t adr = s->adr;
+    mpc_i2c_reset(DEVICE(s));
+    s->adr = adr;
+}
+
+static void  mpc_i2c_address_send(MPCI2CState *s)
+{
+    /* if returns non zero slave address is not right */
+    if (i2c_start_transfer(s->bus, s->dr >> 1, s->dr & (0x01))) {
+        s->sr |= CSR_RXAK;
+    } else {
+        s->address = s->dr;
+        s->sr &= ~CSR_RXAK;
+        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    }
+}
+
+static void  mpc_i2c_data_send(MPCI2CState *s)
+{
+    if (i2c_send(s->bus, s->dr)) {
+        /* End of transfer */
+        s->sr |= CSR_RXAK;
+        i2c_end_transfer(s->bus);
+    } else {
+        s->sr &= ~CSR_RXAK;
+        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    }
+}
+
+static void  mpc_i2c_data_recive(MPCI2CState *s)
+{
+    int ret;
+    /* get the next byte */
+    ret = i2c_recv(s->bus);
+    if (ret >= 0) {
+        s->sr |= CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |= CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    } else {
+        DPRINTF("read failed for device");
+        ret = 0xff;
+    }
+    s->dr = ret;
+}
+
+static uint64_t mpc_i2c_read(void *opaque, hwaddr addr, unsigned size)
+{
+    MPCI2CState *s = opaque;
+    uint8_t value;
+
+    switch (addr) {
+    case MPC_I2C_ADR:
+        value = s->adr;
+        break;
+    case MPC_I2C_FDR:
+        value = s->fdr;
+        break;
+    case MPC_I2C_CR:
+        value = s->cr;
+        break;
+    case MPC_I2C_SR:
+        value = s->sr;
+        break;
+    case MPC_I2C_DR:
+        value = s->dr;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            if (mpc_i2c_direction_is_tx(s)) {
+                DPRINTF("MTX is set not in recv mode\n");
+            } else {
+                mpc_i2c_data_recive(s);
+            }
+        }
+        break;
+    default:
+        value = 0;
+        DPRINTF("ERROR: Bad read addr 0x%x\n", (unsigned int)addr);
+        break;
+    }
+
+    DPRINTF("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__,
+                                         addr, value);
+    return (uint64_t)value;
+}
+
+static void mpc_i2c_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    MPCI2CState *s = opaque;
+
+    DPRINTF("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n", __func__,
+                                             addr, value);
+    switch (addr) {
+    case MPC_I2C_ADR:
+        s->adr = value & CADR_MASK;
+        break;
+    case MPC_I2C_FDR:
+        s->fdr = value & CFDR_MASK;
+        break;
+    case MPC_I2C_CR:
+        if (mpc_i2c_is_enabled(s) && ((value & CCR_MEN) == 0)) {
+            mpc_i2c_soft_reset(s);
+            break;
+        }
+        /* normal write */
+        s->cr = value & CCR_MASK;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            /* set the bus to busy after master is set as per RM */
+            s->sr |= CSR_MBB;
+        } else {
+            /* bus is not busy anymore */
+            s->sr &= ~CSR_MBB;
+            /* Reset the address for fresh write/read cycle */
+        if (s->address != CYCLE_RESET) {
+            i2c_end_transfer(s->bus);
+            s->address = CYCLE_RESET;
+            }
+        }
+        /* For restart end the onging transfer */
+        if (s->cr & CCR_RSTA) {
+            if (s->address != CYCLE_RESET) {
+                s->address = CYCLE_RESET;
+                i2c_end_transfer(s->bus);
+                s->cr &= ~CCR_RSTA;
+            }
+        }
+        break;
+    case MPC_I2C_SR:
+        s->sr = value & CSR_MASK;
+        /* Lower the interrupt */
+        if (!(s->sr & CSR_MIF) || !(s->sr & CSR_MAL)) {
+            mpc_i2c_irq(s);
+        }
+        break;
+    case MPC_I2C_DR:
+        /* if the device is not enabled, nothing to do */
+        if (!mpc_i2c_is_enabled(s)) {
+            break;
+        }
+        s->dr = value & CDR_MASK;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            if (s->address == CYCLE_RESET) {
+                mpc_i2c_address_send(s);
+            } else {
+                mpc_i2c_data_send(s);
+            }
+        }
+        break;
+    case MPC_I2C_DFSRR:
+        s->dfssr = value;
+        break;
+    default:
+        DPRINTF("ERROR: Bad write addr 0x%x\n", (unsigned int)addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps i2c_ops = {
+    .read =  mpc_i2c_read,
+    .write =  mpc_i2c_write,
+    .valid.max_access_size = 1,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription mpc_i2c_vmstate = {
+    .name = TYPE_MPC_I2C,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(address, MPCI2CState),
+        VMSTATE_UINT8(adr, MPCI2CState),
+        VMSTATE_UINT8(fdr, MPCI2CState),
+        VMSTATE_UINT8(cr, MPCI2CState),
+        VMSTATE_UINT8(sr, MPCI2CState),
+        VMSTATE_UINT8(dr, MPCI2CState),
+        VMSTATE_UINT8(dfssr, MPCI2CState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mpc_i2c_realize(DeviceState *dev, Error **errp)
+{
+    MPCI2CState  *i2c = MPC_I2C(dev);
+    sysbus_init_irq(SYS_BUS_DEVICE(dev), &i2c->irq);
+    memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c,
+                          "mpc-i2c", 0x14);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem);
+    i2c->bus = i2c_init_bus(DEVICE(dev), "i2c");
+}
+
+static void mpc_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd  = &mpc_i2c_vmstate ;
+    dc->reset = mpc_i2c_reset;
+    dc->realize = mpc_i2c_realize;
+    dc->desc = "MPC I2C Controller";
+}
+
+static const TypeInfo mpc_i2c_type_info = {
+    .name          = TYPE_MPC_I2C,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MPCI2CState),
+    .class_init    = mpc_i2c_class_init,
+};
+
+static void mpc_i2c_register_types(void)
+{
+    type_register_static(&mpc_i2c_type_info);
+}
+
+type_init(mpc_i2c_register_types)
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 8ad707a..6eabdf9 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -2,7 +2,7 @@
  * QEMU emulation of AMD IOMMU (AMD-Vi)
  *
  * Copyright (C) 2011 Eduard - Gabriel Munteanu
- * Copyright (C) 2015 David Kiarie, <davidkiarie4@gmail.com>
+ * Copyright (C) 2015, 2016 David Kiarie Kahurani
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index c52886f..0ff9095 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -2,7 +2,7 @@
  * QEMU emulation of an AMD IOMMU (AMD-Vi)
  *
  * Copyright (C) 2011 Eduard - Gabriel Munteanu
- * Copyright (C) 2015 David Kiarie, <davidkiarie4@gmail.com>
+ * Copyright (C) 2015, 2016 David Kiarie Kahurani
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 4212818..d71dc28 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -136,6 +136,7 @@
     { "Icelake-Client" "-" TYPE_X86_CPU,      "mpx", "on" },
     { "Icelake-Server" "-" TYPE_X86_CPU,      "mpx", "on" },
     { "Cascadelake-Server" "-" TYPE_X86_CPU, "stepping", "5" },
+    { TYPE_X86_CPU, "x-intel-pt-auto-level", "off" },
 };
 const size_t pc_compat_3_1_len = G_N_ELEMENTS(pc_compat_3_1);
 
@@ -1210,6 +1211,17 @@
         protocol = lduw_p(header+0x206);
     } else {
         /*
+         * This could be a multiboot kernel. If it is, let's stop treating it
+         * like a Linux kernel.
+         * Note: some multiboot images could be in the ELF format (the same of
+         * PVH), so we try multiboot first since we check the multiboot magic
+         * header before to load it.
+         */
+        if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
+                           kernel_cmdline, kernel_size, header)) {
+            return;
+        }
+        /*
          * Check if the file is an uncompressed kernel file (ELF) and load it,
          * saving the PVH entry point used by the x86/HVM direct boot ABI.
          * If load_elfboot() is successful, populate the fw_cfg info.
@@ -1262,12 +1274,6 @@
 
             return;
         }
-        /* This looks like a multiboot kernel. If it is, let's stop
-           treating it like a Linux kernel. */
-        if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
-                           kernel_cmdline, kernel_size, header)) {
-            return;
-        }
         protocol = 0;
     }
 
@@ -1803,7 +1809,7 @@
     }
 
     /* Initialize PC system firmware */
-    pc_system_firmware_init(rom_memory, !pcmc->pci_enabled);
+    pc_system_firmware_init(pcms, rom_memory);
 
     option_rom_mr = g_malloc(sizeof(*option_rom_mr));
     memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE,
@@ -2643,6 +2649,8 @@
     pcms->smbus_enabled = true;
     pcms->sata_enabled = true;
     pcms->pit_enabled = true;
+
+    pc_system_flash_create(pcms);
 }
 
 static void pc_machine_reset(void)
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 091e22d..c628540 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -40,10 +40,16 @@
 
 #define BIOS_FILENAME "bios.bin"
 
-typedef struct PcSysFwDevice {
-    SysBusDevice busdev;
-    uint8_t isapc_ram_fw;
-} PcSysFwDevice;
+/*
+ * We don't have a theoretically justifiable exact lower bound on the base
+ * address of any flash mapping. In practice, the IO-APIC MMIO range is
+ * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
+ * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
+ * size.
+ */
+#define FLASH_SIZE_LIMIT (8 * MiB)
+
+#define FLASH_SECTOR_SIZE 4096
 
 static void pc_isa_bios_init(MemoryRegion *rom_memory,
                              MemoryRegion *flash_mem,
@@ -76,100 +82,118 @@
     memory_region_set_readonly(isa_bios, true);
 }
 
-#define FLASH_MAP_UNIT_MAX 2
+static PFlashCFI01 *pc_pflash_create(PCMachineState *pcms,
+                                     const char *name,
+                                     const char *alias_prop_name)
+{
+    DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
 
-/* We don't have a theoretically justifiable exact lower bound on the base
- * address of any flash mapping. In practice, the IO-APIC MMIO range is
- * [0xFEE00000..0xFEE01000[ -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
- * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
- * size.
- */
-#define FLASH_MAP_BASE_MIN ((hwaddr)(4 * GiB - 8 * MiB))
+    qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE);
+    qdev_prop_set_uint8(dev, "width", 1);
+    qdev_prop_set_string(dev, "name", name);
+    object_property_add_child(OBJECT(pcms), name, OBJECT(dev),
+                              &error_abort);
+    object_property_add_alias(OBJECT(pcms), alias_prop_name,
+                              OBJECT(dev), "drive", &error_abort);
+    return PFLASH_CFI01(dev);
+}
 
-/* This function maps flash drives from 4G downward, in order of their unit
- * numbers. The mapping starts at unit#0, with unit number increments of 1, and
- * stops before the first missing flash drive, or before
- * unit#FLASH_MAP_UNIT_MAX, whichever is reached first.
+void pc_system_flash_create(PCMachineState *pcms)
+{
+    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+
+    if (pcmc->pci_enabled) {
+        pcms->flash[0] = pc_pflash_create(pcms, "system.flash0",
+                                          "pflash0");
+        pcms->flash[1] = pc_pflash_create(pcms, "system.flash1",
+                                          "pflash1");
+    }
+}
+
+static void pc_system_flash_cleanup_unused(PCMachineState *pcms)
+{
+    char *prop_name;
+    int i;
+    Object *dev_obj;
+
+    assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled);
+
+    for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
+        dev_obj = OBJECT(pcms->flash[i]);
+        if (!object_property_get_bool(dev_obj, "realized", &error_abort)) {
+            prop_name = g_strdup_printf("pflash%d", i);
+            object_property_del(OBJECT(pcms), prop_name, &error_abort);
+            g_free(prop_name);
+            object_unparent(dev_obj);
+            pcms->flash[i] = NULL;
+        }
+    }
+}
+
+/*
+ * Map the pcms->flash[] from 4GiB downward, and realize.
+ * Map them in descending order, i.e. pcms->flash[0] at the top,
+ * without gaps.
+ * Stop at the first pcms->flash[0] lacking a block backend.
+ * Set each flash's size from its block backend.  Fatal error if the
+ * size isn't a non-zero multiple of 4KiB, or the total size exceeds
+ * FLASH_SIZE_LIMIT.
  *
- * Addressing within one flash drive is of course not reversed.
- *
- * An error message is printed and the process exits if:
- * - the size of the backing file for a flash drive is non-positive, or not a
- *   multiple of the required sector size, or
- * - the current mapping's base address would fall below FLASH_MAP_BASE_MIN.
- *
- * The drive with unit#0 (if available) is mapped at the highest address, and
- * it is passed to pc_isa_bios_init(). Merging several drives for isa-bios is
+ * If pcms->flash[0] has a block backend, its memory is passed to
+ * pc_isa_bios_init().  Merging several flash devices for isa-bios is
  * not supported.
  */
-static void pc_system_flash_init(MemoryRegion *rom_memory)
+static void pc_system_flash_map(PCMachineState *pcms,
+                                MemoryRegion *rom_memory)
 {
-    int unit;
-    DriveInfo *pflash_drv;
+    hwaddr total_size = 0;
+    int i;
     BlockBackend *blk;
     int64_t size;
-    char *fatal_errmsg = NULL;
-    hwaddr phys_addr = 0x100000000ULL;
-    int sector_bits, sector_size;
-    pflash_t *system_flash;
+    PFlashCFI01 *system_flash;
     MemoryRegion *flash_mem;
-    char name[64];
     void *flash_ptr;
     int ret, flash_size;
 
-    sector_bits = 12;
-    sector_size = 1 << sector_bits;
+    assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled);
 
-    for (unit = 0;
-         (unit < FLASH_MAP_UNIT_MAX &&
-          (pflash_drv = drive_get(IF_PFLASH, 0, unit)) != NULL);
-         ++unit) {
-        blk = blk_by_legacy_dinfo(pflash_drv);
+    for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
+        system_flash = pcms->flash[i];
+        blk = pflash_cfi01_get_blk(system_flash);
+        if (!blk) {
+            break;
+        }
         size = blk_getlength(blk);
         if (size < 0) {
-            fatal_errmsg = g_strdup_printf("failed to get backing file size");
-        } else if (size == 0) {
-            fatal_errmsg = g_strdup_printf("PC system firmware (pflash) "
-                               "cannot have zero size");
-        } else if ((size % sector_size) != 0) {
-            fatal_errmsg = g_strdup_printf("PC system firmware (pflash) "
-                               "must be a multiple of 0x%x", sector_size);
-        } else if (phys_addr < size || phys_addr - size < FLASH_MAP_BASE_MIN) {
-            fatal_errmsg = g_strdup_printf("oversized backing file, pflash "
-                               "segments cannot be mapped under "
-                               TARGET_FMT_plx, FLASH_MAP_BASE_MIN);
+            error_report("can't get size of block device %s: %s",
+                         blk_name(blk), strerror(-size));
+            exit(1);
         }
-        if (fatal_errmsg != NULL) {
-            Location loc;
-
-            /* push a new, "none" location on the location stack; overwrite its
-             * contents with the location saved in the option; print the error
-             * (includes location); pop the top
-             */
-            loc_push_none(&loc);
-            if (pflash_drv->opts != NULL) {
-                qemu_opts_loc_restore(pflash_drv->opts);
-            }
-            error_report("%s", fatal_errmsg);
-            loc_pop(&loc);
-            g_free(fatal_errmsg);
+        if (size == 0 || size % FLASH_SECTOR_SIZE != 0) {
+            error_report("system firmware block device %s has invalid size "
+                         "%" PRId64,
+                         blk_name(blk), size);
+            info_report("its size must be a non-zero multiple of 0x%x",
+                        FLASH_SECTOR_SIZE);
+            exit(1);
+        }
+        if ((hwaddr)size != size
+            || total_size > HWADDR_MAX - size
+            || total_size + size > FLASH_SIZE_LIMIT) {
+            error_report("combined size of system firmware exceeds "
+                         "%" PRIu64 " bytes",
+                         FLASH_SIZE_LIMIT);
             exit(1);
         }
 
-        phys_addr -= size;
+        total_size += size;
+        qdev_prop_set_uint32(DEVICE(system_flash), "num-blocks",
+                             size / FLASH_SECTOR_SIZE);
+        qdev_init_nofail(DEVICE(system_flash));
+        sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0,
+                        0x100000000ULL - total_size);
 
-        /* pflash_cfi01_register() creates a deep copy of the name */
-        snprintf(name, sizeof name, "system.flash%d", unit);
-        system_flash = pflash_cfi01_register(phys_addr, NULL /* qdev */, name,
-                                             size, blk, sector_size,
-                                             size >> sector_bits,
-                                             1      /* width */,
-                                             0x0000 /* id0 */,
-                                             0x0000 /* id1 */,
-                                             0x0000 /* id2 */,
-                                             0x0000 /* id3 */,
-                                             0      /* be */);
-        if (unit == 0) {
+        if (i == 0) {
             flash_mem = pflash_cfi01_get_memory(system_flash);
             pc_isa_bios_init(rom_memory, flash_mem, size);
 
@@ -240,24 +264,63 @@
                                 bios);
 }
 
-void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
+void pc_system_firmware_init(PCMachineState *pcms,
+                             MemoryRegion *rom_memory)
 {
+    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+    int i;
     DriveInfo *pflash_drv;
+    BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)];
+    Location loc;
 
-    pflash_drv = drive_get(IF_PFLASH, 0, 0);
-
-    if (isapc_ram_fw || pflash_drv == NULL) {
-        /* When a pflash drive is not found, use rom-mode */
-        old_pc_system_rom_init(rom_memory, isapc_ram_fw);
+    if (!pcmc->pci_enabled) {
+        old_pc_system_rom_init(rom_memory, true);
         return;
     }
 
-    if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
-        /* Older KVM cannot execute from device memory. So, flash memory
-         * cannot be used unless the readonly memory kvm capability is present. */
-        fprintf(stderr, "qemu: pflash with kvm requires KVM readonly memory support\n");
-        exit(1);
+    /* Map legacy -drive if=pflash to machine properties */
+    for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
+        pflash_blk[i] = pflash_cfi01_get_blk(pcms->flash[i]);
+        pflash_drv = drive_get(IF_PFLASH, 0, i);
+        if (!pflash_drv) {
+            continue;
+        }
+        loc_push_none(&loc);
+        qemu_opts_loc_restore(pflash_drv->opts);
+        if (pflash_blk[i]) {
+            error_report("clashes with -machine");
+            exit(1);
+        }
+        pflash_blk[i] = blk_by_legacy_dinfo(pflash_drv);
+        qdev_prop_set_drive(DEVICE(pcms->flash[i]),
+                            "drive", pflash_blk[i], &error_fatal);
+        loc_pop(&loc);
     }
 
-    pc_system_flash_init(rom_memory);
+    /* Reject gaps */
+    for (i = 1; i < ARRAY_SIZE(pcms->flash); i++) {
+        if (pflash_blk[i] && !pflash_blk[i - 1]) {
+            error_report("pflash%d requires pflash%d", i, i - 1);
+            exit(1);
+        }
+    }
+
+    if (!pflash_blk[0]) {
+        /* Machine property pflash0 not set, use ROM mode */
+        old_pc_system_rom_init(rom_memory, false);
+    } else {
+        if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
+            /*
+             * Older KVM cannot execute from device memory. So, flash
+             * memory cannot be used unless the readonly memory kvm
+             * capability is present.
+             */
+            error_report("pflash with kvm requires KVM readonly memory support");
+            exit(1);
+        }
+
+        pc_system_flash_map(pcms, rom_memory);
+    }
+
+    pc_system_flash_cleanup_unused(pcms);
 }
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 301a8e9..df712c3 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -39,7 +39,7 @@
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
 obj-$(CONFIG_XIVE) += xive.o
 obj-$(CONFIG_XIVE_SPAPR) += spapr_xive.o
-obj-$(CONFIG_POWERNV) += xics_pnv.o
+obj-$(CONFIG_POWERNV) += xics_pnv.o pnv_xive.o
 obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
 obj-$(CONFIG_S390_FLIC) += s390_flic.o
 obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o
diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c
new file mode 100644
index 0000000..bb0877c
--- /dev/null
+++ b/hw/intc/pnv_xive.c
@@ -0,0 +1,1753 @@
+/*
+ * QEMU PowerPC XIVE interrupt controller model
+ *
+ * Copyright (c) 2017-2019, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "target/ppc/cpu.h"
+#include "sysemu/cpus.h"
+#include "sysemu/dma.h"
+#include "monitor/monitor.h"
+#include "hw/ppc/fdt.h"
+#include "hw/ppc/pnv.h"
+#include "hw/ppc/pnv_core.h"
+#include "hw/ppc/pnv_xscom.h"
+#include "hw/ppc/pnv_xive.h"
+#include "hw/ppc/xive_regs.h"
+#include "hw/ppc/ppc.h"
+
+#include <libfdt.h>
+
+#include "pnv_xive_regs.h"
+
+#define XIVE_DEBUG
+
+/*
+ * Virtual structures table (VST)
+ */
+#define SBE_PER_BYTE   4
+
+typedef struct XiveVstInfo {
+    const char *name;
+    uint32_t    size;
+    uint32_t    max_blocks;
+} XiveVstInfo;
+
+static const XiveVstInfo vst_infos[] = {
+    [VST_TSEL_IVT]  = { "EAT",  sizeof(XiveEAS), 16 },
+    [VST_TSEL_SBE]  = { "SBE",  1,               16 },
+    [VST_TSEL_EQDT] = { "ENDT", sizeof(XiveEND), 16 },
+    [VST_TSEL_VPDT] = { "VPDT", sizeof(XiveNVT), 32 },
+
+    /*
+     *  Interrupt fifo backing store table (not modeled) :
+     *
+     * 0 - IPI,
+     * 1 - HWD,
+     * 2 - First escalate,
+     * 3 - Second escalate,
+     * 4 - Redistribution,
+     * 5 - IPI cascaded queue ?
+     */
+    [VST_TSEL_IRQ]  = { "IRQ",  1,               6  },
+};
+
+#define xive_error(xive, fmt, ...)                                      \
+    qemu_log_mask(LOG_GUEST_ERROR, "XIVE[%x] - " fmt "\n",              \
+                  (xive)->chip->chip_id, ## __VA_ARGS__);
+
+/*
+ * QEMU version of the GETFIELD/SETFIELD macros
+ *
+ * TODO: It might be better to use the existing extract64() and
+ * deposit64() but this means that all the register definitions will
+ * change and become incompatible with the ones found in skiboot.
+ *
+ * Keep it as it is for now until we find a common ground.
+ */
+static inline uint64_t GETFIELD(uint64_t mask, uint64_t word)
+{
+    return (word & mask) >> ctz64(mask);
+}
+
+static inline uint64_t SETFIELD(uint64_t mask, uint64_t word,
+                                uint64_t value)
+{
+    return (word & ~mask) | ((value << ctz64(mask)) & mask);
+}
+
+/*
+ * Remote access to controllers. HW uses MMIOs. For now, a simple scan
+ * of the chips is good enough.
+ *
+ * TODO: Block scope support
+ */
+static PnvXive *pnv_xive_get_ic(uint8_t blk)
+{
+    PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
+    int i;
+
+    for (i = 0; i < pnv->num_chips; i++) {
+        Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
+        PnvXive *xive = &chip9->xive;
+
+        if (xive->chip->chip_id == blk) {
+            return xive;
+        }
+    }
+    return NULL;
+}
+
+/*
+ * VST accessors for SBE, EAT, ENDT, NVT
+ *
+ * Indirect VST tables are arrays of VSDs pointing to a page (of same
+ * size). Each page is a direct VST table.
+ */
+
+#define XIVE_VSD_SIZE 8
+
+/* Indirect page size can be 4K, 64K, 2M, 16M. */
+static uint64_t pnv_xive_vst_page_size_allowed(uint32_t page_shift)
+{
+     return page_shift == 12 || page_shift == 16 ||
+         page_shift == 21 || page_shift == 24;
+}
+
+static uint64_t pnv_xive_vst_size(uint64_t vsd)
+{
+    uint64_t vst_tsize = 1ull << (GETFIELD(VSD_TSIZE, vsd) + 12);
+
+    /*
+     * Read the first descriptor to get the page size of the indirect
+     * table.
+     */
+    if (VSD_INDIRECT & vsd) {
+        uint32_t nr_pages = vst_tsize / XIVE_VSD_SIZE;
+        uint32_t page_shift;
+
+        vsd = ldq_be_dma(&address_space_memory, vsd & VSD_ADDRESS_MASK);
+        page_shift = GETFIELD(VSD_TSIZE, vsd) + 12;
+
+        if (!pnv_xive_vst_page_size_allowed(page_shift)) {
+            return 0;
+        }
+
+        return nr_pages * (1ull << page_shift);
+    }
+
+    return vst_tsize;
+}
+
+static uint64_t pnv_xive_vst_addr_direct(PnvXive *xive, uint32_t type,
+                                         uint64_t vsd, uint32_t idx)
+{
+    const XiveVstInfo *info = &vst_infos[type];
+    uint64_t vst_addr = vsd & VSD_ADDRESS_MASK;
+
+    return vst_addr + idx * info->size;
+}
+
+static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type,
+                                           uint64_t vsd, uint32_t idx)
+{
+    const XiveVstInfo *info = &vst_infos[type];
+    uint64_t vsd_addr;
+    uint32_t vsd_idx;
+    uint32_t page_shift;
+    uint32_t vst_per_page;
+
+    /* Get the page size of the indirect table. */
+    vsd_addr = vsd & VSD_ADDRESS_MASK;
+    vsd = ldq_be_dma(&address_space_memory, vsd_addr);
+
+    if (!(vsd & VSD_ADDRESS_MASK)) {
+        xive_error(xive, "VST: invalid %s entry %x !?", info->name, 0);
+        return 0;
+    }
+
+    page_shift = GETFIELD(VSD_TSIZE, vsd) + 12;
+
+    if (!pnv_xive_vst_page_size_allowed(page_shift)) {
+        xive_error(xive, "VST: invalid %s page shift %d", info->name,
+                   page_shift);
+        return 0;
+    }
+
+    vst_per_page = (1ull << page_shift) / info->size;
+    vsd_idx = idx / vst_per_page;
+
+    /* Load the VSD we are looking for, if not already done */
+    if (vsd_idx) {
+        vsd_addr = vsd_addr + vsd_idx * XIVE_VSD_SIZE;
+        vsd = ldq_be_dma(&address_space_memory, vsd_addr);
+
+        if (!(vsd & VSD_ADDRESS_MASK)) {
+            xive_error(xive, "VST: invalid %s entry %x !?", info->name, 0);
+            return 0;
+        }
+
+        /*
+         * Check that the pages have a consistent size across the
+         * indirect table
+         */
+        if (page_shift != GETFIELD(VSD_TSIZE, vsd) + 12) {
+            xive_error(xive, "VST: %s entry %x indirect page size differ !?",
+                       info->name, idx);
+            return 0;
+        }
+    }
+
+    return pnv_xive_vst_addr_direct(xive, type, vsd, (idx % vst_per_page));
+}
+
+static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t type, uint8_t blk,
+                                  uint32_t idx)
+{
+    const XiveVstInfo *info = &vst_infos[type];
+    uint64_t vsd;
+    uint32_t idx_max;
+
+    if (blk >= info->max_blocks) {
+        xive_error(xive, "VST: invalid block id %d for VST %s %d !?",
+                   blk, info->name, idx);
+        return 0;
+    }
+
+    vsd = xive->vsds[type][blk];
+
+    /* Remote VST access */
+    if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) {
+        xive = pnv_xive_get_ic(blk);
+
+        return xive ? pnv_xive_vst_addr(xive, type, blk, idx) : 0;
+    }
+
+    idx_max = pnv_xive_vst_size(vsd) / info->size - 1;
+    if (idx > idx_max) {
+#ifdef XIVE_DEBUG
+        xive_error(xive, "VST: %s entry %x/%x out of range [ 0 .. %x ] !?",
+                   info->name, blk, idx, idx_max);
+#endif
+        return 0;
+    }
+
+    if (VSD_INDIRECT & vsd) {
+        return pnv_xive_vst_addr_indirect(xive, type, vsd, idx);
+    }
+
+    return pnv_xive_vst_addr_direct(xive, type, vsd, idx);
+}
+
+static int pnv_xive_vst_read(PnvXive *xive, uint32_t type, uint8_t blk,
+                             uint32_t idx, void *data)
+{
+    const XiveVstInfo *info = &vst_infos[type];
+    uint64_t addr = pnv_xive_vst_addr(xive, type, blk, idx);
+
+    if (!addr) {
+        return -1;
+    }
+
+    cpu_physical_memory_read(addr, data, info->size);
+    return 0;
+}
+
+#define XIVE_VST_WORD_ALL -1
+
+static int pnv_xive_vst_write(PnvXive *xive, uint32_t type, uint8_t blk,
+                              uint32_t idx, void *data, uint32_t word_number)
+{
+    const XiveVstInfo *info = &vst_infos[type];
+    uint64_t addr = pnv_xive_vst_addr(xive, type, blk, idx);
+
+    if (!addr) {
+        return -1;
+    }
+
+    if (word_number == XIVE_VST_WORD_ALL) {
+        cpu_physical_memory_write(addr, data, info->size);
+    } else {
+        cpu_physical_memory_write(addr + word_number * 4,
+                                  data + word_number * 4, 4);
+    }
+    return 0;
+}
+
+static int pnv_xive_get_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+                            XiveEND *end)
+{
+    return pnv_xive_vst_read(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end);
+}
+
+static int pnv_xive_write_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+                              XiveEND *end, uint8_t word_number)
+{
+    return pnv_xive_vst_write(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end,
+                              word_number);
+}
+
+static int pnv_xive_end_update(PnvXive *xive, uint8_t blk, uint32_t idx)
+{
+    int i;
+    uint64_t eqc_watch[4];
+
+    for (i = 0; i < ARRAY_SIZE(eqc_watch); i++) {
+        eqc_watch[i] = cpu_to_be64(xive->regs[(VC_EQC_CWATCH_DAT0 >> 3) + i]);
+    }
+
+    return pnv_xive_vst_write(xive, VST_TSEL_EQDT, blk, idx, eqc_watch,
+                              XIVE_VST_WORD_ALL);
+}
+
+static int pnv_xive_get_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+                            XiveNVT *nvt)
+{
+    return pnv_xive_vst_read(PNV_XIVE(xrtr), VST_TSEL_VPDT, blk, idx, nvt);
+}
+
+static int pnv_xive_write_nvt(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+                              XiveNVT *nvt, uint8_t word_number)
+{
+    return pnv_xive_vst_write(PNV_XIVE(xrtr), VST_TSEL_VPDT, blk, idx, nvt,
+                              word_number);
+}
+
+static int pnv_xive_nvt_update(PnvXive *xive, uint8_t blk, uint32_t idx)
+{
+    int i;
+    uint64_t vpc_watch[8];
+
+    for (i = 0; i < ARRAY_SIZE(vpc_watch); i++) {
+        vpc_watch[i] = cpu_to_be64(xive->regs[(PC_VPC_CWATCH_DAT0 >> 3) + i]);
+    }
+
+    return pnv_xive_vst_write(xive, VST_TSEL_VPDT, blk, idx, vpc_watch,
+                              XIVE_VST_WORD_ALL);
+}
+
+static int pnv_xive_get_eas(XiveRouter *xrtr, uint8_t blk, uint32_t idx,
+                            XiveEAS *eas)
+{
+    PnvXive *xive = PNV_XIVE(xrtr);
+
+    if (pnv_xive_get_ic(blk) != xive) {
+        xive_error(xive, "VST: EAS %x is remote !?", XIVE_SRCNO(blk, idx));
+        return -1;
+    }
+
+    return pnv_xive_vst_read(xive, VST_TSEL_IVT, blk, idx, eas);
+}
+
+static int pnv_xive_eas_update(PnvXive *xive, uint8_t blk, uint32_t idx)
+{
+    /* All done. */
+    return 0;
+}
+
+static XiveTCTX *pnv_xive_get_tctx(XiveRouter *xrtr, CPUState *cs)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
+    PnvXive *xive = NULL;
+    CPUPPCState *env = &cpu->env;
+    int pir = env->spr_cb[SPR_PIR].default_value;
+
+    /*
+     * Perform an extra check on the HW thread enablement.
+     *
+     * The TIMA is shared among the chips and to identify the chip
+     * from which the access is being done, we extract the chip id
+     * from the PIR.
+     */
+    xive = pnv_xive_get_ic((pir >> 8) & 0xf);
+    if (!xive) {
+        return NULL;
+    }
+
+    if (!(xive->regs[PC_THREAD_EN_REG0 >> 3] & PPC_BIT(pir & 0x3f))) {
+        xive_error(PNV_XIVE(xrtr), "IC: CPU %x is not enabled", pir);
+    }
+
+    return tctx;
+}
+
+/*
+ * The internal sources (IPIs) of the interrupt controller have no
+ * knowledge of the XIVE chip on which they reside. Encode the block
+ * id in the source interrupt number before forwarding the source
+ * event notification to the Router. This is required on a multichip
+ * system.
+ */
+static void pnv_xive_notify(XiveNotifier *xn, uint32_t srcno)
+{
+    PnvXive *xive = PNV_XIVE(xn);
+    uint8_t blk = xive->chip->chip_id;
+
+    xive_router_notify(xn, XIVE_SRCNO(blk, srcno));
+}
+
+/*
+ * XIVE helpers
+ */
+
+static uint64_t pnv_xive_vc_size(PnvXive *xive)
+{
+    return (~xive->regs[CQ_VC_BARM >> 3] + 1) & CQ_VC_BARM_MASK;
+}
+
+static uint64_t pnv_xive_edt_shift(PnvXive *xive)
+{
+    return ctz64(pnv_xive_vc_size(xive) / XIVE_TABLE_EDT_MAX);
+}
+
+static uint64_t pnv_xive_pc_size(PnvXive *xive)
+{
+    return (~xive->regs[CQ_PC_BARM >> 3] + 1) & CQ_PC_BARM_MASK;
+}
+
+static uint32_t pnv_xive_nr_ipis(PnvXive *xive)
+{
+    uint8_t blk = xive->chip->chip_id;
+
+    return pnv_xive_vst_size(xive->vsds[VST_TSEL_SBE][blk]) * SBE_PER_BYTE;
+}
+
+static uint32_t pnv_xive_nr_ends(PnvXive *xive)
+{
+    uint8_t blk = xive->chip->chip_id;
+
+    return pnv_xive_vst_size(xive->vsds[VST_TSEL_EQDT][blk])
+        / vst_infos[VST_TSEL_EQDT].size;
+}
+
+/*
+ * EDT Table
+ *
+ * The Virtualization Controller MMIO region containing the IPI ESB
+ * pages and END ESB pages is sub-divided into "sets" which map
+ * portions of the VC region to the different ESB pages. It is
+ * configured at runtime through the EDT "Domain Table" to let the
+ * firmware decide how to split the VC address space between IPI ESB
+ * pages and END ESB pages.
+ */
+
+/*
+ * Computes the overall size of the IPI or the END ESB pages
+ */
+static uint64_t pnv_xive_edt_size(PnvXive *xive, uint64_t type)
+{
+    uint64_t edt_size = 1ull << pnv_xive_edt_shift(xive);
+    uint64_t size = 0;
+    int i;
+
+    for (i = 0; i < XIVE_TABLE_EDT_MAX; i++) {
+        uint64_t edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[i]);
+
+        if (edt_type == type) {
+            size += edt_size;
+        }
+    }
+
+    return size;
+}
+
+/*
+ * Maps an offset of the VC region in the IPI or END region using the
+ * layout defined by the EDT "Domaine Table"
+ */
+static uint64_t pnv_xive_edt_offset(PnvXive *xive, uint64_t vc_offset,
+                                              uint64_t type)
+{
+    int i;
+    uint64_t edt_size = 1ull << pnv_xive_edt_shift(xive);
+    uint64_t edt_offset = vc_offset;
+
+    for (i = 0; i < XIVE_TABLE_EDT_MAX && (i * edt_size) < vc_offset; i++) {
+        uint64_t edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[i]);
+
+        if (edt_type != type) {
+            edt_offset -= edt_size;
+        }
+    }
+
+    return edt_offset;
+}
+
+static void pnv_xive_edt_resize(PnvXive *xive)
+{
+    uint64_t ipi_edt_size = pnv_xive_edt_size(xive, CQ_TDR_EDT_IPI);
+    uint64_t end_edt_size = pnv_xive_edt_size(xive, CQ_TDR_EDT_EQ);
+
+    memory_region_set_size(&xive->ipi_edt_mmio, ipi_edt_size);
+    memory_region_add_subregion(&xive->ipi_mmio, 0, &xive->ipi_edt_mmio);
+
+    memory_region_set_size(&xive->end_edt_mmio, end_edt_size);
+    memory_region_add_subregion(&xive->end_mmio, 0, &xive->end_edt_mmio);
+}
+
+/*
+ * XIVE Table configuration. Only EDT is supported.
+ */
+static int pnv_xive_table_set_data(PnvXive *xive, uint64_t val)
+{
+    uint64_t tsel = xive->regs[CQ_TAR >> 3] & CQ_TAR_TSEL;
+    uint8_t tsel_index = GETFIELD(CQ_TAR_TSEL_INDEX, xive->regs[CQ_TAR >> 3]);
+    uint64_t *xive_table;
+    uint8_t max_index;
+
+    switch (tsel) {
+    case CQ_TAR_TSEL_BLK:
+        max_index = ARRAY_SIZE(xive->blk);
+        xive_table = xive->blk;
+        break;
+    case CQ_TAR_TSEL_MIG:
+        max_index = ARRAY_SIZE(xive->mig);
+        xive_table = xive->mig;
+        break;
+    case CQ_TAR_TSEL_EDT:
+        max_index = ARRAY_SIZE(xive->edt);
+        xive_table = xive->edt;
+        break;
+    case CQ_TAR_TSEL_VDT:
+        max_index = ARRAY_SIZE(xive->vdt);
+        xive_table = xive->vdt;
+        break;
+    default:
+        xive_error(xive, "IC: invalid table %d", (int) tsel);
+        return -1;
+    }
+
+    if (tsel_index >= max_index) {
+        xive_error(xive, "IC: invalid index %d", (int) tsel_index);
+        return -1;
+    }
+
+    xive_table[tsel_index] = val;
+
+    if (xive->regs[CQ_TAR >> 3] & CQ_TAR_TBL_AUTOINC) {
+        xive->regs[CQ_TAR >> 3] =
+            SETFIELD(CQ_TAR_TSEL_INDEX, xive->regs[CQ_TAR >> 3], ++tsel_index);
+    }
+
+    /*
+     * EDT configuration is complete. Resize the MMIO windows exposing
+     * the IPI and the END ESBs in the VC region.
+     */
+    if (tsel == CQ_TAR_TSEL_EDT && tsel_index == ARRAY_SIZE(xive->edt)) {
+        pnv_xive_edt_resize(xive);
+    }
+
+    return 0;
+}
+
+/*
+ * Virtual Structure Tables (VST) configuration
+ */
+static void pnv_xive_vst_set_exclusive(PnvXive *xive, uint8_t type,
+                                       uint8_t blk, uint64_t vsd)
+{
+    XiveENDSource *end_xsrc = &xive->end_source;
+    XiveSource *xsrc = &xive->ipi_source;
+    const XiveVstInfo *info = &vst_infos[type];
+    uint32_t page_shift = GETFIELD(VSD_TSIZE, vsd) + 12;
+    uint64_t vst_addr = vsd & VSD_ADDRESS_MASK;
+
+    /* Basic checks */
+
+    if (VSD_INDIRECT & vsd) {
+        if (!(xive->regs[VC_GLOBAL_CONFIG >> 3] & VC_GCONF_INDIRECT)) {
+            xive_error(xive, "VST: %s indirect tables are not enabled",
+                       info->name);
+            return;
+        }
+
+        if (!pnv_xive_vst_page_size_allowed(page_shift)) {
+            xive_error(xive, "VST: invalid %s page shift %d", info->name,
+                       page_shift);
+            return;
+        }
+    }
+
+    if (!QEMU_IS_ALIGNED(vst_addr, 1ull << page_shift)) {
+        xive_error(xive, "VST: %s table address 0x%"PRIx64" is not aligned with"
+                   " page shift %d", info->name, vst_addr, page_shift);
+        return;
+    }
+
+    /* Record the table configuration (in SRAM on HW) */
+    xive->vsds[type][blk] = vsd;
+
+    /* Now tune the models with the configuration provided by the FW */
+
+    switch (type) {
+    case VST_TSEL_IVT:  /* Nothing to be done */
+        break;
+
+    case VST_TSEL_EQDT:
+        /*
+         * Backing store pages for the END. Compute the number of ENDs
+         * provisioned by FW and resize the END ESB window accordingly.
+         */
+        memory_region_set_size(&end_xsrc->esb_mmio, pnv_xive_nr_ends(xive) *
+                               (1ull << (end_xsrc->esb_shift + 1)));
+        memory_region_add_subregion(&xive->end_edt_mmio, 0,
+                                    &end_xsrc->esb_mmio);
+        break;
+
+    case VST_TSEL_SBE:
+        /*
+         * Backing store pages for the source PQ bits. The model does
+         * not use these PQ bits backed in RAM because the XiveSource
+         * model has its own. Compute the number of IRQs provisioned
+         * by FW and resize the IPI ESB window accordingly.
+         */
+        memory_region_set_size(&xsrc->esb_mmio, pnv_xive_nr_ipis(xive) *
+                               (1ull << xsrc->esb_shift));
+        memory_region_add_subregion(&xive->ipi_edt_mmio, 0, &xsrc->esb_mmio);
+        break;
+
+    case VST_TSEL_VPDT: /* Not modeled */
+    case VST_TSEL_IRQ:  /* Not modeled */
+        /*
+         * These tables contains the backing store pages for the
+         * interrupt fifos of the VC sub-engine in case of overflow.
+         */
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
+}
+
+/*
+ * Both PC and VC sub-engines are configured as each use the Virtual
+ * Structure Tables : SBE, EAS, END and NVT.
+ */
+static void pnv_xive_vst_set_data(PnvXive *xive, uint64_t vsd, bool pc_engine)
+{
+    uint8_t mode = GETFIELD(VSD_MODE, vsd);
+    uint8_t type = GETFIELD(VST_TABLE_SELECT,
+                            xive->regs[VC_VSD_TABLE_ADDR >> 3]);
+    uint8_t blk = GETFIELD(VST_TABLE_BLOCK,
+                           xive->regs[VC_VSD_TABLE_ADDR >> 3]);
+    uint64_t vst_addr = vsd & VSD_ADDRESS_MASK;
+
+    if (type > VST_TSEL_IRQ) {
+        xive_error(xive, "VST: invalid table type %d", type);
+        return;
+    }
+
+    if (blk >= vst_infos[type].max_blocks) {
+        xive_error(xive, "VST: invalid block id %d for"
+                      " %s table", blk, vst_infos[type].name);
+        return;
+    }
+
+    /*
+     * Only take the VC sub-engine configuration into account because
+     * the XiveRouter model combines both VC and PC sub-engines
+     */
+    if (pc_engine) {
+        return;
+    }
+
+    if (!vst_addr) {
+        xive_error(xive, "VST: invalid %s table address", vst_infos[type].name);
+        return;
+    }
+
+    switch (mode) {
+    case VSD_MODE_FORWARD:
+        xive->vsds[type][blk] = vsd;
+        break;
+
+    case VSD_MODE_EXCLUSIVE:
+        pnv_xive_vst_set_exclusive(xive, type, blk, vsd);
+        break;
+
+    default:
+        xive_error(xive, "VST: unsupported table mode %d", mode);
+        return;
+    }
+}
+
+/*
+ * Interrupt controller MMIO region. The layout is compatible between
+ * 4K and 64K pages :
+ *
+ * Page 0           sub-engine BARs
+ *  0x000 - 0x3FF   IC registers
+ *  0x400 - 0x7FF   PC registers
+ *  0x800 - 0xFFF   VC registers
+ *
+ * Page 1           Notify page (writes only)
+ *  0x000 - 0x7FF   HW interrupt triggers (PSI, PHB)
+ *  0x800 - 0xFFF   forwards and syncs
+ *
+ * Page 2           LSI Trigger page (writes only) (not modeled)
+ * Page 3           LSI SB EOI page (reads only) (not modeled)
+ *
+ * Page 4-7         indirect TIMA
+ */
+
+/*
+ * IC - registers MMIO
+ */
+static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset,
+                                  uint64_t val, unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+    MemoryRegion *sysmem = get_system_memory();
+    uint32_t reg = offset >> 3;
+    bool is_chip0 = xive->chip->chip_id == 0;
+
+    switch (offset) {
+
+    /*
+     * XIVE CQ (PowerBus bridge) settings
+     */
+    case CQ_MSGSND:     /* msgsnd for doorbells */
+    case CQ_FIRMASK_OR: /* FIR error reporting */
+        break;
+    case CQ_PBI_CTL:
+        if (val & CQ_PBI_PC_64K) {
+            xive->pc_shift = 16;
+        }
+        if (val & CQ_PBI_VC_64K) {
+            xive->vc_shift = 16;
+        }
+        break;
+    case CQ_CFG_PB_GEN: /* PowerBus General Configuration */
+        /*
+         * TODO: CQ_INT_ADDR_OPT for 1-block-per-chip mode
+         */
+        break;
+
+    /*
+     * XIVE Virtualization Controller settings
+     */
+    case VC_GLOBAL_CONFIG:
+        break;
+
+    /*
+     * XIVE Presenter Controller settings
+     */
+    case PC_GLOBAL_CONFIG:
+        /*
+         * PC_GCONF_CHIPID_OVR
+         *   Overrides Int command Chip ID with the Chip ID field (DEBUG)
+         */
+        break;
+    case PC_TCTXT_CFG:
+        /*
+         * TODO: block group support
+         *
+         * PC_TCTXT_CFG_BLKGRP_EN
+         * PC_TCTXT_CFG_HARD_CHIPID_BLK :
+         *   Moves the chipid into block field for hardwired CAM compares.
+         *   Block offset value is adjusted to 0b0..01 & ThrdId
+         *
+         *   Will require changes in xive_presenter_tctx_match(). I am
+         *   not sure how to handle that yet.
+         */
+
+        /* Overrides hardwired chip ID with the chip ID field */
+        if (val & PC_TCTXT_CHIPID_OVERRIDE) {
+            xive->tctx_chipid = GETFIELD(PC_TCTXT_CHIPID, val);
+        }
+        break;
+    case PC_TCTXT_TRACK:
+        /*
+         * PC_TCTXT_TRACK_EN:
+         *   enable block tracking and exchange of block ownership
+         *   information between Interrupt controllers
+         */
+        break;
+
+    /*
+     * Misc settings
+     */
+    case VC_SBC_CONFIG: /* Store EOI configuration */
+        /*
+         * Configure store EOI if required by firwmare (skiboot has removed
+         * support recently though)
+         */
+        if (val & (VC_SBC_CONF_CPLX_CIST | VC_SBC_CONF_CIST_BOTH)) {
+            object_property_set_int(OBJECT(&xive->ipi_source),
+                                    XIVE_SRC_STORE_EOI, "flags", &error_fatal);
+        }
+        break;
+
+    case VC_EQC_CONFIG: /* TODO: silent escalation */
+    case VC_AIB_TX_ORDER_TAG2: /* relax ordering */
+        break;
+
+    /*
+     * XIVE BAR settings (XSCOM only)
+     */
+    case CQ_RST_CTL:
+        /* bit4: resets all BAR registers */
+        break;
+
+    case CQ_IC_BAR: /* IC BAR. 8 pages */
+        xive->ic_shift = val & CQ_IC_BAR_64K ? 16 : 12;
+        if (!(val & CQ_IC_BAR_VALID)) {
+            xive->ic_base = 0;
+            if (xive->regs[reg] & CQ_IC_BAR_VALID) {
+                memory_region_del_subregion(&xive->ic_mmio,
+                                            &xive->ic_reg_mmio);
+                memory_region_del_subregion(&xive->ic_mmio,
+                                            &xive->ic_notify_mmio);
+                memory_region_del_subregion(&xive->ic_mmio,
+                                            &xive->ic_lsi_mmio);
+                memory_region_del_subregion(&xive->ic_mmio,
+                                            &xive->tm_indirect_mmio);
+
+                memory_region_del_subregion(sysmem, &xive->ic_mmio);
+            }
+        } else {
+            xive->ic_base = val & ~(CQ_IC_BAR_VALID | CQ_IC_BAR_64K);
+            if (!(xive->regs[reg] & CQ_IC_BAR_VALID)) {
+                memory_region_add_subregion(sysmem, xive->ic_base,
+                                            &xive->ic_mmio);
+
+                memory_region_add_subregion(&xive->ic_mmio,  0,
+                                            &xive->ic_reg_mmio);
+                memory_region_add_subregion(&xive->ic_mmio,
+                                            1ul << xive->ic_shift,
+                                            &xive->ic_notify_mmio);
+                memory_region_add_subregion(&xive->ic_mmio,
+                                            2ul << xive->ic_shift,
+                                            &xive->ic_lsi_mmio);
+                memory_region_add_subregion(&xive->ic_mmio,
+                                            4ull << xive->ic_shift,
+                                            &xive->tm_indirect_mmio);
+            }
+        }
+        break;
+
+    case CQ_TM1_BAR: /* TM BAR. 4 pages. Map only once */
+    case CQ_TM2_BAR: /* second TM BAR. for hotplug. Not modeled */
+        xive->tm_shift = val & CQ_TM_BAR_64K ? 16 : 12;
+        if (!(val & CQ_TM_BAR_VALID)) {
+            xive->tm_base = 0;
+            if (xive->regs[reg] & CQ_TM_BAR_VALID && is_chip0) {
+                memory_region_del_subregion(sysmem, &xive->tm_mmio);
+            }
+        } else {
+            xive->tm_base = val & ~(CQ_TM_BAR_VALID | CQ_TM_BAR_64K);
+            if (!(xive->regs[reg] & CQ_TM_BAR_VALID) && is_chip0) {
+                memory_region_add_subregion(sysmem, xive->tm_base,
+                                            &xive->tm_mmio);
+            }
+        }
+        break;
+
+    case CQ_PC_BARM:
+        xive->regs[reg] = val;
+        memory_region_set_size(&xive->pc_mmio, pnv_xive_pc_size(xive));
+        break;
+    case CQ_PC_BAR: /* From 32M to 512G */
+        if (!(val & CQ_PC_BAR_VALID)) {
+            xive->pc_base = 0;
+            if (xive->regs[reg] & CQ_PC_BAR_VALID) {
+                memory_region_del_subregion(sysmem, &xive->pc_mmio);
+            }
+        } else {
+            xive->pc_base = val & ~(CQ_PC_BAR_VALID);
+            if (!(xive->regs[reg] & CQ_PC_BAR_VALID)) {
+                memory_region_add_subregion(sysmem, xive->pc_base,
+                                            &xive->pc_mmio);
+            }
+        }
+        break;
+
+    case CQ_VC_BARM:
+        xive->regs[reg] = val;
+        memory_region_set_size(&xive->vc_mmio, pnv_xive_vc_size(xive));
+        break;
+    case CQ_VC_BAR: /* From 64M to 4TB */
+        if (!(val & CQ_VC_BAR_VALID)) {
+            xive->vc_base = 0;
+            if (xive->regs[reg] & CQ_VC_BAR_VALID) {
+                memory_region_del_subregion(sysmem, &xive->vc_mmio);
+            }
+        } else {
+            xive->vc_base = val & ~(CQ_VC_BAR_VALID);
+            if (!(xive->regs[reg] & CQ_VC_BAR_VALID)) {
+                memory_region_add_subregion(sysmem, xive->vc_base,
+                                            &xive->vc_mmio);
+            }
+        }
+        break;
+
+    /*
+     * XIVE Table settings.
+     */
+    case CQ_TAR: /* Table Address */
+        break;
+    case CQ_TDR: /* Table Data */
+        pnv_xive_table_set_data(xive, val);
+        break;
+
+    /*
+     * XIVE VC & PC Virtual Structure Table settings
+     */
+    case VC_VSD_TABLE_ADDR:
+    case PC_VSD_TABLE_ADDR: /* Virtual table selector */
+        break;
+    case VC_VSD_TABLE_DATA: /* Virtual table setting */
+    case PC_VSD_TABLE_DATA:
+        pnv_xive_vst_set_data(xive, val, offset == PC_VSD_TABLE_DATA);
+        break;
+
+    /*
+     * Interrupt fifo overflow in memory backing store (Not modeled)
+     */
+    case VC_IRQ_CONFIG_IPI:
+    case VC_IRQ_CONFIG_HW:
+    case VC_IRQ_CONFIG_CASCADE1:
+    case VC_IRQ_CONFIG_CASCADE2:
+    case VC_IRQ_CONFIG_REDIST:
+    case VC_IRQ_CONFIG_IPI_CASC:
+        break;
+
+    /*
+     * XIVE hardware thread enablement
+     */
+    case PC_THREAD_EN_REG0: /* Physical Thread Enable */
+    case PC_THREAD_EN_REG1: /* Physical Thread Enable (fused core) */
+        break;
+
+    case PC_THREAD_EN_REG0_SET:
+        xive->regs[PC_THREAD_EN_REG0 >> 3] |= val;
+        break;
+    case PC_THREAD_EN_REG1_SET:
+        xive->regs[PC_THREAD_EN_REG1 >> 3] |= val;
+        break;
+    case PC_THREAD_EN_REG0_CLR:
+        xive->regs[PC_THREAD_EN_REG0 >> 3] &= ~val;
+        break;
+    case PC_THREAD_EN_REG1_CLR:
+        xive->regs[PC_THREAD_EN_REG1 >> 3] &= ~val;
+        break;
+
+    /*
+     * Indirect TIMA access set up. Defines the PIR of the HW thread
+     * to use.
+     */
+    case PC_TCTXT_INDIR0 ... PC_TCTXT_INDIR3:
+        break;
+
+    /*
+     * XIVE PC & VC cache updates for EAS, NVT and END
+     */
+    case VC_IVC_SCRUB_MASK:
+        break;
+    case VC_IVC_SCRUB_TRIG:
+        pnv_xive_eas_update(xive, GETFIELD(PC_SCRUB_BLOCK_ID, val),
+                            GETFIELD(VC_SCRUB_OFFSET, val));
+        break;
+
+    case VC_EQC_SCRUB_MASK:
+    case VC_EQC_CWATCH_SPEC:
+    case VC_EQC_CWATCH_DAT0 ... VC_EQC_CWATCH_DAT3:
+        break;
+    case VC_EQC_SCRUB_TRIG:
+        pnv_xive_end_update(xive, GETFIELD(VC_SCRUB_BLOCK_ID, val),
+                            GETFIELD(VC_SCRUB_OFFSET, val));
+        break;
+
+    case PC_VPC_SCRUB_MASK:
+    case PC_VPC_CWATCH_SPEC:
+    case PC_VPC_CWATCH_DAT0 ... PC_VPC_CWATCH_DAT7:
+        break;
+    case PC_VPC_SCRUB_TRIG:
+        pnv_xive_nvt_update(xive, GETFIELD(PC_SCRUB_BLOCK_ID, val),
+                           GETFIELD(PC_SCRUB_OFFSET, val));
+        break;
+
+
+    /*
+     * XIVE PC & VC cache invalidation
+     */
+    case PC_AT_KILL:
+        break;
+    case VC_AT_MACRO_KILL:
+        break;
+    case PC_AT_KILL_MASK:
+    case VC_AT_MACRO_KILL_MASK:
+        break;
+
+    default:
+        xive_error(xive, "IC: invalid write to reg=0x%"HWADDR_PRIx, offset);
+        return;
+    }
+
+    xive->regs[reg] = val;
+}
+
+static uint64_t pnv_xive_ic_reg_read(void *opaque, hwaddr offset, unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+    uint64_t val = 0;
+    uint32_t reg = offset >> 3;
+
+    switch (offset) {
+    case CQ_CFG_PB_GEN:
+    case CQ_IC_BAR:
+    case CQ_TM1_BAR:
+    case CQ_TM2_BAR:
+    case CQ_PC_BAR:
+    case CQ_PC_BARM:
+    case CQ_VC_BAR:
+    case CQ_VC_BARM:
+    case CQ_TAR:
+    case CQ_TDR:
+    case CQ_PBI_CTL:
+
+    case PC_TCTXT_CFG:
+    case PC_TCTXT_TRACK:
+    case PC_TCTXT_INDIR0:
+    case PC_TCTXT_INDIR1:
+    case PC_TCTXT_INDIR2:
+    case PC_TCTXT_INDIR3:
+    case PC_GLOBAL_CONFIG:
+
+    case PC_VPC_SCRUB_MASK:
+    case PC_VPC_CWATCH_SPEC:
+    case PC_VPC_CWATCH_DAT0:
+    case PC_VPC_CWATCH_DAT1:
+    case PC_VPC_CWATCH_DAT2:
+    case PC_VPC_CWATCH_DAT3:
+    case PC_VPC_CWATCH_DAT4:
+    case PC_VPC_CWATCH_DAT5:
+    case PC_VPC_CWATCH_DAT6:
+    case PC_VPC_CWATCH_DAT7:
+
+    case VC_GLOBAL_CONFIG:
+    case VC_AIB_TX_ORDER_TAG2:
+
+    case VC_IRQ_CONFIG_IPI:
+    case VC_IRQ_CONFIG_HW:
+    case VC_IRQ_CONFIG_CASCADE1:
+    case VC_IRQ_CONFIG_CASCADE2:
+    case VC_IRQ_CONFIG_REDIST:
+    case VC_IRQ_CONFIG_IPI_CASC:
+
+    case VC_EQC_SCRUB_MASK:
+    case VC_EQC_CWATCH_DAT0:
+    case VC_EQC_CWATCH_DAT1:
+    case VC_EQC_CWATCH_DAT2:
+    case VC_EQC_CWATCH_DAT3:
+
+    case VC_EQC_CWATCH_SPEC:
+    case VC_IVC_SCRUB_MASK:
+    case VC_SBC_CONFIG:
+    case VC_AT_MACRO_KILL_MASK:
+    case VC_VSD_TABLE_ADDR:
+    case PC_VSD_TABLE_ADDR:
+    case VC_VSD_TABLE_DATA:
+    case PC_VSD_TABLE_DATA:
+    case PC_THREAD_EN_REG0:
+    case PC_THREAD_EN_REG1:
+        val = xive->regs[reg];
+        break;
+
+    /*
+     * XIVE hardware thread enablement
+     */
+    case PC_THREAD_EN_REG0_SET:
+    case PC_THREAD_EN_REG0_CLR:
+        val = xive->regs[PC_THREAD_EN_REG0 >> 3];
+        break;
+    case PC_THREAD_EN_REG1_SET:
+    case PC_THREAD_EN_REG1_CLR:
+        val = xive->regs[PC_THREAD_EN_REG1 >> 3];
+        break;
+
+    case CQ_MSGSND: /* Identifies which cores have msgsnd enabled. */
+        val = 0xffffff0000000000;
+        break;
+
+    /*
+     * XIVE PC & VC cache updates for EAS, NVT and END
+     */
+    case PC_VPC_SCRUB_TRIG:
+    case VC_IVC_SCRUB_TRIG:
+    case VC_EQC_SCRUB_TRIG:
+        xive->regs[reg] &= ~VC_SCRUB_VALID;
+        val = xive->regs[reg];
+        break;
+
+    /*
+     * XIVE PC & VC cache invalidation
+     */
+    case PC_AT_KILL:
+        xive->regs[reg] &= ~PC_AT_KILL_VALID;
+        val = xive->regs[reg];
+        break;
+    case VC_AT_MACRO_KILL:
+        xive->regs[reg] &= ~VC_KILL_VALID;
+        val = xive->regs[reg];
+        break;
+
+    /*
+     * XIVE synchronisation
+     */
+    case VC_EQC_CONFIG:
+        val = VC_EQC_SYNC_MASK;
+        break;
+
+    default:
+        xive_error(xive, "IC: invalid read reg=0x%"HWADDR_PRIx, offset);
+    }
+
+    return val;
+}
+
+static const MemoryRegionOps pnv_xive_ic_reg_ops = {
+    .read = pnv_xive_ic_reg_read,
+    .write = pnv_xive_ic_reg_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+};
+
+/*
+ * IC - Notify MMIO port page (write only)
+ */
+#define PNV_XIVE_FORWARD_IPI        0x800 /* Forward IPI */
+#define PNV_XIVE_FORWARD_HW         0x880 /* Forward HW */
+#define PNV_XIVE_FORWARD_OS_ESC     0x900 /* Forward OS escalation */
+#define PNV_XIVE_FORWARD_HW_ESC     0x980 /* Forward Hyp escalation */
+#define PNV_XIVE_FORWARD_REDIS      0xa00 /* Forward Redistribution */
+#define PNV_XIVE_RESERVED5          0xa80 /* Cache line 5 PowerBUS operation */
+#define PNV_XIVE_RESERVED6          0xb00 /* Cache line 6 PowerBUS operation */
+#define PNV_XIVE_RESERVED7          0xb80 /* Cache line 7 PowerBUS operation */
+
+/* VC synchronisation */
+#define PNV_XIVE_SYNC_IPI           0xc00 /* Sync IPI */
+#define PNV_XIVE_SYNC_HW            0xc80 /* Sync HW */
+#define PNV_XIVE_SYNC_OS_ESC        0xd00 /* Sync OS escalation */
+#define PNV_XIVE_SYNC_HW_ESC        0xd80 /* Sync Hyp escalation */
+#define PNV_XIVE_SYNC_REDIS         0xe00 /* Sync Redistribution */
+
+/* PC synchronisation */
+#define PNV_XIVE_SYNC_PULL          0xe80 /* Sync pull context */
+#define PNV_XIVE_SYNC_PUSH          0xf00 /* Sync push context */
+#define PNV_XIVE_SYNC_VPC           0xf80 /* Sync remove VPC store */
+
+static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val)
+{
+    /*
+     * Forward the source event notification directly to the Router.
+     * The source interrupt number should already be correctly encoded
+     * with the chip block id by the sending device (PHB, PSI).
+     */
+    xive_router_notify(XIVE_NOTIFIER(xive), val);
+}
+
+static void pnv_xive_ic_notify_write(void *opaque, hwaddr addr, uint64_t val,
+                                     unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+
+    /* VC: HW triggers */
+    switch (addr) {
+    case 0x000 ... 0x7FF:
+        pnv_xive_ic_hw_trigger(opaque, addr, val);
+        break;
+
+    /* VC: Forwarded IRQs */
+    case PNV_XIVE_FORWARD_IPI:
+    case PNV_XIVE_FORWARD_HW:
+    case PNV_XIVE_FORWARD_OS_ESC:
+    case PNV_XIVE_FORWARD_HW_ESC:
+    case PNV_XIVE_FORWARD_REDIS:
+        /* TODO: forwarded IRQs. Should be like HW triggers */
+        xive_error(xive, "IC: forwarded at @0x%"HWADDR_PRIx" IRQ 0x%"PRIx64,
+                   addr, val);
+        break;
+
+    /* VC syncs */
+    case PNV_XIVE_SYNC_IPI:
+    case PNV_XIVE_SYNC_HW:
+    case PNV_XIVE_SYNC_OS_ESC:
+    case PNV_XIVE_SYNC_HW_ESC:
+    case PNV_XIVE_SYNC_REDIS:
+        break;
+
+    /* PC syncs */
+    case PNV_XIVE_SYNC_PULL:
+    case PNV_XIVE_SYNC_PUSH:
+    case PNV_XIVE_SYNC_VPC:
+        break;
+
+    default:
+        xive_error(xive, "IC: invalid notify write @%"HWADDR_PRIx, addr);
+    }
+}
+
+static uint64_t pnv_xive_ic_notify_read(void *opaque, hwaddr addr,
+                                        unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+
+    /* loads are invalid */
+    xive_error(xive, "IC: invalid notify read @%"HWADDR_PRIx, addr);
+    return -1;
+}
+
+static const MemoryRegionOps pnv_xive_ic_notify_ops = {
+    .read = pnv_xive_ic_notify_read,
+    .write = pnv_xive_ic_notify_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+};
+
+/*
+ * IC - LSI MMIO handlers (not modeled)
+ */
+
+static void pnv_xive_ic_lsi_write(void *opaque, hwaddr addr,
+                              uint64_t val, unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+
+    xive_error(xive, "IC: LSI invalid write @%"HWADDR_PRIx, addr);
+}
+
+static uint64_t pnv_xive_ic_lsi_read(void *opaque, hwaddr addr, unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+
+    xive_error(xive, "IC: LSI invalid read @%"HWADDR_PRIx, addr);
+    return -1;
+}
+
+static const MemoryRegionOps pnv_xive_ic_lsi_ops = {
+    .read = pnv_xive_ic_lsi_read,
+    .write = pnv_xive_ic_lsi_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+};
+
+/*
+ * IC - Indirect TIMA MMIO handlers
+ */
+
+/*
+ * When the TIMA is accessed from the indirect page, the thread id
+ * (PIR) has to be configured in the IC registers before. This is used
+ * for resets and for debug purpose also.
+ */
+static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
+{
+    uint64_t tctxt_indir = xive->regs[PC_TCTXT_INDIR0 >> 3];
+    PowerPCCPU *cpu = NULL;
+    int pir;
+
+    if (!(tctxt_indir & PC_TCTXT_INDIR_VALID)) {
+        xive_error(xive, "IC: no indirect TIMA access in progress");
+        return NULL;
+    }
+
+    pir = GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir) & 0xff;
+    cpu = ppc_get_vcpu_by_pir(pir);
+    if (!cpu) {
+        xive_error(xive, "IC: invalid PIR %x for indirect access", pir);
+        return NULL;
+    }
+
+    /* Check that HW thread is XIVE enabled */
+    if (!(xive->regs[PC_THREAD_EN_REG0 >> 3] & PPC_BIT(pir & 0x3f))) {
+        xive_error(xive, "IC: CPU %x is not enabled", pir);
+    }
+
+    return XIVE_TCTX(pnv_cpu_state(cpu)->intc);
+}
+
+static void xive_tm_indirect_write(void *opaque, hwaddr offset,
+                                   uint64_t value, unsigned size)
+{
+    XiveTCTX *tctx = pnv_xive_get_indirect_tctx(PNV_XIVE(opaque));
+
+    xive_tctx_tm_write(tctx, offset, value, size);
+}
+
+static uint64_t xive_tm_indirect_read(void *opaque, hwaddr offset,
+                                      unsigned size)
+{
+    XiveTCTX *tctx = pnv_xive_get_indirect_tctx(PNV_XIVE(opaque));
+
+    return xive_tctx_tm_read(tctx, offset, size);
+}
+
+static const MemoryRegionOps xive_tm_indirect_ops = {
+    .read = xive_tm_indirect_read,
+    .write = xive_tm_indirect_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+};
+
+/*
+ * Interrupt controller XSCOM region.
+ */
+static uint64_t pnv_xive_xscom_read(void *opaque, hwaddr addr, unsigned size)
+{
+    switch (addr >> 3) {
+    case X_VC_EQC_CONFIG:
+        /* FIXME (skiboot): This is the only XSCOM load. Bizarre. */
+        return VC_EQC_SYNC_MASK;
+    default:
+        return pnv_xive_ic_reg_read(opaque, addr, size);
+    }
+}
+
+static void pnv_xive_xscom_write(void *opaque, hwaddr addr,
+                                uint64_t val, unsigned size)
+{
+    pnv_xive_ic_reg_write(opaque, addr, val, size);
+}
+
+static const MemoryRegionOps pnv_xive_xscom_ops = {
+    .read = pnv_xive_xscom_read,
+    .write = pnv_xive_xscom_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    }
+};
+
+/*
+ * Virtualization Controller MMIO region containing the IPI and END ESB pages
+ */
+static uint64_t pnv_xive_vc_read(void *opaque, hwaddr offset,
+                                 unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+    uint64_t edt_index = offset >> pnv_xive_edt_shift(xive);
+    uint64_t edt_type = 0;
+    uint64_t edt_offset;
+    MemTxResult result;
+    AddressSpace *edt_as = NULL;
+    uint64_t ret = -1;
+
+    if (edt_index < XIVE_TABLE_EDT_MAX) {
+        edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[edt_index]);
+    }
+
+    switch (edt_type) {
+    case CQ_TDR_EDT_IPI:
+        edt_as = &xive->ipi_as;
+        break;
+    case CQ_TDR_EDT_EQ:
+        edt_as = &xive->end_as;
+        break;
+    default:
+        xive_error(xive, "VC: invalid EDT type for read @%"HWADDR_PRIx, offset);
+        return -1;
+    }
+
+    /* Remap the offset for the targeted address space */
+    edt_offset = pnv_xive_edt_offset(xive, offset, edt_type);
+
+    ret = address_space_ldq(edt_as, edt_offset, MEMTXATTRS_UNSPECIFIED,
+                            &result);
+
+    if (result != MEMTX_OK) {
+        xive_error(xive, "VC: %s read failed at @0x%"HWADDR_PRIx " -> @0x%"
+                   HWADDR_PRIx, edt_type == CQ_TDR_EDT_IPI ? "IPI" : "END",
+                   offset, edt_offset);
+        return -1;
+    }
+
+    return ret;
+}
+
+static void pnv_xive_vc_write(void *opaque, hwaddr offset,
+                              uint64_t val, unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+    uint64_t edt_index = offset >> pnv_xive_edt_shift(xive);
+    uint64_t edt_type = 0;
+    uint64_t edt_offset;
+    MemTxResult result;
+    AddressSpace *edt_as = NULL;
+
+    if (edt_index < XIVE_TABLE_EDT_MAX) {
+        edt_type = GETFIELD(CQ_TDR_EDT_TYPE, xive->edt[edt_index]);
+    }
+
+    switch (edt_type) {
+    case CQ_TDR_EDT_IPI:
+        edt_as = &xive->ipi_as;
+        break;
+    case CQ_TDR_EDT_EQ:
+        edt_as = &xive->end_as;
+        break;
+    default:
+        xive_error(xive, "VC: invalid EDT type for write @%"HWADDR_PRIx,
+                   offset);
+        return;
+    }
+
+    /* Remap the offset for the targeted address space */
+    edt_offset = pnv_xive_edt_offset(xive, offset, edt_type);
+
+    address_space_stq(edt_as, edt_offset, val, MEMTXATTRS_UNSPECIFIED, &result);
+    if (result != MEMTX_OK) {
+        xive_error(xive, "VC: write failed at @0x%"HWADDR_PRIx, edt_offset);
+    }
+}
+
+static const MemoryRegionOps pnv_xive_vc_ops = {
+    .read = pnv_xive_vc_read,
+    .write = pnv_xive_vc_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+};
+
+/*
+ * Presenter Controller MMIO region. The Virtualization Controller
+ * updates the IPB in the NVT table when required. Not modeled.
+ */
+static uint64_t pnv_xive_pc_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+
+    xive_error(xive, "PC: invalid read @%"HWADDR_PRIx, addr);
+    return -1;
+}
+
+static void pnv_xive_pc_write(void *opaque, hwaddr addr,
+                              uint64_t value, unsigned size)
+{
+    PnvXive *xive = PNV_XIVE(opaque);
+
+    xive_error(xive, "PC: invalid write to VC @%"HWADDR_PRIx, addr);
+}
+
+static const MemoryRegionOps pnv_xive_pc_ops = {
+    .read = pnv_xive_pc_read,
+    .write = pnv_xive_pc_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+};
+
+void pnv_xive_pic_print_info(PnvXive *xive, Monitor *mon)
+{
+    XiveRouter *xrtr = XIVE_ROUTER(xive);
+    uint8_t blk = xive->chip->chip_id;
+    uint32_t srcno0 = XIVE_SRCNO(blk, 0);
+    uint32_t nr_ipis = pnv_xive_nr_ipis(xive);
+    uint32_t nr_ends = pnv_xive_nr_ends(xive);
+    XiveEAS eas;
+    XiveEND end;
+    int i;
+
+    monitor_printf(mon, "XIVE[%x] Source %08x .. %08x\n", blk, srcno0,
+                   srcno0 + nr_ipis - 1);
+    xive_source_pic_print_info(&xive->ipi_source, srcno0, mon);
+
+    monitor_printf(mon, "XIVE[%x] EAT %08x .. %08x\n", blk, srcno0,
+                   srcno0 + nr_ipis - 1);
+    for (i = 0; i < nr_ipis; i++) {
+        if (xive_router_get_eas(xrtr, blk, i, &eas)) {
+            break;
+        }
+        if (!xive_eas_is_masked(&eas)) {
+            xive_eas_pic_print_info(&eas, i, mon);
+        }
+    }
+
+    monitor_printf(mon, "XIVE[%x] ENDT %08x .. %08x\n", blk, 0, nr_ends - 1);
+    for (i = 0; i < nr_ends; i++) {
+        if (xive_router_get_end(xrtr, blk, i, &end)) {
+            break;
+        }
+        xive_end_pic_print_info(&end, i, mon);
+    }
+}
+
+static void pnv_xive_reset(void *dev)
+{
+    PnvXive *xive = PNV_XIVE(dev);
+    XiveSource *xsrc = &xive->ipi_source;
+    XiveENDSource *end_xsrc = &xive->end_source;
+
+    /*
+     * Use the PnvChip id to identify the XIVE interrupt controller.
+     * It can be overriden by configuration at runtime.
+     */
+    xive->tctx_chipid = xive->chip->chip_id;
+
+    /* Default page size (Should be changed at runtime to 64k) */
+    xive->ic_shift = xive->vc_shift = xive->pc_shift = 12;
+
+    /* Clear subregions */
+    if (memory_region_is_mapped(&xsrc->esb_mmio)) {
+        memory_region_del_subregion(&xive->ipi_edt_mmio, &xsrc->esb_mmio);
+    }
+
+    if (memory_region_is_mapped(&xive->ipi_edt_mmio)) {
+        memory_region_del_subregion(&xive->ipi_mmio, &xive->ipi_edt_mmio);
+    }
+
+    if (memory_region_is_mapped(&end_xsrc->esb_mmio)) {
+        memory_region_del_subregion(&xive->end_edt_mmio, &end_xsrc->esb_mmio);
+    }
+
+    if (memory_region_is_mapped(&xive->end_edt_mmio)) {
+        memory_region_del_subregion(&xive->end_mmio, &xive->end_edt_mmio);
+    }
+}
+
+static void pnv_xive_init(Object *obj)
+{
+    PnvXive *xive = PNV_XIVE(obj);
+
+    object_initialize_child(obj, "ipi_source", &xive->ipi_source,
+                            sizeof(xive->ipi_source), TYPE_XIVE_SOURCE,
+                            &error_abort, NULL);
+    object_initialize_child(obj, "end_source", &xive->end_source,
+                            sizeof(xive->end_source), TYPE_XIVE_END_SOURCE,
+                            &error_abort, NULL);
+}
+
+/*
+ *  Maximum number of IRQs and ENDs supported by HW
+ */
+#define PNV_XIVE_NR_IRQS (PNV9_XIVE_VC_SIZE / (1ull << XIVE_ESB_64K_2PAGE))
+#define PNV_XIVE_NR_ENDS (PNV9_XIVE_VC_SIZE / (1ull << XIVE_ESB_64K_2PAGE))
+
+static void pnv_xive_realize(DeviceState *dev, Error **errp)
+{
+    PnvXive *xive = PNV_XIVE(dev);
+    XiveSource *xsrc = &xive->ipi_source;
+    XiveENDSource *end_xsrc = &xive->end_source;
+    Error *local_err = NULL;
+    Object *obj;
+
+    obj = object_property_get_link(OBJECT(dev), "chip", &local_err);
+    if (!obj) {
+        error_propagate(errp, local_err);
+        error_prepend(errp, "required link 'chip' not found: ");
+        return;
+    }
+
+    /* The PnvChip id identifies the XIVE interrupt controller. */
+    xive->chip = PNV_CHIP(obj);
+
+    /*
+     * The XiveSource and XiveENDSource objects are realized with the
+     * maximum allowed HW configuration. The ESB MMIO regions will be
+     * resized dynamically when the controller is configured by the FW
+     * to limit accesses to resources not provisioned.
+     */
+    object_property_set_int(OBJECT(xsrc), PNV_XIVE_NR_IRQS, "nr-irqs",
+                            &error_fatal);
+    object_property_add_const_link(OBJECT(xsrc), "xive", OBJECT(xive),
+                                   &error_fatal);
+    object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    object_property_set_int(OBJECT(end_xsrc), PNV_XIVE_NR_ENDS, "nr-ends",
+                            &error_fatal);
+    object_property_add_const_link(OBJECT(end_xsrc), "xive", OBJECT(xive),
+                                   &error_fatal);
+    object_property_set_bool(OBJECT(end_xsrc), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    /* Default page size. Generally changed at runtime to 64k */
+    xive->ic_shift = xive->vc_shift = xive->pc_shift = 12;
+
+    /* XSCOM region, used for initial configuration of the BARs */
+    memory_region_init_io(&xive->xscom_regs, OBJECT(dev), &pnv_xive_xscom_ops,
+                          xive, "xscom-xive", PNV9_XSCOM_XIVE_SIZE << 3);
+
+    /* Interrupt controller MMIO regions */
+    memory_region_init(&xive->ic_mmio, OBJECT(dev), "xive-ic",
+                       PNV9_XIVE_IC_SIZE);
+
+    memory_region_init_io(&xive->ic_reg_mmio, OBJECT(dev), &pnv_xive_ic_reg_ops,
+                          xive, "xive-ic-reg", 1 << xive->ic_shift);
+    memory_region_init_io(&xive->ic_notify_mmio, OBJECT(dev),
+                          &pnv_xive_ic_notify_ops,
+                          xive, "xive-ic-notify", 1 << xive->ic_shift);
+
+    /* The Pervasive LSI trigger and EOI pages (not modeled) */
+    memory_region_init_io(&xive->ic_lsi_mmio, OBJECT(dev), &pnv_xive_ic_lsi_ops,
+                          xive, "xive-ic-lsi", 2 << xive->ic_shift);
+
+    /* Thread Interrupt Management Area (Indirect) */
+    memory_region_init_io(&xive->tm_indirect_mmio, OBJECT(dev),
+                          &xive_tm_indirect_ops,
+                          xive, "xive-tima-indirect", PNV9_XIVE_TM_SIZE);
+    /*
+     * Overall Virtualization Controller MMIO region containing the
+     * IPI ESB pages and END ESB pages. The layout is defined by the
+     * EDT "Domain table" and the accesses are dispatched using
+     * address spaces for each.
+     */
+    memory_region_init_io(&xive->vc_mmio, OBJECT(xive), &pnv_xive_vc_ops, xive,
+                          "xive-vc", PNV9_XIVE_VC_SIZE);
+
+    memory_region_init(&xive->ipi_mmio, OBJECT(xive), "xive-vc-ipi",
+                       PNV9_XIVE_VC_SIZE);
+    address_space_init(&xive->ipi_as, &xive->ipi_mmio, "xive-vc-ipi");
+    memory_region_init(&xive->end_mmio, OBJECT(xive), "xive-vc-end",
+                       PNV9_XIVE_VC_SIZE);
+    address_space_init(&xive->end_as, &xive->end_mmio, "xive-vc-end");
+
+    /*
+     * The MMIO windows exposing the IPI ESBs and the END ESBs in the
+     * VC region. Their size is configured by the FW in the EDT table.
+     */
+    memory_region_init(&xive->ipi_edt_mmio, OBJECT(xive), "xive-vc-ipi-edt", 0);
+    memory_region_init(&xive->end_edt_mmio, OBJECT(xive), "xive-vc-end-edt", 0);
+
+    /* Presenter Controller MMIO region (not modeled) */
+    memory_region_init_io(&xive->pc_mmio, OBJECT(xive), &pnv_xive_pc_ops, xive,
+                          "xive-pc", PNV9_XIVE_PC_SIZE);
+
+    /* Thread Interrupt Management Area (Direct) */
+    memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops,
+                          xive, "xive-tima", PNV9_XIVE_TM_SIZE);
+
+    qemu_register_reset(pnv_xive_reset, dev);
+}
+
+static int pnv_xive_dt_xscom(PnvXScomInterface *dev, void *fdt,
+                             int xscom_offset)
+{
+    const char compat[] = "ibm,power9-xive-x";
+    char *name;
+    int offset;
+    uint32_t lpc_pcba = PNV9_XSCOM_XIVE_BASE;
+    uint32_t reg[] = {
+        cpu_to_be32(lpc_pcba),
+        cpu_to_be32(PNV9_XSCOM_XIVE_SIZE)
+    };
+
+    name = g_strdup_printf("xive@%x", lpc_pcba);
+    offset = fdt_add_subnode(fdt, xscom_offset, name);
+    _FDT(offset);
+    g_free(name);
+
+    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
+    _FDT((fdt_setprop(fdt, offset, "compatible", compat,
+                      sizeof(compat))));
+    return 0;
+}
+
+static Property pnv_xive_properties[] = {
+    DEFINE_PROP_UINT64("ic-bar", PnvXive, ic_base, 0),
+    DEFINE_PROP_UINT64("vc-bar", PnvXive, vc_base, 0),
+    DEFINE_PROP_UINT64("pc-bar", PnvXive, pc_base, 0),
+    DEFINE_PROP_UINT64("tm-bar", PnvXive, tm_base, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pnv_xive_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
+    XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass);
+    XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass);
+
+    xdc->dt_xscom = pnv_xive_dt_xscom;
+
+    dc->desc = "PowerNV XIVE Interrupt Controller";
+    dc->realize = pnv_xive_realize;
+    dc->props = pnv_xive_properties;
+
+    xrc->get_eas = pnv_xive_get_eas;
+    xrc->get_end = pnv_xive_get_end;
+    xrc->write_end = pnv_xive_write_end;
+    xrc->get_nvt = pnv_xive_get_nvt;
+    xrc->write_nvt = pnv_xive_write_nvt;
+    xrc->get_tctx = pnv_xive_get_tctx;
+
+    xnc->notify = pnv_xive_notify;
+};
+
+static const TypeInfo pnv_xive_info = {
+    .name          = TYPE_PNV_XIVE,
+    .parent        = TYPE_XIVE_ROUTER,
+    .instance_init = pnv_xive_init,
+    .instance_size = sizeof(PnvXive),
+    .class_init    = pnv_xive_class_init,
+    .interfaces    = (InterfaceInfo[]) {
+        { TYPE_PNV_XSCOM_INTERFACE },
+        { }
+    }
+};
+
+static void pnv_xive_register_types(void)
+{
+    type_register_static(&pnv_xive_info);
+}
+
+type_init(pnv_xive_register_types)
diff --git a/hw/intc/pnv_xive_regs.h b/hw/intc/pnv_xive_regs.h
new file mode 100644
index 0000000..c78f030
--- /dev/null
+++ b/hw/intc/pnv_xive_regs.h
@@ -0,0 +1,248 @@
+/*
+ * QEMU PowerPC XIVE interrupt controller model
+ *
+ * Copyright (c) 2017-2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_PNV_XIVE_REGS_H
+#define PPC_PNV_XIVE_REGS_H
+
+/* IC register offsets 0x0 - 0x400 */
+#define CQ_SWI_CMD_HIST         0x020
+#define CQ_SWI_CMD_POLL         0x028
+#define CQ_SWI_CMD_BCAST        0x030
+#define CQ_SWI_CMD_ASSIGN       0x038
+#define CQ_SWI_CMD_BLK_UPD      0x040
+#define CQ_SWI_RSP              0x048
+#define CQ_CFG_PB_GEN           0x050
+#define   CQ_INT_ADDR_OPT       PPC_BITMASK(14, 15)
+#define CQ_MSGSND               0x058
+#define CQ_CNPM_SEL             0x078
+#define CQ_IC_BAR               0x080
+#define   CQ_IC_BAR_VALID       PPC_BIT(0)
+#define   CQ_IC_BAR_64K         PPC_BIT(1)
+#define CQ_TM1_BAR              0x90
+#define CQ_TM2_BAR              0x0a0
+#define   CQ_TM_BAR_VALID       PPC_BIT(0)
+#define   CQ_TM_BAR_64K         PPC_BIT(1)
+#define CQ_PC_BAR               0x0b0
+#define  CQ_PC_BAR_VALID        PPC_BIT(0)
+#define CQ_PC_BARM              0x0b8
+#define  CQ_PC_BARM_MASK        PPC_BITMASK(26, 38)
+#define CQ_VC_BAR               0x0c0
+#define  CQ_VC_BAR_VALID        PPC_BIT(0)
+#define CQ_VC_BARM              0x0c8
+#define  CQ_VC_BARM_MASK        PPC_BITMASK(21, 37)
+#define CQ_TAR                  0x0f0
+#define  CQ_TAR_TBL_AUTOINC     PPC_BIT(0)
+#define  CQ_TAR_TSEL            PPC_BITMASK(12, 15)
+#define  CQ_TAR_TSEL_BLK        PPC_BIT(12)
+#define  CQ_TAR_TSEL_MIG        PPC_BIT(13)
+#define  CQ_TAR_TSEL_VDT        PPC_BIT(14)
+#define  CQ_TAR_TSEL_EDT        PPC_BIT(15)
+#define  CQ_TAR_TSEL_INDEX      PPC_BITMASK(26, 31)
+#define CQ_TDR                  0x0f8
+#define  CQ_TDR_VDT_VALID       PPC_BIT(0)
+#define  CQ_TDR_VDT_BLK         PPC_BITMASK(11, 15)
+#define  CQ_TDR_VDT_INDEX       PPC_BITMASK(28, 31)
+#define  CQ_TDR_EDT_TYPE        PPC_BITMASK(0, 1)
+#define  CQ_TDR_EDT_INVALID     0
+#define  CQ_TDR_EDT_IPI         1
+#define  CQ_TDR_EDT_EQ          2
+#define  CQ_TDR_EDT_BLK         PPC_BITMASK(12, 15)
+#define  CQ_TDR_EDT_INDEX       PPC_BITMASK(26, 31)
+#define CQ_PBI_CTL              0x100
+#define  CQ_PBI_PC_64K          PPC_BIT(5)
+#define  CQ_PBI_VC_64K          PPC_BIT(6)
+#define  CQ_PBI_LNX_TRIG        PPC_BIT(7)
+#define  CQ_PBI_FORCE_TM_LOCAL  PPC_BIT(22)
+#define CQ_PBO_CTL              0x108
+#define CQ_AIB_CTL              0x110
+#define CQ_RST_CTL              0x118
+#define CQ_FIRMASK              0x198
+#define CQ_FIRMASK_AND          0x1a0
+#define CQ_FIRMASK_OR           0x1a8
+
+/* PC LBS1 register offsets 0x400 - 0x800 */
+#define PC_TCTXT_CFG            0x400
+#define  PC_TCTXT_CFG_BLKGRP_EN         PPC_BIT(0)
+#define  PC_TCTXT_CFG_TARGET_EN         PPC_BIT(1)
+#define  PC_TCTXT_CFG_LGS_EN            PPC_BIT(2)
+#define  PC_TCTXT_CFG_STORE_ACK         PPC_BIT(3)
+#define  PC_TCTXT_CFG_HARD_CHIPID_BLK   PPC_BIT(8)
+#define  PC_TCTXT_CHIPID_OVERRIDE       PPC_BIT(9)
+#define  PC_TCTXT_CHIPID                PPC_BITMASK(12, 15)
+#define  PC_TCTXT_INIT_AGE              PPC_BITMASK(30, 31)
+#define PC_TCTXT_TRACK          0x408
+#define  PC_TCTXT_TRACK_EN              PPC_BIT(0)
+#define PC_TCTXT_INDIR0         0x420
+#define  PC_TCTXT_INDIR_VALID           PPC_BIT(0)
+#define  PC_TCTXT_INDIR_THRDID          PPC_BITMASK(9, 15)
+#define PC_TCTXT_INDIR1         0x428
+#define PC_TCTXT_INDIR2         0x430
+#define PC_TCTXT_INDIR3         0x438
+#define PC_THREAD_EN_REG0       0x440
+#define PC_THREAD_EN_REG0_SET   0x448
+#define PC_THREAD_EN_REG0_CLR   0x450
+#define PC_THREAD_EN_REG1       0x460
+#define PC_THREAD_EN_REG1_SET   0x468
+#define PC_THREAD_EN_REG1_CLR   0x470
+#define PC_GLOBAL_CONFIG        0x480
+#define  PC_GCONF_INDIRECT      PPC_BIT(32)
+#define  PC_GCONF_CHIPID_OVR    PPC_BIT(40)
+#define  PC_GCONF_CHIPID        PPC_BITMASK(44, 47)
+#define PC_VSD_TABLE_ADDR       0x488
+#define PC_VSD_TABLE_DATA       0x490
+#define PC_AT_KILL              0x4b0
+#define  PC_AT_KILL_VALID       PPC_BIT(0)
+#define  PC_AT_KILL_BLOCK_ID    PPC_BITMASK(27, 31)
+#define  PC_AT_KILL_OFFSET      PPC_BITMASK(48, 60)
+#define PC_AT_KILL_MASK         0x4b8
+
+/* PC LBS2 register offsets */
+#define PC_VPC_CACHE_ENABLE     0x708
+#define  PC_VPC_CACHE_EN_MASK   PPC_BITMASK(0, 31)
+#define PC_VPC_SCRUB_TRIG       0x710
+#define PC_VPC_SCRUB_MASK       0x718
+#define  PC_SCRUB_VALID         PPC_BIT(0)
+#define  PC_SCRUB_WANT_DISABLE  PPC_BIT(1)
+#define  PC_SCRUB_WANT_INVAL    PPC_BIT(2)
+#define  PC_SCRUB_BLOCK_ID      PPC_BITMASK(27, 31)
+#define  PC_SCRUB_OFFSET        PPC_BITMASK(45, 63)
+#define PC_VPC_CWATCH_SPEC      0x738
+#define  PC_VPC_CWATCH_CONFLICT PPC_BIT(0)
+#define  PC_VPC_CWATCH_FULL     PPC_BIT(8)
+#define  PC_VPC_CWATCH_BLOCKID  PPC_BITMASK(27, 31)
+#define  PC_VPC_CWATCH_OFFSET   PPC_BITMASK(45, 63)
+#define PC_VPC_CWATCH_DAT0      0x740
+#define PC_VPC_CWATCH_DAT1      0x748
+#define PC_VPC_CWATCH_DAT2      0x750
+#define PC_VPC_CWATCH_DAT3      0x758
+#define PC_VPC_CWATCH_DAT4      0x760
+#define PC_VPC_CWATCH_DAT5      0x768
+#define PC_VPC_CWATCH_DAT6      0x770
+#define PC_VPC_CWATCH_DAT7      0x778
+
+/* VC0 register offsets 0x800 - 0xFFF */
+#define VC_GLOBAL_CONFIG        0x800
+#define  VC_GCONF_INDIRECT      PPC_BIT(32)
+#define VC_VSD_TABLE_ADDR       0x808
+#define VC_VSD_TABLE_DATA       0x810
+#define VC_IVE_ISB_BLOCK_MODE   0x818
+#define VC_EQD_BLOCK_MODE       0x820
+#define VC_VPS_BLOCK_MODE       0x828
+#define VC_IRQ_CONFIG_IPI       0x840
+#define  VC_IRQ_CONFIG_MEMB_EN  PPC_BIT(45)
+#define  VC_IRQ_CONFIG_MEMB_SZ  PPC_BITMASK(46, 51)
+#define VC_IRQ_CONFIG_HW        0x848
+#define VC_IRQ_CONFIG_CASCADE1  0x850
+#define VC_IRQ_CONFIG_CASCADE2  0x858
+#define VC_IRQ_CONFIG_REDIST    0x860
+#define VC_IRQ_CONFIG_IPI_CASC  0x868
+#define  VC_AIB_TX_ORDER_TAG2_REL_TF    PPC_BIT(20)
+#define VC_AIB_TX_ORDER_TAG2    0x890
+#define VC_AT_MACRO_KILL        0x8b0
+#define VC_AT_MACRO_KILL_MASK   0x8b8
+#define  VC_KILL_VALID          PPC_BIT(0)
+#define  VC_KILL_TYPE           PPC_BITMASK(14, 15)
+#define   VC_KILL_IRQ   0
+#define   VC_KILL_IVC   1
+#define   VC_KILL_SBC   2
+#define   VC_KILL_EQD   3
+#define  VC_KILL_BLOCK_ID       PPC_BITMASK(27, 31)
+#define  VC_KILL_OFFSET         PPC_BITMASK(48, 60)
+#define VC_EQC_CACHE_ENABLE     0x908
+#define  VC_EQC_CACHE_EN_MASK   PPC_BITMASK(0, 15)
+#define VC_EQC_SCRUB_TRIG       0x910
+#define VC_EQC_SCRUB_MASK       0x918
+#define VC_EQC_CONFIG           0x920
+#define X_VC_EQC_CONFIG         0x214 /* XSCOM register */
+#define  VC_EQC_CONF_SYNC_IPI           PPC_BIT(32)
+#define  VC_EQC_CONF_SYNC_HW            PPC_BIT(33)
+#define  VC_EQC_CONF_SYNC_ESC1          PPC_BIT(34)
+#define  VC_EQC_CONF_SYNC_ESC2          PPC_BIT(35)
+#define  VC_EQC_CONF_SYNC_REDI          PPC_BIT(36)
+#define  VC_EQC_CONF_EQP_INTERLEAVE     PPC_BIT(38)
+#define  VC_EQC_CONF_ENABLE_END_s_BIT   PPC_BIT(39)
+#define  VC_EQC_CONF_ENABLE_END_u_BIT   PPC_BIT(40)
+#define  VC_EQC_CONF_ENABLE_END_c_BIT   PPC_BIT(41)
+#define  VC_EQC_CONF_ENABLE_MORE_QSZ    PPC_BIT(42)
+#define  VC_EQC_CONF_SKIP_ESCALATE      PPC_BIT(43)
+#define VC_EQC_CWATCH_SPEC      0x928
+#define  VC_EQC_CWATCH_CONFLICT PPC_BIT(0)
+#define  VC_EQC_CWATCH_FULL     PPC_BIT(8)
+#define  VC_EQC_CWATCH_BLOCKID  PPC_BITMASK(28, 31)
+#define  VC_EQC_CWATCH_OFFSET   PPC_BITMASK(40, 63)
+#define VC_EQC_CWATCH_DAT0      0x930
+#define VC_EQC_CWATCH_DAT1      0x938
+#define VC_EQC_CWATCH_DAT2      0x940
+#define VC_EQC_CWATCH_DAT3      0x948
+#define VC_IVC_SCRUB_TRIG       0x990
+#define VC_IVC_SCRUB_MASK       0x998
+#define VC_SBC_SCRUB_TRIG       0xa10
+#define VC_SBC_SCRUB_MASK       0xa18
+#define  VC_SCRUB_VALID         PPC_BIT(0)
+#define  VC_SCRUB_WANT_DISABLE  PPC_BIT(1)
+#define  VC_SCRUB_WANT_INVAL    PPC_BIT(2) /* EQC and SBC only */
+#define  VC_SCRUB_BLOCK_ID      PPC_BITMASK(28, 31)
+#define  VC_SCRUB_OFFSET        PPC_BITMASK(40, 63)
+#define VC_IVC_CACHE_ENABLE     0x988
+#define  VC_IVC_CACHE_EN_MASK   PPC_BITMASK(0, 15)
+#define VC_SBC_CACHE_ENABLE     0xa08
+#define  VC_SBC_CACHE_EN_MASK   PPC_BITMASK(0, 15)
+#define VC_IVC_CACHE_SCRUB_TRIG 0x990
+#define VC_IVC_CACHE_SCRUB_MASK 0x998
+#define VC_SBC_CACHE_ENABLE     0xa08
+#define VC_SBC_CACHE_SCRUB_TRIG 0xa10
+#define VC_SBC_CACHE_SCRUB_MASK 0xa18
+#define VC_SBC_CONFIG           0xa20
+#define  VC_SBC_CONF_CPLX_CIST  PPC_BIT(44)
+#define  VC_SBC_CONF_CIST_BOTH  PPC_BIT(45)
+#define  VC_SBC_CONF_NO_UPD_PRF PPC_BIT(59)
+
+/* VC1 register offsets */
+
+/* VSD Table address register definitions (shared) */
+#define VST_ADDR_AUTOINC        PPC_BIT(0)
+#define VST_TABLE_SELECT        PPC_BITMASK(13, 15)
+#define  VST_TSEL_IVT   0
+#define  VST_TSEL_SBE   1
+#define  VST_TSEL_EQDT  2
+#define  VST_TSEL_VPDT  3
+#define  VST_TSEL_IRQ   4       /* VC only */
+#define VST_TABLE_BLOCK        PPC_BITMASK(27, 31)
+
+/* Number of queue overflow pages */
+#define VC_QUEUE_OVF_COUNT      6
+
+/*
+ * Bits in a VSD entry.
+ *
+ * Note: the address is naturally aligned,  we don't use a PPC_BITMASK,
+ *       but just a mask to apply to the address before OR'ing it in.
+ *
+ * Note: VSD_FIRMWARE is a SW bit ! It hijacks an unused bit in the
+ *       VSD and is only meant to be used in indirect mode !
+ */
+#define VSD_MODE                PPC_BITMASK(0, 1)
+#define  VSD_MODE_SHARED        1
+#define  VSD_MODE_EXCLUSIVE     2
+#define  VSD_MODE_FORWARD       3
+#define VSD_ADDRESS_MASK        0x0ffffffffffff000ull
+#define VSD_MIGRATION_REG       PPC_BITMASK(52, 55)
+#define VSD_INDIRECT            PPC_BIT(56)
+#define VSD_TSIZE               PPC_BITMASK(59, 63)
+#define VSD_FIRMWARE            PPC_BIT(2) /* Read warning above */
+
+#define VC_EQC_SYNC_MASK         \
+        (VC_EQC_CONF_SYNC_IPI  | \
+         VC_EQC_CONF_SYNC_HW   | \
+         VC_EQC_CONF_SYNC_ESC1 | \
+         VC_EQC_CONF_SYNC_ESC2 | \
+         VC_EQC_CONF_SYNC_REDI)
+
+
+#endif /* PPC_PNV_XIVE_REGS_H */
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index e0e5cb5..097f88d 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -117,7 +117,7 @@
  * On sPAPR machines, use a simplified output for the XIVE END
  * structure dumping only the information related to the OS EQ.
  */
-static void spapr_xive_end_pic_print_info(sPAPRXive *xive, XiveEND *end,
+static void spapr_xive_end_pic_print_info(SpaprXive *xive, XiveEND *end,
                                           Monitor *mon)
 {
     uint32_t qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1);
@@ -135,7 +135,7 @@
     monitor_printf(mon, "]");
 }
 
-void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon)
+void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon)
 {
     XiveSource *xsrc = &xive->source;
     int i;
@@ -173,14 +173,14 @@
     }
 }
 
-static void spapr_xive_map_mmio(sPAPRXive *xive)
+static void spapr_xive_map_mmio(SpaprXive *xive)
 {
     sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->vc_base);
     sysbus_mmio_map(SYS_BUS_DEVICE(xive), 1, xive->end_base);
     sysbus_mmio_map(SYS_BUS_DEVICE(xive), 2, xive->tm_base);
 }
 
-void spapr_xive_mmio_set_enabled(sPAPRXive *xive, bool enable)
+void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable)
 {
     memory_region_set_enabled(&xive->source.esb_mmio, enable);
     memory_region_set_enabled(&xive->tm_mmio, enable);
@@ -216,7 +216,7 @@
 
 static void spapr_xive_reset(void *dev)
 {
-    sPAPRXive *xive = SPAPR_XIVE(dev);
+    SpaprXive *xive = SPAPR_XIVE(dev);
     int i;
 
     /*
@@ -242,7 +242,7 @@
 
 static void spapr_xive_instance_init(Object *obj)
 {
-    sPAPRXive *xive = SPAPR_XIVE(obj);
+    SpaprXive *xive = SPAPR_XIVE(obj);
 
     object_initialize_child(obj, "source", &xive->source, sizeof(xive->source),
                             TYPE_XIVE_SOURCE, &error_abort, NULL);
@@ -254,7 +254,7 @@
 
 static void spapr_xive_realize(DeviceState *dev, Error **errp)
 {
-    sPAPRXive *xive = SPAPR_XIVE(dev);
+    SpaprXive *xive = SPAPR_XIVE(dev);
     XiveSource *xsrc = &xive->source;
     XiveENDSource *end_xsrc = &xive->end_source;
     Error *local_err = NULL;
@@ -325,7 +325,7 @@
 static int spapr_xive_get_eas(XiveRouter *xrtr, uint8_t eas_blk,
                               uint32_t eas_idx, XiveEAS *eas)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    SpaprXive *xive = SPAPR_XIVE(xrtr);
 
     if (eas_idx >= xive->nr_irqs) {
         return -1;
@@ -338,7 +338,7 @@
 static int spapr_xive_get_end(XiveRouter *xrtr,
                               uint8_t end_blk, uint32_t end_idx, XiveEND *end)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    SpaprXive *xive = SPAPR_XIVE(xrtr);
 
     if (end_idx >= xive->nr_ends) {
         return -1;
@@ -352,7 +352,7 @@
                                 uint32_t end_idx, XiveEND *end,
                                 uint8_t word_number)
 {
-    sPAPRXive *xive = SPAPR_XIVE(xrtr);
+    SpaprXive *xive = SPAPR_XIVE(xrtr);
 
     if (end_idx >= xive->nr_ends) {
         return -1;
@@ -432,20 +432,20 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32_EQUAL(nr_irqs, sPAPRXive, NULL),
-        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(eat, sPAPRXive, nr_irqs,
+        VMSTATE_UINT32_EQUAL(nr_irqs, SpaprXive, NULL),
+        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(eat, SpaprXive, nr_irqs,
                                      vmstate_spapr_xive_eas, XiveEAS),
-        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(endt, sPAPRXive, nr_ends,
+        VMSTATE_STRUCT_VARRAY_POINTER_UINT32(endt, SpaprXive, nr_ends,
                                              vmstate_spapr_xive_end, XiveEND),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static Property spapr_xive_properties[] = {
-    DEFINE_PROP_UINT32("nr-irqs", sPAPRXive, nr_irqs, 0),
-    DEFINE_PROP_UINT32("nr-ends", sPAPRXive, nr_ends, 0),
-    DEFINE_PROP_UINT64("vc-base", sPAPRXive, vc_base, SPAPR_XIVE_VC_BASE),
-    DEFINE_PROP_UINT64("tm-base", sPAPRXive, tm_base, SPAPR_XIVE_TM_BASE),
+    DEFINE_PROP_UINT32("nr-irqs", SpaprXive, nr_irqs, 0),
+    DEFINE_PROP_UINT32("nr-ends", SpaprXive, nr_ends, 0),
+    DEFINE_PROP_UINT64("vc-base", SpaprXive, vc_base, SPAPR_XIVE_VC_BASE),
+    DEFINE_PROP_UINT64("tm-base", SpaprXive, tm_base, SPAPR_XIVE_TM_BASE),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -471,7 +471,7 @@
     .name = TYPE_SPAPR_XIVE,
     .parent = TYPE_XIVE_ROUTER,
     .instance_init = spapr_xive_instance_init,
-    .instance_size = sizeof(sPAPRXive),
+    .instance_size = sizeof(SpaprXive),
     .class_init = spapr_xive_class_init,
 };
 
@@ -482,7 +482,7 @@
 
 type_init(spapr_xive_register_types)
 
-bool spapr_xive_irq_claim(sPAPRXive *xive, uint32_t lisn, bool lsi)
+bool spapr_xive_irq_claim(SpaprXive *xive, uint32_t lisn, bool lsi)
 {
     XiveSource *xsrc = &xive->source;
 
@@ -497,7 +497,7 @@
     return true;
 }
 
-bool spapr_xive_irq_free(sPAPRXive *xive, uint32_t lisn)
+bool spapr_xive_irq_free(SpaprXive *xive, uint32_t lisn)
 {
     if (lisn >= xive->nr_irqs) {
         return false;
@@ -576,11 +576,11 @@
 #define SPAPR_XIVE_SRC_STORE_EOI     PPC_BIT(63) /* Store EOI support */
 
 static target_ulong h_int_get_source_info(PowerPCCPU *cpu,
-                                          sPAPRMachineState *spapr,
+                                          SpaprMachineState *spapr,
                                           target_ulong opcode,
                                           target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     XiveSource *xsrc = &xive->source;
     target_ulong flags  = args[0];
     target_ulong lisn   = args[1];
@@ -686,11 +686,11 @@
 #define SPAPR_XIVE_SRC_MASK     PPC_BIT(63)
 
 static target_ulong h_int_set_source_config(PowerPCCPU *cpu,
-                                            sPAPRMachineState *spapr,
+                                            SpaprMachineState *spapr,
                                             target_ulong opcode,
                                             target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     XiveEAS eas, new_eas;
     target_ulong flags    = args[0];
     target_ulong lisn     = args[1];
@@ -783,11 +783,11 @@
  *       equivalent to the LISN if not changed by H_INT_SET_SOURCE_CONFIG)
  */
 static target_ulong h_int_get_source_config(PowerPCCPU *cpu,
-                                            sPAPRMachineState *spapr,
+                                            SpaprMachineState *spapr,
                                             target_ulong opcode,
                                             target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     target_ulong flags = args[0];
     target_ulong lisn = args[1];
     XiveEAS eas;
@@ -856,11 +856,11 @@
  * - R5: Power of 2 page size of the notification page
  */
 static target_ulong h_int_get_queue_info(PowerPCCPU *cpu,
-                                         sPAPRMachineState *spapr,
+                                         SpaprMachineState *spapr,
                                          target_ulong opcode,
                                          target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     XiveENDSource *end_xsrc = &xive->end_source;
     target_ulong flags = args[0];
     target_ulong target = args[1];
@@ -942,11 +942,11 @@
 #define SPAPR_XIVE_END_ALWAYS_NOTIFY PPC_BIT(63)
 
 static target_ulong h_int_set_queue_config(PowerPCCPU *cpu,
-                                           sPAPRMachineState *spapr,
+                                           SpaprMachineState *spapr,
                                            target_ulong opcode,
                                            target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     target_ulong flags = args[0];
     target_ulong target = args[1];
     target_ulong priority = args[2];
@@ -1095,11 +1095,11 @@
 #define SPAPR_XIVE_END_DEBUG     PPC_BIT(63)
 
 static target_ulong h_int_get_queue_config(PowerPCCPU *cpu,
-                                           sPAPRMachineState *spapr,
+                                           SpaprMachineState *spapr,
                                            target_ulong opcode,
                                            target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     target_ulong flags = args[0];
     target_ulong target = args[1];
     target_ulong priority = args[2];
@@ -1187,7 +1187,7 @@
  * - None
  */
 static target_ulong h_int_set_os_reporting_line(PowerPCCPU *cpu,
-                                                sPAPRMachineState *spapr,
+                                                SpaprMachineState *spapr,
                                                 target_ulong opcode,
                                                 target_ulong *args)
 {
@@ -1223,7 +1223,7 @@
  * - R4: The logical real address of the reporting line if set, else -1
  */
 static target_ulong h_int_get_os_reporting_line(PowerPCCPU *cpu,
-                                                sPAPRMachineState *spapr,
+                                                SpaprMachineState *spapr,
                                                 target_ulong opcode,
                                                 target_ulong *args)
 {
@@ -1266,11 +1266,11 @@
 #define SPAPR_XIVE_ESB_STORE PPC_BIT(63)
 
 static target_ulong h_int_esb(PowerPCCPU *cpu,
-                              sPAPRMachineState *spapr,
+                              SpaprMachineState *spapr,
                               target_ulong opcode,
                               target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     XiveEAS eas;
     target_ulong flags  = args[0];
     target_ulong lisn   = args[1];
@@ -1334,11 +1334,11 @@
  * - None
  */
 static target_ulong h_int_sync(PowerPCCPU *cpu,
-                               sPAPRMachineState *spapr,
+                               SpaprMachineState *spapr,
                                target_ulong opcode,
                                target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     XiveEAS eas;
     target_ulong flags = args[0];
     target_ulong lisn = args[1];
@@ -1388,11 +1388,11 @@
  * - None
  */
 static target_ulong h_int_reset(PowerPCCPU *cpu,
-                                sPAPRMachineState *spapr,
+                                SpaprMachineState *spapr,
                                 target_ulong opcode,
                                 target_ulong *args)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     target_ulong flags   = args[0];
 
     if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
@@ -1407,7 +1407,7 @@
     return H_SUCCESS;
 }
 
-void spapr_xive_hcall_init(sPAPRMachineState *spapr)
+void spapr_xive_hcall_init(SpaprMachineState *spapr)
 {
     spapr_register_hypercall(H_INT_GET_SOURCE_INFO, h_int_get_source_info);
     spapr_register_hypercall(H_INT_SET_SOURCE_CONFIG, h_int_set_source_config);
@@ -1424,10 +1424,10 @@
     spapr_register_hypercall(H_INT_RESET, h_int_reset);
 }
 
-void spapr_dt_xive(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt,
+void spapr_dt_xive(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
                    uint32_t phandle)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
     int node;
     uint64_t timas[2 * 2];
     /* Interrupt number ranges for the IPIs */
diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c
index c6e1b63..78a252e 100644
--- a/hw/intc/xics_kvm.c
+++ b/hw/intc/xics_kvm.c
@@ -291,7 +291,7 @@
     }
 }
 
-static void rtas_dummy(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_dummy(PowerPCCPU *cpu, SpaprMachineState *spapr,
                        uint32_t token,
                        uint32_t nargs, target_ulong args,
                        uint32_t nret, target_ulong rets)
@@ -300,7 +300,7 @@
                  __func__);
 }
 
-int xics_kvm_init(sPAPRMachineState *spapr, Error **errp)
+int xics_kvm_init(SpaprMachineState *spapr, Error **errp)
 {
     int rc;
 
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 53bda66..607e1c1 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -41,7 +41,7 @@
  * Guest interfaces
  */
 
-static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_cppr(PowerPCCPU *cpu, SpaprMachineState *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     target_ulong cppr = args[0];
@@ -50,7 +50,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_ipi(PowerPCCPU *cpu, SpaprMachineState *spapr,
                           target_ulong opcode, target_ulong *args)
 {
     target_ulong mfrr = args[1];
@@ -64,7 +64,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_xirr(PowerPCCPU *cpu, SpaprMachineState *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
@@ -73,7 +73,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_xirr_x(PowerPCCPU *cpu, SpaprMachineState *spapr,
                              target_ulong opcode, target_ulong *args)
 {
     uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
@@ -83,7 +83,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_eoi(PowerPCCPU *cpu, SpaprMachineState *spapr,
                           target_ulong opcode, target_ulong *args)
 {
     target_ulong xirr = args[0];
@@ -92,7 +92,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr,
                             target_ulong opcode, target_ulong *args)
 {
     uint32_t mfrr;
@@ -104,7 +104,7 @@
     return H_SUCCESS;
 }
 
-static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr,
                           uint32_t token,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
@@ -137,7 +137,7 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_get_xive(PowerPCCPU *cpu, SpaprMachineState *spapr,
                           uint32_t token,
                           uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
@@ -167,7 +167,7 @@
     rtas_st(rets, 2, ics->irqs[srcno].priority);
 }
 
-static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
                          uint32_t token,
                          uint32_t nargs, target_ulong args,
                          uint32_t nret, target_ulong rets)
@@ -198,7 +198,7 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr,
                         uint32_t token,
                         uint32_t nargs, target_ulong args,
                         uint32_t nret, target_ulong rets)
@@ -230,7 +230,7 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-void xics_spapr_init(sPAPRMachineState *spapr)
+void xics_spapr_init(SpaprMachineState *spapr)
 {
     /* Registration of global state belongs into realize */
     spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
@@ -246,7 +246,7 @@
     spapr_register_hypercall(H_IPOLL, h_ipoll);
 }
 
-void spapr_dt_xics(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt,
+void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
                    uint32_t phandle)
 {
     uint32_t interrupt_server_ranges_prop[] = {
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index daa7bad..a0b8700 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -54,6 +54,8 @@
     switch (ring) {
     case TM_QW1_OS:
         return TM_QW1_NSR_EO;
+    case TM_QW3_HV_PHYS:
+        return TM_QW3_NSR_HE;
     default:
         g_assert_not_reached();
     }
@@ -88,7 +90,16 @@
     uint8_t *regs = &tctx->regs[ring];
 
     if (regs[TM_PIPR] < regs[TM_CPPR]) {
-        regs[TM_NSR] |= exception_mask(ring);
+        switch (ring) {
+        case TM_QW1_OS:
+            regs[TM_NSR] |= TM_QW1_NSR_EO;
+            break;
+        case TM_QW3_HV_PHYS:
+            regs[TM_NSR] |= (TM_QW3_NSR_HE_PHYS << 6);
+            break;
+        default:
+            g_assert_not_reached();
+        }
         qemu_irq_raise(tctx->output);
     }
 }
@@ -109,6 +120,38 @@
  * XIVE Thread Interrupt Management Area (TIMA)
  */
 
+static void xive_tm_set_hv_cppr(XiveTCTX *tctx, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    xive_tctx_set_cppr(tctx, TM_QW3_HV_PHYS, value & 0xff);
+}
+
+static uint64_t xive_tm_ack_hv_reg(XiveTCTX *tctx, hwaddr offset, unsigned size)
+{
+    return xive_tctx_accept(tctx, TM_QW3_HV_PHYS);
+}
+
+static uint64_t xive_tm_pull_pool_ctx(XiveTCTX *tctx, hwaddr offset,
+                                      unsigned size)
+{
+    uint64_t ret;
+
+    ret = tctx->regs[TM_QW2_HV_POOL + TM_WORD2] & TM_QW2W2_POOL_CAM;
+    tctx->regs[TM_QW2_HV_POOL + TM_WORD2] &= ~TM_QW2W2_POOL_CAM;
+    return ret;
+}
+
+static void xive_tm_vt_push(XiveTCTX *tctx, hwaddr offset,
+                            uint64_t value, unsigned size)
+{
+    tctx->regs[TM_QW3_HV_PHYS + TM_WORD2] = value & 0xff;
+}
+
+static uint64_t xive_tm_vt_poll(XiveTCTX *tctx, hwaddr offset, unsigned size)
+{
+    return tctx->regs[TM_QW3_HV_PHYS + TM_WORD2] & 0xff;
+}
+
 /*
  * Define an access map for each page of the TIMA that we will use in
  * the memory region ops to filter values when doing loads and stores
@@ -288,10 +331,16 @@
      * effects
      */
     { XIVE_TM_OS_PAGE, TM_QW1_OS + TM_CPPR,   1, xive_tm_set_os_cppr, NULL },
+    { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_CPPR, 1, xive_tm_set_hv_cppr, NULL },
+    { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, xive_tm_vt_push, NULL },
+    { XIVE_TM_HV_PAGE, TM_QW3_HV_PHYS + TM_WORD2, 1, NULL, xive_tm_vt_poll },
 
     /* MMIOs above 2K : special operations with side effects */
     { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG,     2, NULL, xive_tm_ack_os_reg },
     { XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending, NULL },
+    { XIVE_TM_HV_PAGE, TM_SPC_ACK_HV_REG,     2, NULL, xive_tm_ack_hv_reg },
+    { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX,  4, NULL, xive_tm_pull_pool_ctx },
+    { XIVE_TM_HV_PAGE, TM_SPC_PULL_POOL_CTX,  8, NULL, xive_tm_pull_pool_ctx },
 };
 
 static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool write)
@@ -317,14 +366,13 @@
 /*
  * TIMA MMIO handlers
  */
-static void xive_tm_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
+void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value,
+                        unsigned size)
 {
-    XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
     const XiveTmOp *xto;
 
     /*
-     * TODO: check V bit in Q[0-3]W2, check PTER bit associated with CPU
+     * TODO: check V bit in Q[0-3]W2
      */
 
     /*
@@ -356,13 +404,12 @@
     xive_tm_raw_write(tctx, offset, value, size);
 }
 
-static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size)
+uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size)
 {
-    XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
     const XiveTmOp *xto;
 
     /*
-     * TODO: check V bit in Q[0-3]W2, check PTER bit associated with CPU
+     * TODO: check V bit in Q[0-3]W2
      */
 
     /*
@@ -392,6 +439,21 @@
     return xive_tm_raw_read(tctx, offset, size);
 }
 
+static void xive_tm_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
+
+    xive_tctx_tm_write(tctx, offset, value, size);
+}
+
+static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size)
+{
+    XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
+
+    return xive_tctx_tm_read(tctx, offset, size);
+}
+
 const MemoryRegionOps xive_tm_ops = {
     .read = xive_tm_read,
     .write = xive_tm_write,
@@ -459,6 +521,8 @@
      */
     tctx->regs[TM_QW1_OS + TM_PIPR] =
         ipb_to_pipr(tctx->regs[TM_QW1_OS + TM_IPB]);
+    tctx->regs[TM_QW3_HV_PHYS + TM_PIPR] =
+        ipb_to_pipr(tctx->regs[TM_QW3_HV_PHYS + TM_IPB]);
 }
 
 static void xive_tctx_realize(DeviceState *dev, Error **errp)
@@ -1113,6 +1177,30 @@
 }
 
 /*
+ * By default on P9, the HW CAM line (23bits) is hardwired to :
+ *
+ *   0x000||0b1||4Bit chip number||7Bit Thread number.
+ *
+ * When the block grouping is enabled, the CAM line is changed to :
+ *
+ *   4Bit chip number||0x001||7Bit Thread number.
+ */
+static uint32_t hw_cam_line(uint8_t chip_id, uint8_t tid)
+{
+    return 1 << 11 | (chip_id & 0xf) << 7 | (tid & 0x7f);
+}
+
+static bool xive_presenter_tctx_match_hw(XiveTCTX *tctx,
+                                         uint8_t nvt_blk, uint32_t nvt_idx)
+{
+    CPUPPCState *env = &POWERPC_CPU(tctx->cs)->env;
+    uint32_t pir = env->spr_cb[SPR_PIR].default_value;
+
+    return hw_cam_line((pir >> 8) & 0xf, pir & 0x7f) ==
+        hw_cam_line(nvt_blk, nvt_idx);
+}
+
+/*
  * The thread context register words are in big-endian format.
  */
 static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format,
@@ -1120,6 +1208,7 @@
                                      bool cam_ignore, uint32_t logic_serv)
 {
     uint32_t cam = xive_nvt_cam_line(nvt_blk, nvt_idx);
+    uint32_t qw3w2 = xive_tctx_word2(&tctx->regs[TM_QW3_HV_PHYS]);
     uint32_t qw2w2 = xive_tctx_word2(&tctx->regs[TM_QW2_HV_POOL]);
     uint32_t qw1w2 = xive_tctx_word2(&tctx->regs[TM_QW1_OS]);
     uint32_t qw0w2 = xive_tctx_word2(&tctx->regs[TM_QW0_USER]);
@@ -1142,7 +1231,11 @@
 
         /* F=0 & i=0: Specific NVT notification */
 
-        /* TODO (PowerNV) : PHYS ring */
+        /* PHYS ring */
+        if ((be32_to_cpu(qw3w2) & TM_QW3W2_VT) &&
+            xive_presenter_tctx_match_hw(tctx, nvt_blk, nvt_idx)) {
+            return TM_QW3_HV_PHYS;
+        }
 
         /* HV POOL ring */
         if ((be32_to_cpu(qw2w2) & TM_QW2W2_VP) &&
@@ -1362,7 +1455,7 @@
     /* TODO: Auto EOI. */
 }
 
-static void xive_router_notify(XiveNotifier *xn, uint32_t lisn)
+void xive_router_notify(XiveNotifier *xn, uint32_t lisn)
 {
     XiveRouter *xrtr = XIVE_ROUTER(xn);
     uint8_t eas_blk = XIVE_SRCNO_BLOCK(lisn);
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index 599e0d4..b820c91 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -113,9 +113,9 @@
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
+    pflash_cfi02_register(flash_base, "lm32_evr.flash", flash_size,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          flash_sector_size, flash_size / flash_sector_size,
+                          flash_sector_size,
                           1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
     /* create irq lines */
@@ -206,9 +206,9 @@
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
+    pflash_cfi02_register(flash_base, "lm32_uclinux.flash", flash_size,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          flash_sector_size, flash_size / flash_sector_size,
+                          flash_sector_size,
                           1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
     /* create irq lines */
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 538f33b..689e633 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -120,10 +120,9 @@
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Numonyx JS28F256J3F105 */
-    pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
+    pflash_cfi01_register(flash_base, "milkymist.flash", flash_size,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          flash_sector_size, flash_size / flash_sector_size,
-                          2, 0x00, 0x89, 0x00, 0x1d, 1);
+                          flash_sector_size, 2, 0x00, 0x89, 0x00, 0x1d, 1);
 
     /* create irq lines */
     env->pic_state = lm32_pic_init(qemu_allocate_irq(cpu_irq_handler, cpu, 0));
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 18048d3..a907604 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -106,11 +106,9 @@
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* 5th parameter 2 means bank-width
      * 10th paremeter 0 means little-endian */
-    pflash_cfi01_register(FLASH_BASEADDR,
-                          NULL, "petalogix_ml605.flash", FLASH_SIZE,
+    pflash_cfi01_register(FLASH_BASEADDR, "petalogix_ml605.flash", FLASH_SIZE,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          64 * KiB, FLASH_SIZE >> 16,
-                          2, 0x89, 0x18, 0x0000, 0x0, 0);
+                          64 * KiB, 2, 0x89, 0x18, 0x0000, 0x0, 0);
 
 
     dev = qdev_create(NULL, "xlnx.xps-intc");
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index a0edaf8..88ce570 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -87,10 +87,9 @@
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(FLASH_BASEADDR,
-                          NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
+                          "petalogix_s3adsp1800.flash", FLASH_SIZE,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          64 * KiB, FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+                          64 * KiB, 1, 0x89, 0x18, 0x0000, 0x0, 1);
 
     dev = qdev_create(NULL, "xlnx.xps-intc");
     qdev_prop_set_uint32(dev, "kind-of-intr",
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 39aef4b..439665a 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -58,8 +58,6 @@
 #include "exec/semihost.h"
 #include "hw/mips/cps.h"
 
-//#define DEBUG_BOARD_INIT
-
 #define ENVP_ADDR		0x80002000l
 #define ENVP_NB_ENTRIES	 	16
 #define ENVP_ENTRY_SIZE	 	256
@@ -1189,13 +1187,12 @@
     const char *kernel_cmdline = machine->kernel_cmdline;
     const char *initrd_filename = machine->initrd_filename;
     char *filename;
-    pflash_t *fl;
+    PFlashCFI01 *fl;
     MemoryRegion *system_memory = get_system_memory();
     MemoryRegion *ram_high = g_new(MemoryRegion, 1);
     MemoryRegion *ram_low_preio = g_new(MemoryRegion, 1);
     MemoryRegion *ram_low_postio;
     MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1);
-    target_long bios_size = FLASH_SIZE;
     const size_t smbus_eeprom_size = 8 * 256;
     uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
     int64_t kernel_entry, bootloader_run_addr;
@@ -1208,7 +1205,6 @@
     DriveInfo *dinfo;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     int fl_idx = 0;
-    int fl_sectors = bios_size >> 16;
     int be;
 
     DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA);
@@ -1265,18 +1261,10 @@
 
     /* Load firmware in flash / BIOS. */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-#ifdef DEBUG_BOARD_INIT
-    if (dinfo) {
-        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
-               "addr %08llx '%s' %x\n",
-               fl_idx, bios_size, FLASH_ADDRESS,
-               blk_name(dinfo->bdrv), fl_sectors);
-    }
-#endif
-    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
-                               BIOS_SIZE,
+    fl = pflash_cfi01_register(FLASH_ADDRESS, "mips_malta.bios",
+                               FLASH_SIZE,
                                dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                               65536, fl_sectors,
+                               65536,
                                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
     bios = pflash_cfi01_get_memory(fl);
     fl_idx++;
@@ -1312,6 +1300,7 @@
                              bootloader_run_addr, kernel_entry);
         }
     } else {
+        target_long bios_size = FLASH_SIZE;
         /* The flash region isn't executable from a KVM guest */
         if (kvm_enabled()) {
             error_report("KVM enabled but no -kernel argument was specified. "
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index a015a6d..93dbf76 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -235,10 +235,9 @@
         load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
-        if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
+        if (!pflash_cfi01_register(0x1fc00000, "mips_r4k.bios", mips_rom,
                                    blk_by_legacy_dinfo(dinfo),
-                                   sector_len, mips_rom / sector_len,
-                                   4, 0, 0, 0, 0, be)) {
+                                   sector_len, 4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
         }
     } else if (!qtest_enabled()) {
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index d239e4b..63ba392 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -84,7 +84,7 @@
 
 #define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan"
 #define VIO_SPAPR_VLAN_DEVICE(obj) \
-     OBJECT_CHECK(VIOsPAPRVLANDevice, (obj), TYPE_VIO_SPAPR_VLAN_DEVICE)
+     OBJECT_CHECK(SpaprVioVlan, (obj), TYPE_VIO_SPAPR_VLAN_DEVICE)
 
 #define RX_POOL_MAX_BDS 4096
 #define RX_MAX_POOLS 5
@@ -95,8 +95,8 @@
     vlan_bd_t bds[RX_POOL_MAX_BDS];
 } RxBufPool;
 
-typedef struct VIOsPAPRVLANDevice {
-    VIOsPAPRDevice sdev;
+typedef struct SpaprVioVlan {
+    SpaprVioDevice sdev;
     NICConf nicconf;
     NICState *nic;
     MACAddr perm_mac;
@@ -107,11 +107,11 @@
     QEMUTimer *rxp_timer;
     uint32_t compat_flags;             /* Compatibility flags for migration */
     RxBufPool *rx_pool[RX_MAX_POOLS];  /* Receive buffer descriptor pools */
-} VIOsPAPRVLANDevice;
+} SpaprVioVlan;
 
 static int spapr_vlan_can_receive(NetClientState *nc)
 {
-    VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc);
+    SpaprVioVlan *dev = qemu_get_nic_opaque(nc);
 
     return (dev->isopen && dev->rx_bufs > 0);
 }
@@ -123,7 +123,7 @@
  * suitable receive buffer available. This function is used to increase
  * this counter by one.
  */
-static void spapr_vlan_record_dropped_rx_frame(VIOsPAPRVLANDevice *dev)
+static void spapr_vlan_record_dropped_rx_frame(SpaprVioVlan *dev)
 {
     uint64_t cnt;
 
@@ -134,7 +134,7 @@
 /**
  * Get buffer descriptor from one of our receive buffer pools
  */
-static vlan_bd_t spapr_vlan_get_rx_bd_from_pool(VIOsPAPRVLANDevice *dev,
+static vlan_bd_t spapr_vlan_get_rx_bd_from_pool(SpaprVioVlan *dev,
                                                 size_t size)
 {
     vlan_bd_t bd;
@@ -168,7 +168,7 @@
  * Get buffer descriptor from the receive buffer list page that has been
  * supplied by the guest with the H_REGISTER_LOGICAL_LAN call
  */
-static vlan_bd_t spapr_vlan_get_rx_bd_from_page(VIOsPAPRVLANDevice *dev,
+static vlan_bd_t spapr_vlan_get_rx_bd_from_page(SpaprVioVlan *dev,
                                                 size_t size)
 {
     int buf_ptr = dev->use_buf_ptr;
@@ -203,8 +203,8 @@
 static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
                                   size_t size)
 {
-    VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc);
-    VIOsPAPRDevice *sdev = VIO_SPAPR_DEVICE(dev);
+    SpaprVioVlan *dev = qemu_get_nic_opaque(nc);
+    SpaprVioDevice *sdev = VIO_SPAPR_DEVICE(dev);
     vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF);
     vlan_bd_t bd;
     uint64_t handle;
@@ -280,7 +280,7 @@
 
 static void spapr_vlan_flush_rx_queue(void *opaque)
 {
-    VIOsPAPRVLANDevice *dev = opaque;
+    SpaprVioVlan *dev = opaque;
 
     qemu_flush_queued_packets(qemu_get_queue(dev->nic));
 }
@@ -296,9 +296,9 @@
     memset(rxp->bds, 0, sizeof(rxp->bds));
 }
 
-static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
+static void spapr_vlan_reset(SpaprVioDevice *sdev)
 {
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     int i;
 
     dev->buf_list = 0;
@@ -316,9 +316,9 @@
     qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
 }
 
-static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
+static void spapr_vlan_realize(SpaprVioDevice *sdev, Error **errp)
 {
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
 
     qemu_macaddr_default_if_unset(&dev->nicconf.macaddr);
 
@@ -334,7 +334,7 @@
 
 static void spapr_vlan_instance_init(Object *obj)
 {
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(obj);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(obj);
     int i;
 
     device_add_bootindex_property(obj, &dev->nicconf.bootindex,
@@ -351,7 +351,7 @@
 
 static void spapr_vlan_instance_finalize(Object *obj)
 {
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(obj);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(obj);
     int i;
 
     if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) {
@@ -367,7 +367,7 @@
     }
 }
 
-void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
+void spapr_vlan_create(SpaprVioBus *bus, NICInfo *nd)
 {
     DeviceState *dev;
 
@@ -378,9 +378,9 @@
     qdev_init_nofail(dev);
 }
 
-static int spapr_vlan_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+static int spapr_vlan_devnode(SpaprVioDevice *dev, void *fdt, int node_off)
 {
-    VIOsPAPRVLANDevice *vdev = VIO_SPAPR_VLAN_DEVICE(dev);
+    SpaprVioVlan *vdev = VIO_SPAPR_VLAN_DEVICE(dev);
     uint8_t padded_mac[8] = {0, 0};
     int ret;
 
@@ -415,7 +415,7 @@
     return 0;
 }
 
-static int check_bd(VIOsPAPRVLANDevice *dev, vlan_bd_t bd,
+static int check_bd(SpaprVioVlan *dev, vlan_bd_t bd,
                     target_ulong alignment)
 {
     if ((VLAN_BD_ADDR(bd) % alignment)
@@ -434,7 +434,7 @@
 }
 
 static target_ulong h_register_logical_lan(PowerPCCPU *cpu,
-                                           sPAPRMachineState *spapr,
+                                           SpaprMachineState *spapr,
                                            target_ulong opcode,
                                            target_ulong *args)
 {
@@ -442,8 +442,8 @@
     target_ulong buf_list = args[1];
     target_ulong rec_queue = args[2];
     target_ulong filter_list = args[3];
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
+    SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     vlan_bd_t filter_list_bd;
 
     if (!dev) {
@@ -500,12 +500,12 @@
 
 
 static target_ulong h_free_logical_lan(PowerPCCPU *cpu,
-                                       sPAPRMachineState *spapr,
+                                       SpaprMachineState *spapr,
                                        target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
+    SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
 
     if (!dev) {
         return H_PARAMETER;
@@ -539,7 +539,7 @@
  * Search for a matching buffer pool with exact matching size,
  * or return -1 if no matching pool has been found.
  */
-static int spapr_vlan_get_rx_pool_id(VIOsPAPRVLANDevice *dev, int size)
+static int spapr_vlan_get_rx_pool_id(SpaprVioVlan *dev, int size)
 {
     int pool;
 
@@ -555,7 +555,7 @@
 /**
  * Enqueuing receive buffer by adding it to one of our receive buffer pools
  */
-static target_long spapr_vlan_add_rxbuf_to_pool(VIOsPAPRVLANDevice *dev,
+static target_long spapr_vlan_add_rxbuf_to_pool(SpaprVioVlan *dev,
                                                 target_ulong buf)
 {
     int size = VLAN_BD_LEN(buf);
@@ -602,7 +602,7 @@
  * This is the old way of enqueuing receive buffers: Add it to the rx queue
  * page that has been supplied by the guest (which is quite limited in size).
  */
-static target_long spapr_vlan_add_rxbuf_to_page(VIOsPAPRVLANDevice *dev,
+static target_long spapr_vlan_add_rxbuf_to_page(SpaprVioVlan *dev,
                                                 target_ulong buf)
 {
     vlan_bd_t bd;
@@ -628,14 +628,14 @@
 }
 
 static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
-                                             sPAPRMachineState *spapr,
+                                             SpaprMachineState *spapr,
                                              target_ulong opcode,
                                              target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong buf = args[1];
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
+    SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     target_long ret;
 
     trace_spapr_vlan_h_add_logical_lan_buffer(reg, buf);
@@ -678,14 +678,14 @@
 }
 
 static target_ulong h_send_logical_lan(PowerPCCPU *cpu,
-                                       sPAPRMachineState *spapr,
+                                       SpaprMachineState *spapr,
                                        target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong *bufs = args + 1;
     target_ulong continue_token = args[7];
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
+    SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     unsigned total_len;
     uint8_t *lbuf, *p;
     int i, nbufs;
@@ -745,11 +745,11 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_multicast_ctrl(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_multicast_ctrl(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                      target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 
     if (!dev) {
         return H_PARAMETER;
@@ -759,14 +759,14 @@
 }
 
 static target_ulong h_change_logical_lan_mac(PowerPCCPU *cpu,
-                                             sPAPRMachineState *spapr,
+                                             SpaprMachineState *spapr,
                                              target_ulong opcode,
                                              target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong macaddr = args[1];
-    VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
+    SpaprVioDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioVlan *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
     int i;
 
     for (i = 0; i < ETH_ALEN; i++) {
@@ -780,16 +780,16 @@
 }
 
 static Property spapr_vlan_properties[] = {
-    DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev),
-    DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
-    DEFINE_PROP_BIT("use-rx-buffer-pools", VIOsPAPRVLANDevice,
+    DEFINE_SPAPR_PROPERTIES(SpaprVioVlan, sdev),
+    DEFINE_NIC_PROPERTIES(SpaprVioVlan, nicconf),
+    DEFINE_PROP_BIT("use-rx-buffer-pools", SpaprVioVlan,
                     compat_flags, SPAPRVLAN_FLAG_RX_BUF_POOLS_BIT, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
 static bool spapr_vlan_rx_buffer_pools_needed(void *opaque)
 {
-    VIOsPAPRVLANDevice *dev = opaque;
+    SpaprVioVlan *dev = opaque;
 
     return (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) != 0;
 }
@@ -813,7 +813,7 @@
     .minimum_version_id = 1,
     .needed = spapr_vlan_rx_buffer_pools_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(rx_pool, VIOsPAPRVLANDevice,
+        VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(rx_pool, SpaprVioVlan,
                                            RX_MAX_POOLS, 1,
                                            vmstate_rx_buffer_pool, RxBufPool),
         VMSTATE_END_OF_LIST()
@@ -825,14 +825,14 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_SPAPR_VIO(sdev, VIOsPAPRVLANDevice),
+        VMSTATE_SPAPR_VIO(sdev, SpaprVioVlan),
         /* LLAN state */
-        VMSTATE_BOOL(isopen, VIOsPAPRVLANDevice),
-        VMSTATE_UINT64(buf_list, VIOsPAPRVLANDevice),
-        VMSTATE_UINT32(add_buf_ptr, VIOsPAPRVLANDevice),
-        VMSTATE_UINT32(use_buf_ptr, VIOsPAPRVLANDevice),
-        VMSTATE_UINT32(rx_bufs, VIOsPAPRVLANDevice),
-        VMSTATE_UINT64(rxq_ptr, VIOsPAPRVLANDevice),
+        VMSTATE_BOOL(isopen, SpaprVioVlan),
+        VMSTATE_UINT64(buf_list, SpaprVioVlan),
+        VMSTATE_UINT32(add_buf_ptr, SpaprVioVlan),
+        VMSTATE_UINT32(use_buf_ptr, SpaprVioVlan),
+        VMSTATE_UINT32(rx_bufs, SpaprVioVlan),
+        VMSTATE_UINT64(rxq_ptr, SpaprVioVlan),
 
         VMSTATE_END_OF_LIST()
     },
@@ -845,7 +845,7 @@
 static void spapr_vlan_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+    SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
 
     k->realize = spapr_vlan_realize;
     k->reset = spapr_vlan_reset;
@@ -863,7 +863,7 @@
 static const TypeInfo spapr_vlan_info = {
     .name          = TYPE_VIO_SPAPR_VLAN_DEVICE,
     .parent        = TYPE_VIO_SPAPR_DEVICE,
-    .instance_size = sizeof(VIOsPAPRVLANDevice),
+    .instance_size = sizeof(SpaprVioVlan),
     .class_init    = spapr_vlan_class_init,
     .instance_init = spapr_vlan_instance_init,
     .instance_finalize = spapr_vlan_instance_finalize,
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 7fdf04a..5c3a46c 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -85,7 +85,7 @@
     }
 
     /* check magic ID */
-    filehead = ((content[0] & 0xff) + (content[1] << 8)) & 0xffff;
+    filehead = lduw_le_p(content);
     if (filehead == 0xd8ff) {
         file_type = JPG_FILE;
     } else if (filehead == 0x4d42) {
@@ -96,7 +96,7 @@
 
     /* check BMP bpp */
     if (file_type == BMP_FILE) {
-        bmp_bpp = (content[28] + (content[29] << 8)) & 0xffff;
+        bmp_bpp = lduw_le_p(&content[28]);
         if (bmp_bpp != 24) {
             goto error;
         }
@@ -161,15 +161,14 @@
         }
         g_free(boot_splash_filedata);
         boot_splash_filedata = (uint8_t *)file_data;
-        boot_splash_filedata_size = file_size;
 
         /* insert data */
         if (file_type == JPG_FILE) {
             fw_cfg_add_file(s, "bootsplash.jpg",
-                    boot_splash_filedata, boot_splash_filedata_size);
+                            boot_splash_filedata, file_size);
         } else {
             fw_cfg_add_file(s, "bootsplash.bmp",
-                    boot_splash_filedata, boot_splash_filedata_size);
+                            boot_splash_filedata, file_size);
         }
         g_free(filename);
     }
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index bed1557..c98c757 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -36,28 +36,28 @@
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
 
-typedef struct sPAPRNVRAM {
-    VIOsPAPRDevice sdev;
+typedef struct SpaprNvram {
+    SpaprVioDevice sdev;
     uint32_t size;
     uint8_t *buf;
     BlockBackend *blk;
     VMChangeStateEntry *vmstate;
-} sPAPRNVRAM;
+} SpaprNvram;
 
 #define TYPE_VIO_SPAPR_NVRAM "spapr-nvram"
 #define VIO_SPAPR_NVRAM(obj) \
-     OBJECT_CHECK(sPAPRNVRAM, (obj), TYPE_VIO_SPAPR_NVRAM)
+     OBJECT_CHECK(SpaprNvram, (obj), TYPE_VIO_SPAPR_NVRAM)
 
 #define MIN_NVRAM_SIZE      (8 * KiB)
 #define DEFAULT_NVRAM_SIZE  (64 * KiB)
 #define MAX_NVRAM_SIZE      (1 * MiB)
 
-static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_nvram_fetch(PowerPCCPU *cpu, SpaprMachineState *spapr,
                              uint32_t token, uint32_t nargs,
                              target_ulong args,
                              uint32_t nret, target_ulong rets)
 {
-    sPAPRNVRAM *nvram = spapr->nvram;
+    SpaprNvram *nvram = spapr->nvram;
     hwaddr offset, buffer, len;
     void *membuf;
 
@@ -93,12 +93,12 @@
     rtas_st(rets, 1, len);
 }
 
-static void rtas_nvram_store(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_nvram_store(PowerPCCPU *cpu, SpaprMachineState *spapr,
                              uint32_t token, uint32_t nargs,
                              target_ulong args,
                              uint32_t nret, target_ulong rets)
 {
-    sPAPRNVRAM *nvram = spapr->nvram;
+    SpaprNvram *nvram = spapr->nvram;
     hwaddr offset, buffer, len;
     int alen;
     void *membuf;
@@ -139,9 +139,9 @@
     rtas_st(rets, 1, (alen < 0) ? 0 : alen);
 }
 
-static void spapr_nvram_realize(VIOsPAPRDevice *dev, Error **errp)
+static void spapr_nvram_realize(SpaprVioDevice *dev, Error **errp)
 {
-    sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
+    SpaprNvram *nvram = VIO_SPAPR_NVRAM(dev);
     int ret;
 
     if (nvram->blk) {
@@ -193,16 +193,16 @@
     spapr_rtas_register(RTAS_NVRAM_STORE, "nvram-store", rtas_nvram_store);
 }
 
-static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+static int spapr_nvram_devnode(SpaprVioDevice *dev, void *fdt, int node_off)
 {
-    sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
+    SpaprNvram *nvram = VIO_SPAPR_NVRAM(dev);
 
     return fdt_setprop_cell(fdt, node_off, "#bytes", nvram->size);
 }
 
 static int spapr_nvram_pre_load(void *opaque)
 {
-    sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(opaque);
+    SpaprNvram *nvram = VIO_SPAPR_NVRAM(opaque);
 
     g_free(nvram->buf);
     nvram->buf = NULL;
@@ -213,7 +213,7 @@
 
 static void postload_update_cb(void *opaque, int running, RunState state)
 {
-    sPAPRNVRAM *nvram = opaque;
+    SpaprNvram *nvram = opaque;
 
     /* This is called after bdrv_invalidate_cache_all.  */
 
@@ -225,7 +225,7 @@
 
 static int spapr_nvram_post_load(void *opaque, int version_id)
 {
-    sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(opaque);
+    SpaprNvram *nvram = VIO_SPAPR_NVRAM(opaque);
 
     if (nvram->blk) {
         nvram->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
@@ -242,22 +242,22 @@
     .pre_load = spapr_nvram_pre_load,
     .post_load = spapr_nvram_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(size, sPAPRNVRAM),
-        VMSTATE_VBUFFER_ALLOC_UINT32(buf, sPAPRNVRAM, 1, NULL, size),
+        VMSTATE_UINT32(size, SpaprNvram),
+        VMSTATE_VBUFFER_ALLOC_UINT32(buf, SpaprNvram, 1, NULL, size),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static Property spapr_nvram_properties[] = {
-    DEFINE_SPAPR_PROPERTIES(sPAPRNVRAM, sdev),
-    DEFINE_PROP_DRIVE("drive", sPAPRNVRAM, blk),
+    DEFINE_SPAPR_PROPERTIES(SpaprNvram, sdev),
+    DEFINE_PROP_DRIVE("drive", SpaprNvram, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
 static void spapr_nvram_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+    SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
 
     k->realize = spapr_nvram_realize;
     k->devnode = spapr_nvram_devnode;
@@ -274,7 +274,7 @@
 static const TypeInfo spapr_nvram_type_info = {
     .name          = TYPE_VIO_SPAPR_NVRAM,
     .parent        = TYPE_VIO_SPAPR_DEVICE,
-    .instance_size = sizeof(sPAPRNVRAM),
+    .instance_size = sizeof(SpaprNvram),
     .class_init    = spapr_nvram_class_init,
 };
 
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 7553f67..beb2efd 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -42,6 +42,7 @@
 #include "qemu/error-report.h"
 #include "hw/platform-bus.h"
 #include "hw/net/fsl_etsec/etsec.h"
+#include "hw/i2c/i2c.h"
 
 #define EPAPR_MAGIC                (0x45504150)
 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
@@ -63,7 +64,10 @@
 #define MPC8544_PCI_REGS_SIZE      0x1000ULL
 #define MPC8544_UTIL_OFFSET        0xe0000ULL
 #define MPC8XXX_GPIO_OFFSET        0x000FF000ULL
+#define MPC8544_I2C_REGS_OFFSET    0x3000ULL
 #define MPC8XXX_GPIO_IRQ           47
+#define MPC8544_I2C_IRQ            43
+#define RTC_REGS_OFFSET            0x68
 
 struct boot_info
 {
@@ -161,6 +165,39 @@
     g_free(poweroff);
 }
 
+static void dt_rtc_create(void *fdt, const char *i2c, const char *alias)
+{
+    int offset = RTC_REGS_OFFSET;
+
+    gchar *rtc = g_strdup_printf("%s/rtc@%"PRIx32, i2c, offset);
+    qemu_fdt_add_subnode(fdt, rtc);
+    qemu_fdt_setprop_string(fdt, rtc, "compatible", "pericom,pt7c4338");
+    qemu_fdt_setprop_cells(fdt, rtc, "reg", offset);
+    qemu_fdt_setprop_string(fdt, "/aliases", alias, rtc);
+
+    g_free(rtc);
+}
+
+static void dt_i2c_create(void *fdt, const char *soc, const char *mpic,
+                             const char *alias)
+{
+    hwaddr mmio0 = MPC8544_I2C_REGS_OFFSET;
+    int irq0 = MPC8544_I2C_IRQ;
+
+    gchar *i2c = g_strdup_printf("%s/i2c@%"PRIx64, soc, mmio0);
+    qemu_fdt_add_subnode(fdt, i2c);
+    qemu_fdt_setprop_string(fdt, i2c, "device_type", "i2c");
+    qemu_fdt_setprop_string(fdt, i2c, "compatible", "fsl-i2c");
+    qemu_fdt_setprop_cells(fdt, i2c, "reg", mmio0, 0x14);
+    qemu_fdt_setprop_cells(fdt, i2c, "cell-index", 0);
+    qemu_fdt_setprop_cells(fdt, i2c, "interrupts", irq0, 0x2);
+    qemu_fdt_setprop_phandle(fdt, i2c, "interrupt-parent", mpic);
+    qemu_fdt_setprop_string(fdt, "/aliases", alias, i2c);
+
+    g_free(i2c);
+}
+
+
 typedef struct PlatformDevtreeData {
     void *fdt;
     const char *mpic;
@@ -464,6 +501,12 @@
                          soc, mpic, "serial0", 0, true);
     }
 
+    /* i2c */
+    dt_i2c_create(fdt, soc, mpic, "i2c");
+
+    dt_rtc_create(fdt, "i2c", "rtc");
+
+
     gutil = g_strdup_printf("%s/global-utilities@%llx", soc,
                             MPC8544_UTIL_OFFSET);
     qemu_fdt_add_subnode(fdt, gutil);
@@ -812,6 +855,7 @@
     MemoryRegion *ccsr_addr_space;
     SysBusDevice *s;
     PPCE500CCSRState *ccsr;
+    I2CBus *i2c;
 
     irqs = g_new0(IrqLines, smp_cpus);
     for (i = 0; i < smp_cpus; i++) {
@@ -887,6 +931,16 @@
                        0, qdev_get_gpio_in(mpicdev, 42), 399193,
                        serial_hd(1), DEVICE_BIG_ENDIAN);
     }
+        /* I2C */
+    dev = qdev_create(NULL, "mpc-i2c");
+    s = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8544_I2C_IRQ));
+    memory_region_add_subregion(ccsr_addr_space, MPC8544_I2C_REGS_OFFSET,
+                                sysbus_mmio_get_region(s, 0));
+    i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
+    i2c_create_slave(i2c, "ds1338", RTC_REGS_OFFSET);
+
 
     /* General Utility device */
     dev = qdev_create(NULL, "mpc8544-guts");
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 97e8817..02d8559 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -547,11 +547,11 @@
             return g_strdup("cdrom");
         }
 
-        return g_strdup("hd");
+        return g_strdup("disk");
     }
 
     if (!strcmp(object_get_typename(OBJECT(dev)), "ide-hd")) {
-        return g_strdup("hd");
+        return g_strdup("disk");
     }
 
     if (!strcmp(object_get_typename(OBJECT(dev)), "ide-cd")) {
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index cc1e463..460cbc7 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -402,11 +402,11 @@
             return g_strdup("cdrom");
         }
 
-        return g_strdup("hd");
+        return g_strdup("disk");
     }
 
     if (!strcmp(object_get_typename(OBJECT(dev)), "ide-hd")) {
-        return g_strdup("hd");
+        return g_strdup("disk");
     }
 
     if (!strcmp(object_get_typename(OBJECT(dev)), "ide-cd")) {
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 3d5dfef..8be4d4c 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -267,7 +267,7 @@
     g_free(reg);
 }
 
-static void pnv_dt_chip(PnvChip *chip, void *fdt)
+static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
 {
     const char *typename = pnv_chip_core_typename(chip);
     size_t typesize = object_type_get_instance_size(typename);
@@ -289,6 +289,27 @@
     }
 }
 
+static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
+{
+    const char *typename = pnv_chip_core_typename(chip);
+    size_t typesize = object_type_get_instance_size(typename);
+    int i;
+
+    pnv_dt_xscom(chip, fdt, 0);
+
+    for (i = 0; i < chip->nr_cores; i++) {
+        PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
+
+        pnv_dt_core(chip, pnv_core, fdt);
+    }
+
+    if (chip->ram_size) {
+        pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
+    }
+
+    pnv_dt_lpc(chip, fdt, 0);
+}
+
 static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
 {
     uint32_t io_base = d->ioport_id;
@@ -398,24 +419,12 @@
     return 0;
 }
 
-static int pnv_chip_isa_offset(PnvChip *chip, void *fdt)
-{
-    char *name;
-    int offset;
-
-    name = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
-                           (uint64_t) PNV_XSCOM_BASE(chip), PNV_XSCOM_LPC_BASE);
-    offset = fdt_path_offset(fdt, name);
-    g_free(name);
-    return offset;
-}
-
 /* The default LPC bus of a multichip system is on chip 0. It's
  * recognized by the firmware (skiboot) using a "primary" property.
  */
 static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
 {
-    int isa_offset = pnv_chip_isa_offset(pnv->chips[0], fdt);
+    int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
     ForeachPopulateArgs args = {
         .fdt = fdt,
         .offset = isa_offset,
@@ -429,6 +438,16 @@
                        &args);
 }
 
+static void pnv_dt_power_mgt(void *fdt)
+{
+    int off;
+
+    off = fdt_add_subnode(fdt, 0, "ibm,opal");
+    off = fdt_add_subnode(fdt, off, "power-mgt");
+
+    _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
+}
+
 static void *pnv_dt_create(MachineState *machine)
 {
     const char plat_compat[] = "qemu,powernv\0ibm,powernv";
@@ -474,7 +493,7 @@
 
     /* Populate device tree for each chip */
     for (i = 0; i < pnv->num_chips; i++) {
-        pnv_dt_chip(pnv->chips[i], fdt);
+        PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
     }
 
     /* Populate ISA devices on chip 0 */
@@ -484,6 +503,11 @@
         pnv_dt_bmc_sensors(pnv->bmc, fdt);
     }
 
+    /* Create an extra node for power management on Power9 */
+    if (pnv_is_power9(pnv)) {
+        pnv_dt_power_mgt(fdt);
+    }
+
     return fdt;
 }
 
@@ -540,7 +564,8 @@
 
 static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
 {
-    return NULL;
+    Pnv9Chip *chip9 = PNV9_CHIP(chip);
+    return pnv_lpc_isa_create(&chip9->lpc, false, errp);
 }
 
 static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
@@ -548,6 +573,21 @@
     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
 }
 
+static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
+{
+    Pnv8Chip *chip8 = PNV8_CHIP(chip);
+
+    ics_pic_print_info(&chip8->psi.ics, mon);
+}
+
+static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
+{
+    Pnv9Chip *chip9 = PNV9_CHIP(chip);
+
+    pnv_xive_pic_print_info(&chip9->xive, mon);
+    pnv_psi_pic_print_info(&chip9->psi, mon);
+}
+
 static void pnv_init(MachineState *machine)
 {
     PnvMachineState *pnv = PNV_MACHINE(machine);
@@ -684,7 +724,7 @@
         return;
     }
 
-    pnv_cpu->icp = ICP(obj);
+    pnv_cpu->intc = obj;
 }
 
 /*
@@ -705,7 +745,23 @@
 static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
                                         Error **errp)
 {
-    return;
+    Pnv9Chip *chip9 = PNV9_CHIP(chip);
+    Error *local_err = NULL;
+    Object *obj;
+    PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
+
+    /*
+     * The core creates its interrupt presenter but the XIVE interrupt
+     * controller object is initialized afterwards. Hopefully, it's
+     * only used at runtime.
+     */
+    obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), errp);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    pnv_cpu->intc = obj;
 }
 
 /* Allowed core identifiers on a POWER8 Processor Chip :
@@ -739,17 +795,17 @@
     Pnv8Chip *chip8 = PNV8_CHIP(obj);
 
     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
-                            TYPE_PNV_PSI, &error_abort, NULL);
+                            TYPE_PNV8_PSI, &error_abort, NULL);
     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
                                    OBJECT(qdev_get_machine()), &error_abort);
 
     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
-                            TYPE_PNV_LPC, &error_abort, NULL);
+                            TYPE_PNV8_LPC, &error_abort, NULL);
     object_property_add_const_link(OBJECT(&chip8->lpc), "psi",
                                    OBJECT(&chip8->psi), &error_abort);
 
     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
-                            TYPE_PNV_OCC, &error_abort, NULL);
+                            TYPE_PNV8_OCC, &error_abort, NULL);
     object_property_add_const_link(OBJECT(&chip8->occ), "psi",
                                    OBJECT(&chip8->psi), &error_abort);
 }
@@ -791,6 +847,7 @@
     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
     PnvChip *chip = PNV_CHIP(dev);
     Pnv8Chip *chip8 = PNV8_CHIP(dev);
+    Pnv8Psi *psi8 = &chip8->psi;
     Error *local_err = NULL;
 
     pcc->parent_realize(dev, &local_err);
@@ -807,13 +864,18 @@
         error_propagate(errp, local_err);
         return;
     }
-    pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, &chip8->psi.xscom_regs);
+    pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
+                            &PNV_PSI(psi8)->xscom_regs);
 
     /* Create LPC controller */
     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
                              &error_fatal);
     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
 
+    chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
+                                            (uint64_t) PNV_XSCOM_BASE(chip),
+                                            PNV_XSCOM_LPC_BASE);
+
     /* Interrupt Management Area. This is the memory region holding
      * all the Interrupt Control Presenter (ICP) registers */
     pnv_chip_icp_realize(chip8, &local_err);
@@ -842,6 +904,8 @@
     k->core_pir = pnv_chip_core_pir_p8;
     k->intc_create = pnv_chip_power8_intc_create;
     k->isa_create = pnv_chip_power8_isa_create;
+    k->dt_populate = pnv_chip_power8_dt_populate;
+    k->pic_print_info = pnv_chip_power8_pic_print_info;
     k->xscom_base = 0x003fc0000000000ull;
     dc->desc = "PowerNV Chip POWER8E";
 
@@ -860,6 +924,8 @@
     k->core_pir = pnv_chip_core_pir_p8;
     k->intc_create = pnv_chip_power8_intc_create;
     k->isa_create = pnv_chip_power8_isa_create;
+    k->dt_populate = pnv_chip_power8_dt_populate;
+    k->pic_print_info = pnv_chip_power8_pic_print_info;
     k->xscom_base = 0x003fc0000000000ull;
     dc->desc = "PowerNV Chip POWER8";
 
@@ -878,6 +944,8 @@
     k->core_pir = pnv_chip_core_pir_p8;
     k->intc_create = pnv_chip_power8_intc_create;
     k->isa_create = pnv_chip_power8nvl_isa_create;
+    k->dt_populate = pnv_chip_power8_dt_populate;
+    k->pic_print_info = pnv_chip_power8_pic_print_info;
     k->xscom_base = 0x003fc0000000000ull;
     dc->desc = "PowerNV Chip POWER8NVL";
 
@@ -887,11 +955,65 @@
 
 static void pnv_chip_power9_instance_init(Object *obj)
 {
+    Pnv9Chip *chip9 = PNV9_CHIP(obj);
+
+    object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
+                            TYPE_PNV_XIVE, &error_abort, NULL);
+    object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj,
+                                   &error_abort);
+
+    object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
+                            TYPE_PNV9_PSI, &error_abort, NULL);
+    object_property_add_const_link(OBJECT(&chip9->psi), "chip", obj,
+                                   &error_abort);
+
+    object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
+                            TYPE_PNV9_LPC, &error_abort, NULL);
+    object_property_add_const_link(OBJECT(&chip9->lpc), "psi",
+                                   OBJECT(&chip9->psi), &error_abort);
+
+    object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
+                            TYPE_PNV9_OCC, &error_abort, NULL);
+    object_property_add_const_link(OBJECT(&chip9->occ), "psi",
+                                   OBJECT(&chip9->psi), &error_abort);
+}
+
+static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
+{
+    PnvChip *chip = PNV_CHIP(chip9);
+    const char *typename = pnv_chip_core_typename(chip);
+    size_t typesize = object_type_get_instance_size(typename);
+    int i;
+
+    chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
+    chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
+
+    for (i = 0; i < chip9->nr_quads; i++) {
+        char eq_name[32];
+        PnvQuad *eq = &chip9->quads[i];
+        PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize);
+        int core_id = CPU_CORE(pnv_core)->core_id;
+
+        object_initialize(eq, sizeof(*eq), TYPE_PNV_QUAD);
+        snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
+
+        object_property_add_child(OBJECT(chip), eq_name, OBJECT(eq),
+                                  &error_fatal);
+        object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
+        object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
+        object_unref(OBJECT(eq));
+
+        pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
+                                &eq->xscom_regs);
+    }
 }
 
 static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
 {
     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
+    Pnv9Chip *chip9 = PNV9_CHIP(dev);
+    PnvChip *chip = PNV_CHIP(dev);
+    Pnv9Psi *psi9 = &chip9->psi;
     Error *local_err = NULL;
 
     pcc->parent_realize(dev, &local_err);
@@ -899,6 +1021,61 @@
         error_propagate(errp, local_err);
         return;
     }
+
+    pnv_chip_quad_realize(chip9, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    /* XIVE interrupt controller (POWER9) */
+    object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
+                            "ic-bar", &error_fatal);
+    object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
+                            "vc-bar", &error_fatal);
+    object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
+                            "pc-bar", &error_fatal);
+    object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
+                            "tm-bar", &error_fatal);
+    object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
+                             &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
+                            &chip9->xive.xscom_regs);
+
+    /* Processor Service Interface (PSI) Host Bridge */
+    object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
+                            "bar", &error_fatal);
+    object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
+                            &PNV_PSI(psi9)->xscom_regs);
+
+    /* LPC */
+    object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
+                                &chip9->lpc.xscom_regs);
+
+    chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
+                                            (uint64_t) PNV9_LPCM_BASE(chip));
+
+    /* Create the simplified OCC model */
+    object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+    pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
 }
 
 static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
@@ -912,6 +1089,8 @@
     k->core_pir = pnv_chip_core_pir_p9;
     k->intc_create = pnv_chip_power9_intc_create;
     k->isa_create = pnv_chip_power9_isa_create;
+    k->dt_populate = pnv_chip_power9_dt_populate;
+    k->pic_print_info = pnv_chip_power9_pic_print_info;
     k->xscom_base = 0x00603fc00000000ull;
     dc->desc = "PowerNV Chip POWER9";
 
@@ -1007,7 +1186,7 @@
         if (!pnv_chip_is_power9(chip)) {
             xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid);
         } else {
-            xscom_core_base = PNV_XSCOM_P9_EC_BASE(core_hwid);
+            xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid);
         }
 
         pnv_xscom_add_subregion(chip, xscom_core_base,
@@ -1082,27 +1261,11 @@
     }
 }
 
-static PowerPCCPU *ppc_get_vcpu_by_pir(int pir)
-{
-    CPUState *cs;
-
-    CPU_FOREACH(cs) {
-        PowerPCCPU *cpu = POWERPC_CPU(cs);
-        CPUPPCState *env = &cpu->env;
-
-        if (env->spr_cb[SPR_PIR].default_value == pir) {
-            return cpu;
-        }
-    }
-
-    return NULL;
-}
-
 static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
 {
     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
 
-    return cpu ? pnv_cpu_state(cpu)->icp : NULL;
+    return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
 }
 
 static void pnv_pic_print_info(InterruptStatsProvider *obj,
@@ -1115,12 +1278,15 @@
     CPU_FOREACH(cs) {
         PowerPCCPU *cpu = POWERPC_CPU(cs);
 
-        icp_pic_print_info(pnv_cpu_state(cpu)->icp, mon);
+        if (pnv_chip_is_power9(pnv->chips[0])) {
+            xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
+        } else {
+            icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
+        }
     }
 
     for (i = 0; i < pnv->num_chips; i++) {
-        Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
-        ics_pic_print_info(&chip8->psi.ics, mon);
+        PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
     }
 }
 
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 7c806da..5feeed6 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -60,8 +60,8 @@
 #define PNV_XSCOM_EX_DTS_RESULT0     0x50000
 #define PNV_XSCOM_EX_DTS_RESULT1     0x50001
 
-static uint64_t pnv_core_xscom_read(void *opaque, hwaddr addr,
-                                    unsigned int width)
+static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr,
+                                           unsigned int width)
 {
     uint32_t offset = addr >> 3;
     uint64_t val = 0;
@@ -82,16 +82,74 @@
     return val;
 }
 
-static void pnv_core_xscom_write(void *opaque, hwaddr addr, uint64_t val,
-                                 unsigned int width)
+static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val,
+                                        unsigned int width)
 {
     qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n",
                   addr);
 }
 
-static const MemoryRegionOps pnv_core_xscom_ops = {
-    .read = pnv_core_xscom_read,
-    .write = pnv_core_xscom_write,
+static const MemoryRegionOps pnv_core_power8_xscom_ops = {
+    .read = pnv_core_power8_xscom_read,
+    .write = pnv_core_power8_xscom_write,
+    .valid.min_access_size = 8,
+    .valid.max_access_size = 8,
+    .impl.min_access_size = 8,
+    .impl.max_access_size = 8,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+
+/*
+ * POWER9 core controls
+ */
+#define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d
+#define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a
+
+static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
+                                           unsigned int width)
+{
+    uint32_t offset = addr >> 3;
+    uint64_t val = 0;
+
+    /* The result should be 38 C */
+    switch (offset) {
+    case PNV_XSCOM_EX_DTS_RESULT0:
+        val = 0x26f024f023f0000ull;
+        break;
+    case PNV_XSCOM_EX_DTS_RESULT1:
+        val = 0x24f000000000000ull;
+        break;
+    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
+    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
+        val = 0x0;
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n",
+                  addr);
+    }
+
+    return val;
+}
+
+static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
+                                        unsigned int width)
+{
+    uint32_t offset = addr >> 3;
+
+    switch (offset) {
+    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
+    case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n",
+                      addr);
+    }
+}
+
+static const MemoryRegionOps pnv_core_power9_xscom_ops = {
+    .read = pnv_core_power9_xscom_read,
+    .write = pnv_core_power9_xscom_write,
     .valid.min_access_size = 8,
     .valid.max_access_size = 8,
     .impl.min_access_size = 8,
@@ -138,6 +196,7 @@
 static void pnv_core_realize(DeviceState *dev, Error **errp)
 {
     PnvCore *pc = PNV_CORE(OBJECT(dev));
+    PnvCoreClass *pcc = PNV_CORE_GET_CLASS(pc);
     CPUCore *cc = CPU_CORE(OBJECT(dev));
     const char *typename = pnv_core_cpu_typename(pc);
     Error *local_err = NULL;
@@ -180,7 +239,7 @@
     }
 
     snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id);
-    pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), &pnv_core_xscom_ops,
+    pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops,
                           pc, name, PNV_XSCOM_EX_SIZE);
     return;
 
@@ -198,7 +257,7 @@
     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
 
     qemu_unregister_reset(pnv_cpu_reset, cpu);
-    object_unparent(OBJECT(pnv_cpu_state(cpu)->icp));
+    object_unparent(OBJECT(pnv_cpu_state(cpu)->intc));
     cpu_remove_sync(CPU(cpu));
     cpu->machine_data = NULL;
     g_free(pnv_cpu);
@@ -222,6 +281,20 @@
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void pnv_core_power8_class_init(ObjectClass *oc, void *data)
+{
+    PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
+
+    pcc->xscom_ops = &pnv_core_power8_xscom_ops;
+}
+
+static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
+{
+    PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
+
+    pcc->xscom_ops = &pnv_core_power9_xscom_ops;
+}
+
 static void pnv_core_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
@@ -231,10 +304,11 @@
     dc->props = pnv_core_properties;
 }
 
-#define DEFINE_PNV_CORE_TYPE(cpu_model)         \
+#define DEFINE_PNV_CORE_TYPE(family, cpu_model) \
     {                                           \
         .parent = TYPE_PNV_CORE,                \
         .name = PNV_CORE_TYPE_NAME(cpu_model),  \
+        .class_init = pnv_core_##family##_class_init, \
     }
 
 static const TypeInfo pnv_core_infos[] = {
@@ -246,10 +320,97 @@
         .class_init = pnv_core_class_init,
         .abstract       = true,
     },
-    DEFINE_PNV_CORE_TYPE("power8e_v2.1"),
-    DEFINE_PNV_CORE_TYPE("power8_v2.0"),
-    DEFINE_PNV_CORE_TYPE("power8nvl_v1.0"),
-    DEFINE_PNV_CORE_TYPE("power9_v2.0"),
+    DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"),
+    DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
+    DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
+    DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"),
 };
 
 DEFINE_TYPES(pnv_core_infos)
+
+/*
+ * POWER9 Quads
+ */
+
+#define P9X_EX_NCU_SPEC_BAR                     0x11010
+
+static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr,
+                                    unsigned int width)
+{
+    uint32_t offset = addr >> 3;
+    uint64_t val = -1;
+
+    switch (offset) {
+    case P9X_EX_NCU_SPEC_BAR:
+    case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
+        val = 0;
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__,
+                      offset);
+    }
+
+    return val;
+}
+
+static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val,
+                                 unsigned int width)
+{
+    uint32_t offset = addr >> 3;
+
+    switch (offset) {
+    case P9X_EX_NCU_SPEC_BAR:
+    case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__,
+                  offset);
+    }
+}
+
+static const MemoryRegionOps pnv_quad_xscom_ops = {
+    .read = pnv_quad_xscom_read,
+    .write = pnv_quad_xscom_write,
+    .valid.min_access_size = 8,
+    .valid.max_access_size = 8,
+    .impl.min_access_size = 8,
+    .impl.max_access_size = 8,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void pnv_quad_realize(DeviceState *dev, Error **errp)
+{
+    PnvQuad *eq = PNV_QUAD(dev);
+    char name[32];
+
+    snprintf(name, sizeof(name), "xscom-quad.%d", eq->id);
+    pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), &pnv_quad_xscom_ops,
+                          eq, name, PNV9_XSCOM_EQ_SIZE);
+}
+
+static Property pnv_quad_properties[] = {
+    DEFINE_PROP_UINT32("id", PnvQuad, id, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pnv_quad_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = pnv_quad_realize;
+    dc->props = pnv_quad_properties;
+}
+
+static const TypeInfo pnv_quad_info = {
+    .name          = TYPE_PNV_QUAD,
+    .parent        = TYPE_DEVICE,
+    .instance_size = sizeof(PnvQuad),
+    .class_init    = pnv_quad_class_init,
+};
+
+static void pnv_core_register_types(void)
+{
+    type_register_static(&pnv_quad_info);
+}
+
+type_init(pnv_core_register_types)
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index 172a915..641e204 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -39,6 +39,8 @@
 };
 
 /* OPB Master LS registers */
+#define OPB_MASTER_LS_ROUTE0    0x8
+#define OPB_MASTER_LS_ROUTE1    0xC
 #define OPB_MASTER_LS_IRQ_STAT  0x50
 #define   OPB_MASTER_IRQ_LPC            0x00000800
 #define OPB_MASTER_LS_IRQ_MASK  0x54
@@ -89,10 +91,11 @@
 #define LPC_FW_OPB_SIZE         0x10000000
 
 #define LPC_OPB_REGS_OPB_ADDR   0xc0010000
-#define LPC_OPB_REGS_OPB_SIZE   0x00002000
+#define LPC_OPB_REGS_OPB_SIZE   0x00000060
+#define LPC_OPB_REGS_OPBA_ADDR  0xc0011000
+#define LPC_OPB_REGS_OPBA_SIZE  0x00000008
 #define LPC_HC_REGS_OPB_ADDR    0xc0012000
-#define LPC_HC_REGS_OPB_SIZE    0x00001000
-
+#define LPC_HC_REGS_OPB_SIZE    0x00000100
 
 static int pnv_lpc_dt_xscom(PnvXScomInterface *dev, void *fdt, int xscom_offset)
 {
@@ -117,6 +120,100 @@
     return 0;
 }
 
+/* POWER9 only */
+int pnv_dt_lpc(PnvChip *chip, void *fdt, int root_offset)
+{
+    const char compat[] = "ibm,power9-lpcm-opb\0simple-bus";
+    const char lpc_compat[] = "ibm,power9-lpc\0ibm,lpc";
+    char *name;
+    int offset, lpcm_offset;
+    uint64_t lpcm_addr = PNV9_LPCM_BASE(chip);
+    uint32_t opb_ranges[8] = { 0,
+                               cpu_to_be32(lpcm_addr >> 32),
+                               cpu_to_be32((uint32_t)lpcm_addr),
+                               cpu_to_be32(PNV9_LPCM_SIZE / 2),
+                               cpu_to_be32(PNV9_LPCM_SIZE / 2),
+                               cpu_to_be32(lpcm_addr >> 32),
+                               cpu_to_be32(PNV9_LPCM_SIZE / 2),
+                               cpu_to_be32(PNV9_LPCM_SIZE / 2),
+    };
+    uint32_t opb_reg[4] = { cpu_to_be32(lpcm_addr >> 32),
+                            cpu_to_be32((uint32_t)lpcm_addr),
+                            cpu_to_be32(PNV9_LPCM_SIZE >> 32),
+                            cpu_to_be32((uint32_t)PNV9_LPCM_SIZE),
+    };
+    uint32_t reg[2];
+
+    /*
+     * OPB bus
+     */
+    name = g_strdup_printf("lpcm-opb@%"PRIx64, lpcm_addr);
+    lpcm_offset = fdt_add_subnode(fdt, root_offset, name);
+    _FDT(lpcm_offset);
+    g_free(name);
+
+    _FDT((fdt_setprop(fdt, lpcm_offset, "reg", opb_reg, sizeof(opb_reg))));
+    _FDT((fdt_setprop_cell(fdt, lpcm_offset, "#address-cells", 1)));
+    _FDT((fdt_setprop_cell(fdt, lpcm_offset, "#size-cells", 1)));
+    _FDT((fdt_setprop(fdt, lpcm_offset, "compatible", compat, sizeof(compat))));
+    _FDT((fdt_setprop_cell(fdt, lpcm_offset, "ibm,chip-id", chip->chip_id)));
+    _FDT((fdt_setprop(fdt, lpcm_offset, "ranges", opb_ranges,
+                      sizeof(opb_ranges))));
+
+    /*
+     * OPB Master registers
+     */
+    name = g_strdup_printf("opb-master@%x", LPC_OPB_REGS_OPB_ADDR);
+    offset = fdt_add_subnode(fdt, lpcm_offset, name);
+    _FDT(offset);
+    g_free(name);
+
+    reg[0] = cpu_to_be32(LPC_OPB_REGS_OPB_ADDR);
+    reg[1] = cpu_to_be32(LPC_OPB_REGS_OPB_SIZE);
+    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
+    _FDT((fdt_setprop_string(fdt, offset, "compatible",
+                             "ibm,power9-lpcm-opb-master")));
+
+    /*
+     * OPB arbitrer registers
+     */
+    name = g_strdup_printf("opb-arbitrer@%x", LPC_OPB_REGS_OPBA_ADDR);
+    offset = fdt_add_subnode(fdt, lpcm_offset, name);
+    _FDT(offset);
+    g_free(name);
+
+    reg[0] = cpu_to_be32(LPC_OPB_REGS_OPBA_ADDR);
+    reg[1] = cpu_to_be32(LPC_OPB_REGS_OPBA_SIZE);
+    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
+    _FDT((fdt_setprop_string(fdt, offset, "compatible",
+                             "ibm,power9-lpcm-opb-arbiter")));
+
+    /*
+     * LPC Host Controller registers
+     */
+    name = g_strdup_printf("lpc-controller@%x", LPC_HC_REGS_OPB_ADDR);
+    offset = fdt_add_subnode(fdt, lpcm_offset, name);
+    _FDT(offset);
+    g_free(name);
+
+    reg[0] = cpu_to_be32(LPC_HC_REGS_OPB_ADDR);
+    reg[1] = cpu_to_be32(LPC_HC_REGS_OPB_SIZE);
+    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
+    _FDT((fdt_setprop_string(fdt, offset, "compatible",
+                             "ibm,power9-lpc-controller")));
+
+    name = g_strdup_printf("lpc@0");
+    offset = fdt_add_subnode(fdt, lpcm_offset, name);
+    _FDT(offset);
+    g_free(name);
+    _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 2)));
+    _FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 1)));
+    _FDT((fdt_setprop(fdt, offset, "compatible", lpc_compat,
+                      sizeof(lpc_compat))));
+
+    return 0;
+}
+
 /*
  * These read/write handlers of the OPB address space should be common
  * with the P9 LPC Controller which uses direct MMIOs.
@@ -241,9 +338,78 @@
     .endianness = DEVICE_BIG_ENDIAN,
 };
 
+static uint64_t pnv_lpc_mmio_read(void *opaque, hwaddr addr, unsigned size)
+{
+    PnvLpcController *lpc = PNV_LPC(opaque);
+    uint64_t val = 0;
+    uint32_t opb_addr = addr & ECCB_CTL_ADDR_MASK;
+    MemTxResult result;
+
+    switch (size) {
+    case 4:
+        val = address_space_ldl(&lpc->opb_as, opb_addr, MEMTXATTRS_UNSPECIFIED,
+                                &result);
+        break;
+    case 1:
+        val = address_space_ldub(&lpc->opb_as, opb_addr, MEMTXATTRS_UNSPECIFIED,
+                                 &result);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "OPB read failed at @0x%"
+                      HWADDR_PRIx " invalid size %d\n", addr, size);
+        return 0;
+    }
+
+    if (result != MEMTX_OK) {
+        qemu_log_mask(LOG_GUEST_ERROR, "OPB read failed at @0x%"
+                      HWADDR_PRIx "\n", addr);
+    }
+
+    return val;
+}
+
+static void pnv_lpc_mmio_write(void *opaque, hwaddr addr,
+                                uint64_t val, unsigned size)
+{
+    PnvLpcController *lpc = PNV_LPC(opaque);
+    uint32_t opb_addr = addr & ECCB_CTL_ADDR_MASK;
+    MemTxResult result;
+
+    switch (size) {
+    case 4:
+        address_space_stl(&lpc->opb_as, opb_addr, val, MEMTXATTRS_UNSPECIFIED,
+                          &result);
+         break;
+    case 1:
+        address_space_stb(&lpc->opb_as, opb_addr, val, MEMTXATTRS_UNSPECIFIED,
+                          &result);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "OPB write failed at @0x%"
+                      HWADDR_PRIx " invalid size %d\n", addr, size);
+        return;
+    }
+
+    if (result != MEMTX_OK) {
+        qemu_log_mask(LOG_GUEST_ERROR, "OPB write failed at @0x%"
+                      HWADDR_PRIx "\n", addr);
+    }
+}
+
+static const MemoryRegionOps pnv_lpc_mmio_ops = {
+    .read = pnv_lpc_mmio_read,
+    .write = pnv_lpc_mmio_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
 static void pnv_lpc_eval_irqs(PnvLpcController *lpc)
 {
     bool lpc_to_opb_irq = false;
+    PnvLpcClass *plc = PNV_LPC_GET_CLASS(lpc);
 
     /* Update LPC controller to OPB line */
     if (lpc->lpc_hc_irqser_ctrl & LPC_HC_IRQSER_EN) {
@@ -266,7 +432,7 @@
     lpc->opb_irq_stat |= lpc->opb_irq_input & lpc->opb_irq_mask;
 
     /* Reflect the interrupt */
-    pnv_psi_irq_set(lpc->psi, PSIHB_IRQ_LPC_I2C, lpc->opb_irq_stat != 0);
+    pnv_psi_irq_set(lpc->psi, plc->psi_irq, lpc->opb_irq_stat != 0);
 }
 
 static uint64_t lpc_hc_read(void *opaque, hwaddr addr, unsigned size)
@@ -294,7 +460,7 @@
         val =  lpc->lpc_hc_error_addr;
         break;
     default:
-        qemu_log_mask(LOG_UNIMP, "LPC HC Unimplemented register: Ox%"
+        qemu_log_mask(LOG_UNIMP, "LPC HC Unimplemented register: 0x%"
                       HWADDR_PRIx "\n", addr);
     }
     return val;
@@ -332,7 +498,7 @@
     case LPC_HC_ERROR_ADDRESS:
         break;
     default:
-        qemu_log_mask(LOG_UNIMP, "LPC HC Unimplemented register: Ox%"
+        qemu_log_mask(LOG_UNIMP, "LPC HC Unimplemented register: 0x%"
                       HWADDR_PRIx "\n", addr);
     }
 }
@@ -357,6 +523,12 @@
     uint64_t val = 0xfffffffffffffffful;
 
     switch (addr) {
+    case OPB_MASTER_LS_ROUTE0: /* TODO */
+        val = lpc->opb_irq_route0;
+        break;
+    case OPB_MASTER_LS_ROUTE1: /* TODO */
+        val = lpc->opb_irq_route1;
+        break;
     case OPB_MASTER_LS_IRQ_STAT:
         val = lpc->opb_irq_stat;
         break;
@@ -370,7 +542,7 @@
         val = lpc->opb_irq_input;
         break;
     default:
-        qemu_log_mask(LOG_UNIMP, "OPB MASTER Unimplemented register: Ox%"
+        qemu_log_mask(LOG_UNIMP, "OPBM: read on unimplemented register: 0x%"
                       HWADDR_PRIx "\n", addr);
     }
 
@@ -383,6 +555,12 @@
     PnvLpcController *lpc = opaque;
 
     switch (addr) {
+    case OPB_MASTER_LS_ROUTE0: /* TODO */
+        lpc->opb_irq_route0 = val;
+        break;
+    case OPB_MASTER_LS_ROUTE1: /* TODO */
+        lpc->opb_irq_route1 = val;
+        break;
     case OPB_MASTER_LS_IRQ_STAT:
         lpc->opb_irq_stat &= ~val;
         pnv_lpc_eval_irqs(lpc);
@@ -399,8 +577,8 @@
         /* Read only */
         break;
     default:
-        qemu_log_mask(LOG_UNIMP, "OPB MASTER Unimplemented register: Ox%"
-                      HWADDR_PRIx "\n", addr);
+        qemu_log_mask(LOG_UNIMP, "OPBM: write on unimplemented register: 0x%"
+                      HWADDR_PRIx " val=0x%08"PRIx64"\n", addr, val);
     }
 }
 
@@ -418,11 +596,102 @@
     },
 };
 
+static void pnv_lpc_power8_realize(DeviceState *dev, Error **errp)
+{
+    PnvLpcController *lpc = PNV_LPC(dev);
+    PnvLpcClass *plc = PNV_LPC_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    plc->parent_realize(dev, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    /* P8 uses a XSCOM region for LPC registers */
+    pnv_xscom_region_init(&lpc->xscom_regs, OBJECT(lpc),
+                          &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
+                          PNV_XSCOM_LPC_SIZE);
+}
+
+static void pnv_lpc_power8_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
+    PnvLpcClass *plc = PNV_LPC_CLASS(klass);
+
+    dc->desc = "PowerNV LPC Controller POWER8";
+
+    xdc->dt_xscom = pnv_lpc_dt_xscom;
+
+    plc->psi_irq = PSIHB_IRQ_LPC_I2C;
+
+    device_class_set_parent_realize(dc, pnv_lpc_power8_realize,
+                                    &plc->parent_realize);
+}
+
+static const TypeInfo pnv_lpc_power8_info = {
+    .name          = TYPE_PNV8_LPC,
+    .parent        = TYPE_PNV_LPC,
+    .instance_size = sizeof(PnvLpcController),
+    .class_init    = pnv_lpc_power8_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PNV_XSCOM_INTERFACE },
+        { }
+    }
+};
+
+static void pnv_lpc_power9_realize(DeviceState *dev, Error **errp)
+{
+    PnvLpcController *lpc = PNV_LPC(dev);
+    PnvLpcClass *plc = PNV_LPC_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    plc->parent_realize(dev, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    /* P9 uses a MMIO region */
+    memory_region_init_io(&lpc->xscom_regs, OBJECT(lpc), &pnv_lpc_mmio_ops,
+                          lpc, "lpcm", PNV9_LPCM_SIZE);
+}
+
+static void pnv_lpc_power9_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PnvLpcClass *plc = PNV_LPC_CLASS(klass);
+
+    dc->desc = "PowerNV LPC Controller POWER9";
+
+    plc->psi_irq = PSIHB9_IRQ_LPCHC;
+
+    device_class_set_parent_realize(dc, pnv_lpc_power9_realize,
+                                    &plc->parent_realize);
+}
+
+static const TypeInfo pnv_lpc_power9_info = {
+    .name          = TYPE_PNV9_LPC,
+    .parent        = TYPE_PNV_LPC,
+    .instance_size = sizeof(PnvLpcController),
+    .class_init    = pnv_lpc_power9_class_init,
+};
+
 static void pnv_lpc_realize(DeviceState *dev, Error **errp)
 {
     PnvLpcController *lpc = PNV_LPC(dev);
     Object *obj;
-    Error *error = NULL;
+    Error *local_err = NULL;
+
+    obj = object_property_get_link(OBJECT(dev), "psi", &local_err);
+    if (!obj) {
+        error_propagate(errp, local_err);
+        error_prepend(errp, "required link 'psi' not found: ");
+        return;
+    }
+    /* The LPC controller needs PSI to generate interrupts  */
+    lpc->psi = PNV_PSI(obj);
 
     /* Reg inits */
     lpc->lpc_hc_fw_rd_acc_size = LPC_HC_FW_RD_4B;
@@ -462,46 +731,29 @@
                           "lpc-hc", LPC_HC_REGS_OPB_SIZE);
     memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR,
                                 &lpc->lpc_hc_regs);
-
-    /* XScom region for LPC registers */
-    pnv_xscom_region_init(&lpc->xscom_regs, OBJECT(dev),
-                          &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
-                          PNV_XSCOM_LPC_SIZE);
-
-    /* get PSI object from chip */
-    obj = object_property_get_link(OBJECT(dev), "psi", &error);
-    if (!obj) {
-        error_setg(errp, "%s: required link 'psi' not found: %s",
-                   __func__, error_get_pretty(error));
-        return;
-    }
-    lpc->psi = PNV_PSI(obj);
 }
 
 static void pnv_lpc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
-
-    xdc->dt_xscom = pnv_lpc_dt_xscom;
 
     dc->realize = pnv_lpc_realize;
+    dc->desc = "PowerNV LPC Controller";
 }
 
 static const TypeInfo pnv_lpc_info = {
     .name          = TYPE_PNV_LPC,
     .parent        = TYPE_DEVICE,
-    .instance_size = sizeof(PnvLpcController),
     .class_init    = pnv_lpc_class_init,
-    .interfaces = (InterfaceInfo[]) {
-        { TYPE_PNV_XSCOM_INTERFACE },
-        { }
-    }
+    .class_size    = sizeof(PnvLpcClass),
+    .abstract      = true,
 };
 
 static void pnv_lpc_register_types(void)
 {
     type_register_static(&pnv_lpc_info);
+    type_register_static(&pnv_lpc_power8_info);
+    type_register_static(&pnv_lpc_power9_info);
 }
 
 type_init(pnv_lpc_register_types)
diff --git a/hw/ppc/pnv_occ.c b/hw/ppc/pnv_occ.c
index 04880f2..fdd9296 100644
--- a/hw/ppc/pnv_occ.c
+++ b/hw/ppc/pnv_occ.c
@@ -34,15 +34,17 @@
 static void pnv_occ_set_misc(PnvOCC *occ, uint64_t val)
 {
     bool irq_state;
+    PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ);
 
     val &= 0xffff000000000000ull;
 
     occ->occmisc = val;
     irq_state = !!(val >> 63);
-    pnv_psi_irq_set(occ->psi, PSIHB_IRQ_OCC, irq_state);
+    pnv_psi_irq_set(occ->psi, poc->psi_irq, irq_state);
 }
 
-static uint64_t pnv_occ_xscom_read(void *opaque, hwaddr addr, unsigned size)
+static uint64_t pnv_occ_power8_xscom_read(void *opaque, hwaddr addr,
+                                          unsigned size)
 {
     PnvOCC *occ = PNV_OCC(opaque);
     uint32_t offset = addr >> 3;
@@ -54,13 +56,13 @@
         break;
     default:
         qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
-                      HWADDR_PRIx "\n", addr);
+                      HWADDR_PRIx "\n", addr >> 3);
     }
     return val;
 }
 
-static void pnv_occ_xscom_write(void *opaque, hwaddr addr,
-                                uint64_t val, unsigned size)
+static void pnv_occ_power8_xscom_write(void *opaque, hwaddr addr,
+                                       uint64_t val, unsigned size)
 {
     PnvOCC *occ = PNV_OCC(opaque);
     uint32_t offset = addr >> 3;
@@ -77,13 +79,13 @@
         break;
     default:
         qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
-                      HWADDR_PRIx "\n", addr);
+                      HWADDR_PRIx "\n", addr >> 3);
     }
 }
 
-static const MemoryRegionOps pnv_occ_xscom_ops = {
-    .read = pnv_occ_xscom_read,
-    .write = pnv_occ_xscom_write,
+static const MemoryRegionOps pnv_occ_power8_xscom_ops = {
+    .read = pnv_occ_power8_xscom_read,
+    .write = pnv_occ_power8_xscom_write,
     .valid.min_access_size = 8,
     .valid.max_access_size = 8,
     .impl.min_access_size = 8,
@@ -91,27 +93,113 @@
     .endianness = DEVICE_BIG_ENDIAN,
 };
 
+static void pnv_occ_power8_class_init(ObjectClass *klass, void *data)
+{
+    PnvOCCClass *poc = PNV_OCC_CLASS(klass);
+
+    poc->xscom_size = PNV_XSCOM_OCC_SIZE;
+    poc->xscom_ops = &pnv_occ_power8_xscom_ops;
+    poc->psi_irq = PSIHB_IRQ_OCC;
+}
+
+static const TypeInfo pnv_occ_power8_type_info = {
+    .name          = TYPE_PNV8_OCC,
+    .parent        = TYPE_PNV_OCC,
+    .instance_size = sizeof(PnvOCC),
+    .class_init    = pnv_occ_power8_class_init,
+};
+
+#define P9_OCB_OCI_OCCMISC              0x6080
+#define P9_OCB_OCI_OCCMISC_CLEAR        0x6081
+#define P9_OCB_OCI_OCCMISC_OR           0x6082
+
+
+static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr,
+                                          unsigned size)
+{
+    PnvOCC *occ = PNV_OCC(opaque);
+    uint32_t offset = addr >> 3;
+    uint64_t val = 0;
+
+    switch (offset) {
+    case P9_OCB_OCI_OCCMISC:
+        val = occ->occmisc;
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
+                      HWADDR_PRIx "\n", addr >> 3);
+    }
+    return val;
+}
+
+static void pnv_occ_power9_xscom_write(void *opaque, hwaddr addr,
+                                       uint64_t val, unsigned size)
+{
+    PnvOCC *occ = PNV_OCC(opaque);
+    uint32_t offset = addr >> 3;
+
+    switch (offset) {
+    case P9_OCB_OCI_OCCMISC_CLEAR:
+        pnv_occ_set_misc(occ, 0);
+        break;
+    case P9_OCB_OCI_OCCMISC_OR:
+        pnv_occ_set_misc(occ, occ->occmisc | val);
+        break;
+    case P9_OCB_OCI_OCCMISC:
+        pnv_occ_set_misc(occ, val);
+       break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
+                      HWADDR_PRIx "\n", addr >> 3);
+    }
+}
+
+static const MemoryRegionOps pnv_occ_power9_xscom_ops = {
+    .read = pnv_occ_power9_xscom_read,
+    .write = pnv_occ_power9_xscom_write,
+    .valid.min_access_size = 8,
+    .valid.max_access_size = 8,
+    .impl.min_access_size = 8,
+    .impl.max_access_size = 8,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void pnv_occ_power9_class_init(ObjectClass *klass, void *data)
+{
+    PnvOCCClass *poc = PNV_OCC_CLASS(klass);
+
+    poc->xscom_size = PNV9_XSCOM_OCC_SIZE;
+    poc->xscom_ops = &pnv_occ_power9_xscom_ops;
+    poc->psi_irq = PSIHB9_IRQ_OCC;
+}
+
+static const TypeInfo pnv_occ_power9_type_info = {
+    .name          = TYPE_PNV9_OCC,
+    .parent        = TYPE_PNV_OCC,
+    .instance_size = sizeof(PnvOCC),
+    .class_init    = pnv_occ_power9_class_init,
+};
 
 static void pnv_occ_realize(DeviceState *dev, Error **errp)
 {
     PnvOCC *occ = PNV_OCC(dev);
+    PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ);
     Object *obj;
-    Error *error = NULL;
+    Error *local_err = NULL;
 
     occ->occmisc = 0;
 
-    /* get PSI object from chip */
-    obj = object_property_get_link(OBJECT(dev), "psi", &error);
+    obj = object_property_get_link(OBJECT(dev), "psi", &local_err);
     if (!obj) {
-        error_setg(errp, "%s: required link 'psi' not found: %s",
-                   __func__, error_get_pretty(error));
+        error_propagate(errp, local_err);
+        error_prepend(errp, "required link 'psi' not found: ");
         return;
     }
     occ->psi = PNV_PSI(obj);
 
     /* XScom region for OCC registers */
-    pnv_xscom_region_init(&occ->xscom_regs, OBJECT(dev), &pnv_occ_xscom_ops,
-                  occ, "xscom-occ", PNV_XSCOM_OCC_SIZE);
+    pnv_xscom_region_init(&occ->xscom_regs, OBJECT(dev), poc->xscom_ops,
+                          occ, "xscom-occ", poc->xscom_size);
 }
 
 static void pnv_occ_class_init(ObjectClass *klass, void *data)
@@ -119,6 +207,7 @@
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = pnv_occ_realize;
+    dc->desc = "PowerNV OCC Controller";
 }
 
 static const TypeInfo pnv_occ_type_info = {
@@ -126,11 +215,15 @@
     .parent        = TYPE_DEVICE,
     .instance_size = sizeof(PnvOCC),
     .class_init    = pnv_occ_class_init,
+    .class_size    = sizeof(PnvOCCClass),
+    .abstract      = true,
 };
 
 static void pnv_occ_register_types(void)
 {
     type_register_static(&pnv_occ_type_info);
+    type_register_static(&pnv_occ_power8_type_info);
+    type_register_static(&pnv_occ_power9_type_info);
 }
 
-type_init(pnv_occ_register_types)
+type_init(pnv_occ_register_types);
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 44bc0cb..5a923e4 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -22,6 +22,7 @@
 #include "target/ppc/cpu.h"
 #include "qemu/log.h"
 #include "qapi/error.h"
+#include "monitor/monitor.h"
 
 #include "exec/address-spaces.h"
 
@@ -114,12 +115,18 @@
 #define PSIHB_BAR_MASK                  0x0003fffffff00000ull
 #define PSIHB_FSPBAR_MASK               0x0003ffff00000000ull
 
+#define PSIHB9_BAR_MASK                 0x00fffffffff00000ull
+#define PSIHB9_FSPBAR_MASK              0x00ffffff00000000ull
+
+#define PSIHB_REG(addr) (((addr) >> 3) + PSIHB_XSCOM_BAR)
+
 static void pnv_psi_set_bar(PnvPsi *psi, uint64_t bar)
 {
+    PnvPsiClass *ppc = PNV_PSI_GET_CLASS(psi);
     MemoryRegion *sysmem = get_system_memory();
     uint64_t old = psi->regs[PSIHB_XSCOM_BAR];
 
-    psi->regs[PSIHB_XSCOM_BAR] = bar & (PSIHB_BAR_MASK | PSIHB_BAR_EN);
+    psi->regs[PSIHB_XSCOM_BAR] = bar & (ppc->bar_mask | PSIHB_BAR_EN);
 
     /* Update MR, always remove it first */
     if (old & PSIHB_BAR_EN) {
@@ -128,7 +135,7 @@
 
     /* Then add it back if needed */
     if (bar & PSIHB_BAR_EN) {
-        uint64_t addr = bar & PSIHB_BAR_MASK;
+        uint64_t addr = bar & ppc->bar_mask;
         memory_region_add_subregion(sysmem, addr, &psi->regs_mr);
     }
 }
@@ -152,7 +159,7 @@
 
 static void pnv_psi_set_irsn(PnvPsi *psi, uint64_t val)
 {
-    ICSState *ics = &psi->ics;
+    ICSState *ics = &PNV8_PSI(psi)->ics;
 
     /* In this model we ignore the up/down enable bits for now
      * as SW doesn't use them (other than setting them at boot).
@@ -205,7 +212,12 @@
     [PSIHB_IRQ_EXTERNAL]  = PSIHB_IRQ_STAT_EXT,
 };
 
-void pnv_psi_irq_set(PnvPsi *psi, PnvPsiIrq irq, bool state)
+void pnv_psi_irq_set(PnvPsi *psi, int irq, bool state)
+{
+    PNV_PSI_GET_CLASS(psi)->irq_set(psi, irq, state);
+}
+
+static void pnv_psi_power8_irq_set(PnvPsi *psi, int irq, bool state)
 {
     uint32_t xivr_reg;
     uint32_t stat_reg;
@@ -260,7 +272,7 @@
 
 static void pnv_psi_set_xivr(PnvPsi *psi, uint32_t reg, uint64_t val)
 {
-    ICSState *ics = &psi->ics;
+    ICSState *ics = &PNV8_PSI(psi)->ics;
     uint16_t server;
     uint8_t prio;
     uint8_t src;
@@ -323,7 +335,7 @@
         val = psi->regs[offset];
         break;
     default:
-        qemu_log_mask(LOG_UNIMP, "PSI: read at Ox%" PRIx32 "\n", offset);
+        qemu_log_mask(LOG_UNIMP, "PSI: read at 0x%" PRIx32 "\n", offset);
     }
     return val;
 }
@@ -382,7 +394,7 @@
         pnv_psi_set_irsn(psi, val);
         break;
     default:
-        qemu_log_mask(LOG_UNIMP, "PSI: write at Ox%" PRIx32 "\n", offset);
+        qemu_log_mask(LOG_UNIMP, "PSI: write at 0x%" PRIx32 "\n", offset);
     }
 }
 
@@ -392,13 +404,13 @@
  */
 static uint64_t pnv_psi_mmio_read(void *opaque, hwaddr addr, unsigned size)
 {
-    return pnv_psi_reg_read(opaque, (addr >> 3) + PSIHB_XSCOM_BAR, true);
+    return pnv_psi_reg_read(opaque, PSIHB_REG(addr), true);
 }
 
 static void pnv_psi_mmio_write(void *opaque, hwaddr addr,
                               uint64_t val, unsigned size)
 {
-    pnv_psi_reg_write(opaque, (addr >> 3) + PSIHB_XSCOM_BAR, val, true);
+    pnv_psi_reg_write(opaque, PSIHB_REG(addr), val, true);
 }
 
 static const MemoryRegionOps psi_mmio_ops = {
@@ -440,11 +452,20 @@
     }
 };
 
-static void pnv_psi_init(Object *obj)
+static void pnv_psi_reset(void *dev)
 {
-    PnvPsi *psi = PNV_PSI(obj);
+    PnvPsi *psi = PNV_PSI(dev);
 
-    object_initialize_child(obj, "ics-psi",  &psi->ics, sizeof(psi->ics),
+    memset(psi->regs, 0x0, sizeof(psi->regs));
+
+    psi->regs[PSIHB_XSCOM_BAR] = psi->bar | PSIHB_BAR_EN;
+}
+
+static void pnv_psi_power8_instance_init(Object *obj)
+{
+    Pnv8Psi *psi8 = PNV8_PSI(obj);
+
+    object_initialize_child(obj, "ics-psi",  &psi8->ics, sizeof(psi8->ics),
                             TYPE_ICS_SIMPLE, &error_abort, NULL);
 }
 
@@ -457,10 +478,10 @@
     PSIHB_XSCOM_XIVR_EXT,
 };
 
-static void pnv_psi_realize(DeviceState *dev, Error **errp)
+static void pnv_psi_power8_realize(DeviceState *dev, Error **errp)
 {
     PnvPsi *psi = PNV_PSI(dev);
-    ICSState *ics = &psi->ics;
+    ICSState *ics = &PNV8_PSI(psi)->ics;
     Object *obj;
     Error *err = NULL;
     unsigned int i;
@@ -509,30 +530,38 @@
         psi->regs[xivr] = PSIHB_XIVR_PRIO_MSK |
             ((uint64_t) i << PSIHB_XIVR_SRC_SH);
     }
+
+    qemu_register_reset(pnv_psi_reset, dev);
 }
 
+static const char compat_p8[] = "ibm,power8-psihb-x\0ibm,psihb-x";
+static const char compat_p9[] = "ibm,power9-psihb-x\0ibm,psihb-x";
+
 static int pnv_psi_dt_xscom(PnvXScomInterface *dev, void *fdt, int xscom_offset)
 {
-    const char compat[] = "ibm,power8-psihb-x\0ibm,psihb-x";
+    PnvPsiClass *ppc = PNV_PSI_GET_CLASS(dev);
     char *name;
     int offset;
-    uint32_t lpc_pcba = PNV_XSCOM_PSIHB_BASE;
     uint32_t reg[] = {
-        cpu_to_be32(lpc_pcba),
-        cpu_to_be32(PNV_XSCOM_PSIHB_SIZE)
+        cpu_to_be32(ppc->xscom_pcba),
+        cpu_to_be32(ppc->xscom_size)
     };
 
-    name = g_strdup_printf("psihb@%x", lpc_pcba);
+    name = g_strdup_printf("psihb@%x", ppc->xscom_pcba);
     offset = fdt_add_subnode(fdt, xscom_offset, name);
     _FDT(offset);
     g_free(name);
 
-    _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
-
-    _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 2)));
-    _FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 1)));
-    _FDT((fdt_setprop(fdt, offset, "compatible", compat,
-                      sizeof(compat))));
+    _FDT(fdt_setprop(fdt, offset, "reg", reg, sizeof(reg)));
+    _FDT(fdt_setprop_cell(fdt, offset, "#address-cells", 2));
+    _FDT(fdt_setprop_cell(fdt, offset, "#size-cells", 1));
+    if (ppc->chip_type == PNV_CHIP_POWER9) {
+        _FDT(fdt_setprop(fdt, offset, "compatible", compat_p9,
+                         sizeof(compat_p9)));
+    } else {
+        _FDT(fdt_setprop(fdt, offset, "compatible", compat_p8,
+                         sizeof(compat_p8)));
+    }
     return 0;
 }
 
@@ -542,6 +571,331 @@
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void pnv_psi_power8_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PnvPsiClass *ppc = PNV_PSI_CLASS(klass);
+
+    dc->desc    = "PowerNV PSI Controller POWER8";
+    dc->realize = pnv_psi_power8_realize;
+
+    ppc->chip_type =  PNV_CHIP_POWER8;
+    ppc->xscom_pcba = PNV_XSCOM_PSIHB_BASE;
+    ppc->xscom_size = PNV_XSCOM_PSIHB_SIZE;
+    ppc->bar_mask   = PSIHB_BAR_MASK;
+    ppc->irq_set    = pnv_psi_power8_irq_set;
+}
+
+static const TypeInfo pnv_psi_power8_info = {
+    .name          = TYPE_PNV8_PSI,
+    .parent        = TYPE_PNV_PSI,
+    .instance_size = sizeof(Pnv8Psi),
+    .instance_init = pnv_psi_power8_instance_init,
+    .class_init    = pnv_psi_power8_class_init,
+};
+
+
+/* Common registers */
+
+#define PSIHB9_CR                       0x20
+#define PSIHB9_SEMR                     0x28
+
+/* P9 registers */
+
+#define PSIHB9_INTERRUPT_CONTROL        0x58
+#define   PSIHB9_IRQ_METHOD             PPC_BIT(0)
+#define   PSIHB9_IRQ_RESET              PPC_BIT(1)
+#define PSIHB9_ESB_CI_BASE              0x60
+#define   PSIHB9_ESB_CI_VALID           1
+#define PSIHB9_ESB_NOTIF_ADDR           0x68
+#define   PSIHB9_ESB_NOTIF_VALID        1
+#define PSIHB9_IVT_OFFSET               0x70
+#define   PSIHB9_IVT_OFF_SHIFT          32
+
+#define PSIHB9_IRQ_LEVEL                0x78 /* assertion */
+#define   PSIHB9_IRQ_LEVEL_PSI          PPC_BIT(0)
+#define   PSIHB9_IRQ_LEVEL_OCC          PPC_BIT(1)
+#define   PSIHB9_IRQ_LEVEL_FSI          PPC_BIT(2)
+#define   PSIHB9_IRQ_LEVEL_LPCHC        PPC_BIT(3)
+#define   PSIHB9_IRQ_LEVEL_LOCAL_ERR    PPC_BIT(4)
+#define   PSIHB9_IRQ_LEVEL_GLOBAL_ERR   PPC_BIT(5)
+#define   PSIHB9_IRQ_LEVEL_TPM          PPC_BIT(6)
+#define   PSIHB9_IRQ_LEVEL_LPC_SIRQ1    PPC_BIT(7)
+#define   PSIHB9_IRQ_LEVEL_LPC_SIRQ2    PPC_BIT(8)
+#define   PSIHB9_IRQ_LEVEL_LPC_SIRQ3    PPC_BIT(9)
+#define   PSIHB9_IRQ_LEVEL_LPC_SIRQ4    PPC_BIT(10)
+#define   PSIHB9_IRQ_LEVEL_SBE_I2C      PPC_BIT(11)
+#define   PSIHB9_IRQ_LEVEL_DIO          PPC_BIT(12)
+#define   PSIHB9_IRQ_LEVEL_PSU          PPC_BIT(13)
+#define   PSIHB9_IRQ_LEVEL_I2C_C        PPC_BIT(14)
+#define   PSIHB9_IRQ_LEVEL_I2C_D        PPC_BIT(15)
+#define   PSIHB9_IRQ_LEVEL_I2C_E        PPC_BIT(16)
+#define   PSIHB9_IRQ_LEVEL_SBE          PPC_BIT(19)
+
+#define PSIHB9_IRQ_STAT                 0x80 /* P bit */
+#define   PSIHB9_IRQ_STAT_PSI           PPC_BIT(0)
+#define   PSIHB9_IRQ_STAT_OCC           PPC_BIT(1)
+#define   PSIHB9_IRQ_STAT_FSI           PPC_BIT(2)
+#define   PSIHB9_IRQ_STAT_LPCHC         PPC_BIT(3)
+#define   PSIHB9_IRQ_STAT_LOCAL_ERR     PPC_BIT(4)
+#define   PSIHB9_IRQ_STAT_GLOBAL_ERR    PPC_BIT(5)
+#define   PSIHB9_IRQ_STAT_TPM           PPC_BIT(6)
+#define   PSIHB9_IRQ_STAT_LPC_SIRQ1     PPC_BIT(7)
+#define   PSIHB9_IRQ_STAT_LPC_SIRQ2     PPC_BIT(8)
+#define   PSIHB9_IRQ_STAT_LPC_SIRQ3     PPC_BIT(9)
+#define   PSIHB9_IRQ_STAT_LPC_SIRQ4     PPC_BIT(10)
+#define   PSIHB9_IRQ_STAT_SBE_I2C       PPC_BIT(11)
+#define   PSIHB9_IRQ_STAT_DIO           PPC_BIT(12)
+#define   PSIHB9_IRQ_STAT_PSU           PPC_BIT(13)
+
+static void pnv_psi_notify(XiveNotifier *xf, uint32_t srcno)
+{
+    PnvPsi *psi = PNV_PSI(xf);
+    uint64_t notif_port = psi->regs[PSIHB_REG(PSIHB9_ESB_NOTIF_ADDR)];
+    bool valid = notif_port & PSIHB9_ESB_NOTIF_VALID;
+    uint64_t notify_addr = notif_port & ~PSIHB9_ESB_NOTIF_VALID;
+
+    uint32_t offset =
+        (psi->regs[PSIHB_REG(PSIHB9_IVT_OFFSET)] >> PSIHB9_IVT_OFF_SHIFT);
+    uint64_t lisn = cpu_to_be64(offset + srcno);
+
+    if (valid) {
+        cpu_physical_memory_write(notify_addr, &lisn, sizeof(lisn));
+    }
+}
+
+static uint64_t pnv_psi_p9_mmio_read(void *opaque, hwaddr addr, unsigned size)
+{
+    PnvPsi *psi = PNV_PSI(opaque);
+    uint32_t reg = PSIHB_REG(addr);
+    uint64_t val = -1;
+
+    switch (addr) {
+    case PSIHB9_CR:
+    case PSIHB9_SEMR:
+        /* FSP stuff */
+    case PSIHB9_INTERRUPT_CONTROL:
+    case PSIHB9_ESB_CI_BASE:
+    case PSIHB9_ESB_NOTIF_ADDR:
+    case PSIHB9_IVT_OFFSET:
+        val = psi->regs[reg];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "PSI: read at 0x%" PRIx64 "\n", addr);
+    }
+
+    return val;
+}
+
+static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
+                                  uint64_t val, unsigned size)
+{
+    PnvPsi *psi = PNV_PSI(opaque);
+    Pnv9Psi *psi9 = PNV9_PSI(psi);
+    uint32_t reg = PSIHB_REG(addr);
+    MemoryRegion *sysmem = get_system_memory();
+
+    switch (addr) {
+    case PSIHB9_CR:
+    case PSIHB9_SEMR:
+        /* FSP stuff */
+        break;
+    case PSIHB9_INTERRUPT_CONTROL:
+        if (val & PSIHB9_IRQ_RESET) {
+            device_reset(DEVICE(&psi9->source));
+        }
+        psi->regs[reg] = val;
+        break;
+
+    case PSIHB9_ESB_CI_BASE:
+        if (!(val & PSIHB9_ESB_CI_VALID)) {
+            if (psi->regs[reg] & PSIHB9_ESB_CI_VALID) {
+                memory_region_del_subregion(sysmem, &psi9->source.esb_mmio);
+            }
+        } else {
+            if (!(psi->regs[reg] & PSIHB9_ESB_CI_VALID)) {
+                memory_region_add_subregion(sysmem,
+                                        val & ~PSIHB9_ESB_CI_VALID,
+                                        &psi9->source.esb_mmio);
+            }
+        }
+        psi->regs[reg] = val;
+        break;
+
+    case PSIHB9_ESB_NOTIF_ADDR:
+        psi->regs[reg] = val;
+        break;
+    case PSIHB9_IVT_OFFSET:
+        psi->regs[reg] = val;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "PSI: write at 0x%" PRIx64 "\n", addr);
+    }
+}
+
+static const MemoryRegionOps pnv_psi_p9_mmio_ops = {
+    .read = pnv_psi_p9_mmio_read,
+    .write = pnv_psi_p9_mmio_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+};
+
+static uint64_t pnv_psi_p9_xscom_read(void *opaque, hwaddr addr, unsigned size)
+{
+    /* No read are expected */
+    qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom read at 0x%" PRIx64 "\n", addr);
+    return -1;
+}
+
+static void pnv_psi_p9_xscom_write(void *opaque, hwaddr addr,
+                                uint64_t val, unsigned size)
+{
+    PnvPsi *psi = PNV_PSI(opaque);
+
+    /* XSCOM is only used to set the PSIHB MMIO region */
+    switch (addr >> 3) {
+    case PSIHB_XSCOM_BAR:
+        pnv_psi_set_bar(psi, val);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom write at 0x%" PRIx64 "\n",
+                      addr);
+    }
+}
+
+static const MemoryRegionOps pnv_psi_p9_xscom_ops = {
+    .read = pnv_psi_p9_xscom_read,
+    .write = pnv_psi_p9_xscom_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 8,
+        .max_access_size = 8,
+    }
+};
+
+static void pnv_psi_power9_irq_set(PnvPsi *psi, int irq, bool state)
+{
+    uint32_t irq_method = psi->regs[PSIHB_REG(PSIHB9_INTERRUPT_CONTROL)];
+
+    if (irq > PSIHB9_NUM_IRQS) {
+        qemu_log_mask(LOG_GUEST_ERROR, "PSI: Unsupported irq %d\n", irq);
+        return;
+    }
+
+    if (irq_method & PSIHB9_IRQ_METHOD) {
+        qemu_log_mask(LOG_GUEST_ERROR, "PSI: LSI IRQ method no supported\n");
+        return;
+    }
+
+    /* Update LSI levels */
+    if (state) {
+        psi->regs[PSIHB_REG(PSIHB9_IRQ_LEVEL)] |= PPC_BIT(irq);
+    } else {
+        psi->regs[PSIHB_REG(PSIHB9_IRQ_LEVEL)] &= ~PPC_BIT(irq);
+    }
+
+    qemu_set_irq(psi->qirqs[irq], state);
+}
+
+static void pnv_psi_power9_reset(void *dev)
+{
+    Pnv9Psi *psi = PNV9_PSI(dev);
+
+    pnv_psi_reset(dev);
+
+    if (memory_region_is_mapped(&psi->source.esb_mmio)) {
+        memory_region_del_subregion(get_system_memory(), &psi->source.esb_mmio);
+    }
+}
+
+static void pnv_psi_power9_instance_init(Object *obj)
+{
+    Pnv9Psi *psi = PNV9_PSI(obj);
+
+    object_initialize_child(obj, "source", &psi->source, sizeof(psi->source),
+                            TYPE_XIVE_SOURCE, &error_abort, NULL);
+}
+
+static void pnv_psi_power9_realize(DeviceState *dev, Error **errp)
+{
+    PnvPsi *psi = PNV_PSI(dev);
+    XiveSource *xsrc = &PNV9_PSI(psi)->source;
+    Error *local_err = NULL;
+    int i;
+
+    /* This is the only device with 4k ESB pages */
+    object_property_set_int(OBJECT(xsrc), XIVE_ESB_4K, "shift",
+                            &error_fatal);
+    object_property_set_int(OBJECT(xsrc), PSIHB9_NUM_IRQS, "nr-irqs",
+                            &error_fatal);
+    object_property_add_const_link(OBJECT(xsrc), "xive", OBJECT(psi),
+                                   &error_fatal);
+    object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    for (i = 0; i < xsrc->nr_irqs; i++) {
+        xive_source_irq_set_lsi(xsrc, i);
+    }
+
+    psi->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs);
+
+    /* XSCOM region for PSI registers */
+    pnv_xscom_region_init(&psi->xscom_regs, OBJECT(dev), &pnv_psi_p9_xscom_ops,
+                psi, "xscom-psi", PNV9_XSCOM_PSIHB_SIZE);
+
+    /* MMIO region for PSI registers */
+    memory_region_init_io(&psi->regs_mr, OBJECT(dev), &pnv_psi_p9_mmio_ops, psi,
+                          "psihb", PNV9_PSIHB_SIZE);
+
+    pnv_psi_set_bar(psi, psi->bar | PSIHB_BAR_EN);
+
+    qemu_register_reset(pnv_psi_power9_reset, dev);
+}
+
+static void pnv_psi_power9_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PnvPsiClass *ppc = PNV_PSI_CLASS(klass);
+    XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass);
+
+    dc->desc    = "PowerNV PSI Controller POWER9";
+    dc->realize = pnv_psi_power9_realize;
+
+    ppc->chip_type  = PNV_CHIP_POWER9;
+    ppc->xscom_pcba = PNV9_XSCOM_PSIHB_BASE;
+    ppc->xscom_size = PNV9_XSCOM_PSIHB_SIZE;
+    ppc->bar_mask   = PSIHB9_BAR_MASK;
+    ppc->irq_set    = pnv_psi_power9_irq_set;
+
+    xfc->notify      = pnv_psi_notify;
+}
+
+static const TypeInfo pnv_psi_power9_info = {
+    .name          = TYPE_PNV9_PSI,
+    .parent        = TYPE_PNV_PSI,
+    .instance_size = sizeof(Pnv9Psi),
+    .instance_init = pnv_psi_power9_instance_init,
+    .class_init    = pnv_psi_power9_class_init,
+    .interfaces = (InterfaceInfo[]) {
+            { TYPE_XIVE_NOTIFIER },
+            { },
+    },
+};
+
 static void pnv_psi_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -549,7 +903,7 @@
 
     xdc->dt_xscom = pnv_psi_dt_xscom;
 
-    dc->realize = pnv_psi_realize;
+    dc->desc = "PowerNV PSI Controller";
     dc->props = pnv_psi_properties;
 }
 
@@ -557,8 +911,9 @@
     .name          = TYPE_PNV_PSI,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PnvPsi),
-    .instance_init = pnv_psi_init,
     .class_init    = pnv_psi_class_init,
+    .class_size    = sizeof(PnvPsiClass),
+    .abstract      = true,
     .interfaces    = (InterfaceInfo[]) {
         { TYPE_PNV_XSCOM_INTERFACE },
         { }
@@ -568,6 +923,20 @@
 static void pnv_psi_register_types(void)
 {
     type_register_static(&pnv_psi_info);
+    type_register_static(&pnv_psi_power8_info);
+    type_register_static(&pnv_psi_power9_info);
 }
 
-type_init(pnv_psi_register_types)
+type_init(pnv_psi_register_types);
+
+void pnv_psi_pic_print_info(Pnv9Psi *psi9, Monitor *mon)
+{
+    PnvPsi *psi = PNV_PSI(psi9);
+
+    uint32_t offset =
+        (psi->regs[PSIHB_REG(PSIHB9_IVT_OFFSET)] >> PSIHB9_IVT_OFF_SHIFT);
+
+    monitor_printf(mon, "PSIHB Source %08x .. %08x\n",
+                  offset, offset + psi9->source.nr_irqs - 1);
+    xive_source_pic_print_info(&psi9->source, offset, mon);
+}
diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c
index 46fae41..c285ef5 100644
--- a/hw/ppc/pnv_xscom.c
+++ b/hw/ppc/pnv_xscom.c
@@ -64,11 +64,21 @@
     switch (pcba) {
     case 0xf000f:
         return PNV_CHIP_GET_CLASS(chip)->chip_cfam_id;
+    case 0x18002:       /* ECID2 */
+        return 0;
+
     case 0x1010c00:     /* PIBAM FIR */
     case 0x1010c03:     /* PIBAM FIR MASK */
-    case 0x2020007:     /* ADU stuff */
-    case 0x2020009:     /* ADU stuff */
-    case 0x202000f:     /* ADU stuff */
+
+        /* P9 xscom reset */
+    case 0x0090018:     /* Receive status reg */
+    case 0x0090012:     /* log register */
+    case 0x0090013:     /* error register */
+
+        /* P8 xscom reset */
+    case 0x2020007:     /* ADU stuff, log register */
+    case 0x2020009:     /* ADU stuff, error register */
+    case 0x202000f:     /* ADU stuff, receive status register*/
         return 0;
     case 0x2013f00:     /* PBA stuff */
     case 0x2013f01:     /* PBA stuff */
@@ -100,9 +110,20 @@
     case 0x1010c03:     /* PIBAM FIR MASK */
     case 0x1010c04:     /* PIBAM FIR MASK */
     case 0x1010c05:     /* PIBAM FIR MASK */
-    case 0x2020007:     /* ADU stuff */
-    case 0x2020009:     /* ADU stuff */
-    case 0x202000f:     /* ADU stuff */
+        /* P9 xscom reset */
+    case 0x0090018:     /* Receive status reg */
+    case 0x0090012:     /* log register */
+    case 0x0090013:     /* error register */
+
+        /* P8 xscom reset */
+    case 0x2020007:     /* ADU stuff, log register */
+    case 0x2020009:     /* ADU stuff, error register */
+    case 0x202000f:     /* ADU stuff, receive status register*/
+
+    case 0x2013028:     /* CAPP stuff */
+    case 0x201302a:     /* CAPP stuff */
+    case 0x2013801:     /* CAPP stuff */
+    case 0x2013802:     /* CAPP stuff */
         return true;
     default:
         return false;
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index d1e3d4c..49d5746 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -744,11 +744,10 @@
     return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
 }
 
-static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+static inline int64_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
 {
     ppc_tb_t *tb_env = env->tb_env;
-    uint32_t decr;
-    int64_t diff;
+    int64_t decr, diff;
 
     diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
     if (diff >= 0) {
@@ -758,27 +757,49 @@
     }  else {
         decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
     }
-    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
+    LOG_TB("%s: %016" PRIx64 "\n", __func__, decr);
 
     return decr;
 }
 
-uint32_t cpu_ppc_load_decr (CPUPPCState *env)
+target_ulong cpu_ppc_load_decr(CPUPPCState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
+    uint64_t decr;
 
     if (kvm_enabled()) {
         return env->spr[SPR_DECR];
     }
 
-    return _cpu_ppc_load_decr(env, tb_env->decr_next);
+    decr = _cpu_ppc_load_decr(env, tb_env->decr_next);
+
+    /*
+     * If large decrementer is enabled then the decrementer is signed extened
+     * to 64 bits, otherwise it is a 32 bit value.
+     */
+    if (env->spr[SPR_LPCR] & LPCR_LD) {
+        return decr;
+    }
+    return (uint32_t) decr;
 }
 
-uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
+target_ulong cpu_ppc_load_hdecr(CPUPPCState *env)
 {
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     ppc_tb_t *tb_env = env->tb_env;
+    uint64_t hdecr;
 
-    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+    hdecr =  _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+
+    /*
+     * If we have a large decrementer (POWER9 or later) then hdecr is sign
+     * extended to 64 bits, otherwise it is 32 bits.
+     */
+    if (pcc->lrg_decr_bits > 32) {
+        return hdecr;
+    }
+    return (uint32_t) hdecr;
 }
 
 uint64_t cpu_ppc_load_purr (CPUPPCState *env)
@@ -832,13 +853,22 @@
                                  QEMUTimer *timer,
                                  void (*raise_excp)(void *),
                                  void (*lower_excp)(PowerPCCPU *),
-                                 uint32_t decr, uint32_t value)
+                                 target_ulong decr, target_ulong value,
+                                 int nr_bits)
 {
     CPUPPCState *env = &cpu->env;
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t now, next;
+    bool negative;
 
-    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
+    /* Truncate value to decr_width and sign extend for simplicity */
+    value &= ((1ULL << nr_bits) - 1);
+    negative = !!(value & (1ULL << (nr_bits - 1)));
+    if (negative) {
+        value |= (0xFFFFFFFFULL << nr_bits);
+    }
+
+    LOG_TB("%s: " TARGET_FMT_lx " => " TARGET_FMT_lx "\n", __func__,
                 decr, value);
 
     if (kvm_enabled()) {
@@ -860,15 +890,15 @@
      * an edge interrupt, so raise it here too.
      */
     if ((value < 3) ||
-        ((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x80000000)) ||
-        ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000)
-          && !(decr & 0x80000000))) {
+        ((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && negative) ||
+        ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && negative
+          && !(decr & (1ULL << (nr_bits - 1))))) {
         (*raise_excp)(cpu);
         return;
     }
 
     /* On MSB level based systems a 0 for the MSB stops interrupt delivery */
-    if (!(value & 0x80000000) && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
+    if (!negative && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
         (*lower_excp)(cpu);
     }
 
@@ -881,21 +911,27 @@
     timer_mod(timer, next);
 }
 
-static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
-                                       uint32_t value)
+static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr,
+                                       target_ulong value, int nr_bits)
 {
     ppc_tb_t *tb_env = cpu->env.tb_env;
 
     __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
                          tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr,
-                         value);
+                         value, nr_bits);
 }
 
-void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
+void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    int nr_bits = 32;
 
-    _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value);
+    if (env->spr[SPR_LPCR] & LPCR_LD) {
+        nr_bits = pcc->lrg_decr_bits;
+    }
+
+    _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, nr_bits);
 }
 
 static void cpu_ppc_decr_cb(void *opaque)
@@ -905,23 +941,25 @@
     cpu_ppc_decr_excp(cpu);
 }
 
-static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
-                                        uint32_t value)
+static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, target_ulong hdecr,
+                                        target_ulong value, int nr_bits)
 {
     ppc_tb_t *tb_env = cpu->env.tb_env;
 
     if (tb_env->hdecr_timer != NULL) {
         __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
                              tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower,
-                             hdecr, value);
+                             hdecr, value, nr_bits);
     }
 }
 
-void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
+void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 
-    _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value);
+    _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value,
+                         pcc->lrg_decr_bits);
 }
 
 static void cpu_ppc_hdecr_cb(void *opaque)
@@ -951,8 +989,8 @@
      * if a decrementer exception is pending when it enables msr_ee at startup,
      * it's not ready to handle it...
      */
-    _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
-    _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
+    _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32);
+    _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32);
     cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
 }
 
@@ -1454,3 +1492,19 @@
         break;
     }
 }
+
+PowerPCCPU *ppc_get_vcpu_by_pir(int pir)
+{
+    CPUState *cs;
+
+    CPU_FOREACH(cs) {
+        PowerPCCPU *cpu = POWERPC_CPU(cs);
+        CPUPPCState *env = &cpu->env;
+
+        if (env->spr_cb[SPR_PIR].default_value == pir) {
+            return cpu;
+        }
+    }
+
+    return NULL;
+}
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index f47b15f..13318a9 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -48,8 +48,6 @@
 
 #define USE_FLASH_BIOS
 
-//#define DEBUG_BOARD_INIT
-
 /*****************************************************************************/
 /* PPC405EP reference board (IBM) */
 /* Standalone board with:
@@ -158,7 +156,7 @@
     target_ulong kernel_base, initrd_base;
     long kernel_size, initrd_size;
     int linux_boot;
-    int fl_idx, fl_sectors, len;
+    int len;
     DriveInfo *dinfo;
     MemoryRegion *sysmem = get_system_memory();
 
@@ -171,9 +169,6 @@
     ram_bases[1] = 0x00000000;
     ram_sizes[1] = 0x00000000;
     ram_size = 128 * MiB;
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register cpu\n", __func__);
-#endif
     env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
                         33333333, &pic, kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
@@ -182,35 +177,19 @@
                            &error_fatal);
     memory_region_add_subregion(sysmem, 0xFFF00000, sram);
     /* allocate and load BIOS */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register BIOS\n", __func__);
-#endif
-    fl_idx = 0;
 #ifdef USE_FLASH_BIOS
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
     if (dinfo) {
-        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
-
-        bios_size = blk_getlength(blk);
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr %lx '%s' %d\n",
-               fl_idx, bios_size, -bios_size,
-               blk_name(blk), fl_sectors);
-#endif
+        bios_size = 8 * MiB;
         pflash_cfi02_register((uint32_t)(-bios_size),
-                              NULL, "ef405ep.bios", bios_size,
-                              blk, 65536, fl_sectors, 1,
+                              "ef405ep.bios", bios_size,
+                              dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
+                              64 * KiB, 1,
                               2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
-        fl_idx++;
     } else
 #endif
     {
-#ifdef DEBUG_BOARD_INIT
-        printf("Load BIOS from file\n");
-#endif
         bios = g_new(MemoryRegion, 1);
         memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE,
                                &error_fatal);
@@ -239,21 +218,12 @@
         memory_region_set_readonly(bios, true);
     }
     /* Register FPGA */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register FPGA\n", __func__);
-#endif
     ref405ep_fpga_init(sysmem, 0xF0300000);
     /* Register NVRAM */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register NVRAM\n", __func__);
-#endif
     m48t59_init(NULL, 0xF0000000, 0, 8192, 1968, 8);
     /* Load kernel */
     linux_boot = (kernel_filename != NULL);
     if (linux_boot) {
-#ifdef DEBUG_BOARD_INIT
-        printf("%s: load kernel\n", __func__);
-#endif
         memset(&bd, 0, sizeof(bd));
         bd.bi_memstart = 0x00000000;
         bd.bi_memsize = ram_size;
@@ -325,10 +295,6 @@
         initrd_size = 0;
         bdloc = 0;
     }
-#ifdef DEBUG_BOARD_INIT
-    printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
-    printf("%s: Done\n", __func__);
-#endif
 }
 
 static void ref405ep_class_init(ObjectClass *oc, void *data)
@@ -455,7 +421,7 @@
     target_ulong kernel_base, initrd_base;
     long kernel_size, initrd_size;
     int linux_boot;
-    int fl_idx, fl_sectors;
+    int fl_idx;
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
@@ -473,43 +439,24 @@
     memory_region_init_alias(&ram_memories[1], NULL,
                              "taihu_405ep.ram-1", ram, ram_bases[1],
                              ram_sizes[1]);
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register cpu\n", __func__);
-#endif
     ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
                   33333333, &pic, kernel_filename == NULL ? 0 : 1);
     /* allocate and load BIOS */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register BIOS\n", __func__);
-#endif
     fl_idx = 0;
 #if defined(USE_FLASH_BIOS)
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
-
-        bios_size = blk_getlength(blk);
-        /* XXX: should check that size is 2MB */
-        //        bios_size = 2 * 1024 * 1024;
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr %lx '%s' %d\n",
-               fl_idx, bios_size, -bios_size,
-               blk_name(blk), fl_sectors);
-#endif
-        pflash_cfi02_register((uint32_t)(-bios_size),
-                              NULL, "taihu_405ep.bios", bios_size,
-                              blk, 65536, fl_sectors, 1,
+        bios_size = 2 * MiB;
+        pflash_cfi02_register(0xFFE00000,
+                              "taihu_405ep.bios", bios_size,
+                              dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
+                              64 * KiB, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
     } else
 #endif
     {
-#ifdef DEBUG_BOARD_INIT
-        printf("Load BIOS from file\n");
-#endif
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         bios = g_new(MemoryRegion, 1);
@@ -536,35 +483,19 @@
     /* Register Linux flash */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
-
-        bios_size = blk_getlength(blk);
-        /* XXX: should check that size is 32MB */
         bios_size = 32 * MiB;
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr " TARGET_FMT_lx " '%s'\n",
-               fl_idx, bios_size, (target_ulong)0xfc000000,
-               blk_name(blk));
-#endif
-        pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
-                              blk, 65536, fl_sectors, 1,
+        pflash_cfi02_register(0xfc000000, "taihu_405ep.flash", bios_size,
+                              dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
+                              64 * KiB, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
     }
     /* Register CLPD & LCD display */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register CPLD\n", __func__);
-#endif
     taihu_cpld_init(sysmem, 0x50100000);
     /* Load kernel */
     linux_boot = (kernel_filename != NULL);
     if (linux_boot) {
-#ifdef DEBUG_BOARD_INIT
-        printf("%s: load kernel\n", __func__);
-#endif
         kernel_base = KERNEL_LOAD_ADDR;
         /* now we can load the kernel */
         kernel_size = load_image_targphys(kernel_filename, kernel_base,
@@ -593,9 +524,6 @@
         initrd_base = 0;
         initrd_size = 0;
     }
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: Done\n", __func__);
-#endif
 }
 
 static void taihu_class_init(ObjectClass *oc, void *data)
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index d455c4b..fbcddc5 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -91,32 +91,42 @@
 
 static int sam460ex_load_uboot(void)
 {
+    /*
+     * This first creates 1MiB of flash memory mapped at the end of
+     * the 32-bit address space (0xFFF00000..0xFFFFFFFF).
+     *
+     * If_PFLASH unit 0 is defined, the flash memory is initialized
+     * from that block backend.
+     *
+     * Else, it's initialized to zero.  And then 512KiB of ROM get
+     * mapped on top of its second half (0xFFF80000..0xFFFFFFFF),
+     * initialized from u-boot-sam460-20100605.bin.
+     *
+     * This doesn't smell right.
+     *
+     * The physical hardware appears to have 512KiB flash memory.
+     *
+     * TODO Figure out what we really need here, and clean this up.
+     */
+
     DriveInfo *dinfo;
-    BlockBackend *blk = NULL;
-    hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
-    long bios_size = FLASH_SIZE;
-    int fl_sectors;
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (dinfo) {
-        blk = blk_by_legacy_dinfo(dinfo);
-        bios_size = blk_getlength(blk);
-    }
-    fl_sectors = (bios_size + 65535) >> 16;
-
-    if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
-                               blk, 64 * KiB, fl_sectors,
-                               1, 0x89, 0x18, 0x0000, 0x0, 1)) {
+    if (!pflash_cfi01_register(FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32),
+                               "sam460ex.flash", FLASH_SIZE,
+                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
+                               64 * KiB, 1, 0x89, 0x18, 0x0000, 0x0, 1)) {
         error_report("Error registering flash memory");
         /* XXX: return an error instead? */
         exit(1);
     }
 
-    if (!blk) {
+    if (!dinfo) {
         /*error_report("No flash image given with the 'pflash' parameter,"
                 " using default u-boot image");*/
-        base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
-        rom_add_file_fixed(UBOOT_FILENAME, base, -1);
+        rom_add_file_fixed(UBOOT_FILENAME,
+                           UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32),
+                           -1);
     }
 
     return 0;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 9e01226..6c16d6c 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -29,6 +29,7 @@
 #include "qapi/visitor.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/numa.h"
+#include "sysemu/qtest.h"
 #include "hw/hw.h"
 #include "qemu/log.h"
 #include "hw/fw-path-provider.h"
@@ -102,13 +103,13 @@
  * all and one to identify thread 0 of a VCORE. Any change to the first one
  * is likely to have an impact on the second one, so let's keep them close.
  */
-static int spapr_vcpu_id(sPAPRMachineState *spapr, int cpu_index)
+static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index)
 {
     assert(spapr->vsmt);
     return
         (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads;
 }
-static bool spapr_is_thread0_in_vcore(sPAPRMachineState *spapr,
+static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr,
                                       PowerPCCPU *cpu)
 {
     assert(spapr->vsmt);
@@ -149,7 +150,7 @@
                        (void *)(uintptr_t) i);
 }
 
-int spapr_max_server_number(sPAPRMachineState *spapr)
+int spapr_max_server_number(SpaprMachineState *spapr)
 {
     assert(spapr->vsmt);
     return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads);
@@ -204,7 +205,7 @@
 }
 
 /* Populate the "ibm,pa-features" property */
-static void spapr_populate_pa_features(sPAPRMachineState *spapr,
+static void spapr_populate_pa_features(SpaprMachineState *spapr,
                                        PowerPCCPU *cpu,
                                        void *fdt, int offset,
                                        bool legacy_guest)
@@ -283,7 +284,7 @@
     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
 }
 
-static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
+static int spapr_fixup_cpu_dt(void *fdt, SpaprMachineState *spapr)
 {
     int ret = 0, offset, cpus_offset;
     CPUState *cs;
@@ -386,7 +387,7 @@
     return off;
 }
 
-static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt)
+static int spapr_populate_memory(SpaprMachineState *spapr, void *fdt)
 {
     MachineState *machine = MACHINE(spapr);
     hwaddr mem_start, node_size;
@@ -438,7 +439,7 @@
 }
 
 static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
-                                  sPAPRMachineState *spapr)
+                                  SpaprMachineState *spapr)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     CPUPPCState *env = &cpu->env;
@@ -454,7 +455,7 @@
     uint32_t vcpus_per_socket = smp_threads * smp_cores;
     uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
     int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu));
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     int drc_index;
     uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ];
     int i;
@@ -557,9 +558,17 @@
                           pcc->radix_page_info->count *
                           sizeof(radix_AP_encodings[0]))));
     }
+
+    /*
+     * We set this property to let the guest know that it can use the large
+     * decrementer and its width in bits.
+     */
+    if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) != SPAPR_CAP_OFF)
+        _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits",
+                              pcc->lrg_decr_bits)));
 }
 
-static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr)
+static void spapr_populate_cpus_dt_node(void *fdt, SpaprMachineState *spapr)
 {
     CPUState **rev;
     CPUState *cs;
@@ -683,7 +692,7 @@
 }
 
 /* ibm,dynamic-memory-v2 */
-static int spapr_populate_drmem_v2(sPAPRMachineState *spapr, void *fdt,
+static int spapr_populate_drmem_v2(SpaprMachineState *spapr, void *fdt,
                                    int offset, MemoryDeviceInfoList *dimms)
 {
     MachineState *machine = MACHINE(spapr);
@@ -695,7 +704,7 @@
     uint64_t mem_end = machine->device_memory->base +
                        memory_region_size(&machine->device_memory->mr);
     uint32_t node, buf_len, nr_entries = 0;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     DrconfCellQueue *elem, *next;
     MemoryDeviceInfoList *info;
     QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue
@@ -768,7 +777,7 @@
 }
 
 /* ibm,dynamic-memory */
-static int spapr_populate_drmem_v1(sPAPRMachineState *spapr, void *fdt,
+static int spapr_populate_drmem_v1(SpaprMachineState *spapr, void *fdt,
                                    int offset, MemoryDeviceInfoList *dimms)
 {
     MachineState *machine = MACHINE(spapr);
@@ -792,7 +801,7 @@
         uint32_t *dynamic_memory = cur_index;
 
         if (i >= device_lmb_start) {
-            sPAPRDRConnector *drc;
+            SpaprDrc *drc;
 
             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i);
             g_assert(drc);
@@ -837,7 +846,7 @@
  * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation
  * of this device tree node.
  */
-static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
+static int spapr_populate_drconf_memory(SpaprMachineState *spapr, void *fdt)
 {
     MachineState *machine = MACHINE(spapr);
     int ret, i, offset;
@@ -908,10 +917,10 @@
     return ret;
 }
 
-static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt,
-                                sPAPROptionVector *ov5_updates)
+static int spapr_dt_cas_updates(SpaprMachineState *spapr, void *fdt,
+                                SpaprOptionVector *ov5_updates)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     int ret = 0, offset;
 
     /* Generate ibm,dynamic-reconfiguration-memory node if required */
@@ -957,12 +966,12 @@
     return false;
 }
 
-int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
+int spapr_h_cas_compose_response(SpaprMachineState *spapr,
                                  target_ulong addr, target_ulong size,
-                                 sPAPROptionVector *ov5_updates)
+                                 SpaprOptionVector *ov5_updates)
 {
     void *fdt, *fdt_skel;
-    sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 };
+    SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 };
 
     if (spapr_hotplugged_dev_before_cas()) {
         return 1;
@@ -1011,7 +1020,7 @@
     return 0;
 }
 
-static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
+static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
 {
     int rtas;
     GString *hypertas = g_string_sized_new(256);
@@ -1100,7 +1109,7 @@
  * and the XIVE features that the guest may request and thus the valid
  * values for bytes 23..26 of option vector 5:
  */
-static void spapr_dt_ov5_platform_support(sPAPRMachineState *spapr, void *fdt,
+static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
                                           int chosen)
 {
     PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
@@ -1136,7 +1145,7 @@
                      val, sizeof(val)));
 }
 
-static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
+static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt)
 {
     MachineState *machine = MACHINE(spapr);
     int chosen;
@@ -1202,7 +1211,7 @@
     g_free(bootlist);
 }
 
-static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt)
+static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt)
 {
     /* The /hypervisor node isn't in PAPR - this is a hack to allow PR
      * KVM to work under pHyp with some guest co-operation */
@@ -1225,14 +1234,14 @@
     }
 }
 
-static void *spapr_build_fdt(sPAPRMachineState *spapr)
+static void *spapr_build_fdt(SpaprMachineState *spapr)
 {
     MachineState *machine = MACHINE(spapr);
     MachineClass *mc = MACHINE_GET_CLASS(machine);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
     int ret;
     void *fdt;
-    sPAPRPHBState *phb;
+    SpaprPhbState *phb;
     char *buf;
 
     fdt = g_malloc0(FDT_MAX_SIZE);
@@ -1430,7 +1439,7 @@
 
 static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     /* Copy PATE1:GR into PATE0:HR */
     entry->dw0 = spapr->patb_entry & PATE0_HR;
@@ -1446,7 +1455,7 @@
 /*
  * Get the fd to access the kernel htab, re-opening it if necessary
  */
-static int get_htab_fd(sPAPRMachineState *spapr)
+static int get_htab_fd(SpaprMachineState *spapr)
 {
     Error *local_err = NULL;
 
@@ -1462,7 +1471,7 @@
     return spapr->htab_fd;
 }
 
-void close_htab_fd(sPAPRMachineState *spapr)
+void close_htab_fd(SpaprMachineState *spapr)
 {
     if (spapr->htab_fd >= 0) {
         close(spapr->htab_fd);
@@ -1472,14 +1481,14 @@
 
 static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1;
 }
 
 static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     assert(kvm_enabled());
 
@@ -1493,7 +1502,7 @@
 static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp,
                                                 hwaddr ptex, int n)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
     hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
 
     if (!spapr->htab) {
@@ -1516,7 +1525,7 @@
                               const ppc_hash_pte64_t *hptes,
                               hwaddr ptex, int n)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     if (!spapr->htab) {
         g_free((void *)hptes);
@@ -1528,7 +1537,7 @@
 static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex,
                              uint64_t pte0, uint64_t pte1)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
     hwaddr offset = ptex * HASH_PTE_SIZE_64;
 
     if (!spapr->htab) {
@@ -1569,7 +1578,7 @@
     return shift;
 }
 
-void spapr_free_hpt(sPAPRMachineState *spapr)
+void spapr_free_hpt(SpaprMachineState *spapr)
 {
     g_free(spapr->htab);
     spapr->htab = NULL;
@@ -1577,7 +1586,7 @@
     close_htab_fd(spapr);
 }
 
-void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
+void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift,
                           Error **errp)
 {
     long rc;
@@ -1623,10 +1632,11 @@
         }
     }
     /* We're setting up a hash table, so that means we're not radix */
+    spapr->patb_entry = 0;
     spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT);
 }
 
-void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
+void spapr_setup_hpt_and_vrma(SpaprMachineState *spapr)
 {
     int hpt_shift;
 
@@ -1650,8 +1660,8 @@
 
 static int spapr_reset_drcs(Object *child, void *opaque)
 {
-    sPAPRDRConnector *drc =
-        (sPAPRDRConnector *) object_dynamic_cast(child,
+    SpaprDrc *drc =
+        (SpaprDrc *) object_dynamic_cast(child,
                                                  TYPE_SPAPR_DR_CONNECTOR);
 
     if (drc) {
@@ -1664,7 +1674,7 @@
 static void spapr_machine_reset(void)
 {
     MachineState *machine = MACHINE(qdev_get_machine());
-    sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
+    SpaprMachineState *spapr = SPAPR_MACHINE(machine);
     PowerPCCPU *first_ppc_cpu;
     uint32_t rtas_limit;
     hwaddr rtas_addr, fdt_addr;
@@ -1711,6 +1721,16 @@
      */
     spapr_irq_reset(spapr, &error_fatal);
 
+    /*
+     * There is no CAS under qtest. Simulate one to please the code that
+     * depends on spapr->ov5_cas. This is especially needed to test device
+     * unplug, so we do that before resetting the DRCs.
+     */
+    if (qtest_enabled()) {
+        spapr_ovec_cleanup(spapr->ov5_cas);
+        spapr->ov5_cas = spapr_ovec_clone(spapr->ov5);
+    }
+
     /* DRC reset may cause a device to be unplugged. This will cause troubles
      * if this device is used by another device (eg, a running vhost backend
      * will crash QEMU if the DIMM holding the vring goes away). To avoid such
@@ -1759,7 +1779,7 @@
     spapr->cas_reboot = false;
 }
 
-static void spapr_create_nvram(sPAPRMachineState *spapr)
+static void spapr_create_nvram(SpaprMachineState *spapr)
 {
     DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
@@ -1771,10 +1791,10 @@
 
     qdev_init_nofail(dev);
 
-    spapr->nvram = (struct sPAPRNVRAM *)dev;
+    spapr->nvram = (struct SpaprNvram *)dev;
 }
 
-static void spapr_rtc_create(sPAPRMachineState *spapr)
+static void spapr_rtc_create(SpaprMachineState *spapr)
 {
     object_initialize_child(OBJECT(spapr), "rtc",
                             &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC,
@@ -1818,7 +1838,7 @@
 
 static int spapr_post_load(void *opaque, int version_id)
 {
-    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    SpaprMachineState *spapr = (SpaprMachineState *)opaque;
     int err = 0;
 
     err = spapr_caps_post_migration(spapr);
@@ -1885,7 +1905,7 @@
 
 static bool spapr_pending_events_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    SpaprMachineState *spapr = (SpaprMachineState *)opaque;
     return !QTAILQ_EMPTY(&spapr->pending_events);
 }
 
@@ -1894,9 +1914,9 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(summary, sPAPREventLogEntry),
-        VMSTATE_UINT32(extended_length, sPAPREventLogEntry),
-        VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, sPAPREventLogEntry, 0,
+        VMSTATE_UINT32(summary, SpaprEventLogEntry),
+        VMSTATE_UINT32(extended_length, SpaprEventLogEntry),
+        VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0,
                                      NULL, extended_length),
         VMSTATE_END_OF_LIST()
     },
@@ -1908,21 +1928,21 @@
     .minimum_version_id = 1,
     .needed = spapr_pending_events_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1,
-                         vmstate_spapr_event_entry, sPAPREventLogEntry, next),
+        VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1,
+                         vmstate_spapr_event_entry, SpaprEventLogEntry, next),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_ov5_cas_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
-    sPAPROptionVector *ov5_mask = spapr_ovec_new();
-    sPAPROptionVector *ov5_legacy = spapr_ovec_new();
-    sPAPROptionVector *ov5_removed = spapr_ovec_new();
+    SpaprMachineState *spapr = opaque;
+    SpaprOptionVector *ov5_mask = spapr_ovec_new();
+    SpaprOptionVector *ov5_legacy = spapr_ovec_new();
+    SpaprOptionVector *ov5_removed = spapr_ovec_new();
     bool cas_needed;
 
-    /* Prior to the introduction of sPAPROptionVector, we had two option
+    /* Prior to the introduction of SpaprOptionVector, we had two option
      * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY.
      * Both of these options encode machine topology into the device-tree
      * in such a way that the now-booted OS should still be able to interact
@@ -1972,15 +1992,15 @@
     .minimum_version_id = 1,
     .needed = spapr_ov5_cas_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1,
-                                 vmstate_spapr_ovec, sPAPROptionVector),
+        VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1,
+                                 vmstate_spapr_ovec, SpaprOptionVector),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_patb_entry_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     return !!spapr->patb_entry;
 }
@@ -1991,14 +2011,14 @@
     .minimum_version_id = 1,
     .needed = spapr_patb_entry_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64(patb_entry, sPAPRMachineState),
+        VMSTATE_UINT64(patb_entry, SpaprMachineState),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_irq_map_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr);
 }
@@ -2009,21 +2029,21 @@
     .minimum_version_id = 1,
     .needed = spapr_irq_map_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_BITMAP(irq_map, sPAPRMachineState, 0, irq_map_nr),
+        VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_dtb_needed(void *opaque)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
 
     return smc->update_dt_enabled;
 }
 
 static int spapr_dtb_pre_load(void *opaque)
 {
-    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    SpaprMachineState *spapr = (SpaprMachineState *)opaque;
 
     g_free(spapr->fdt_blob);
     spapr->fdt_blob = NULL;
@@ -2039,9 +2059,9 @@
     .needed = spapr_dtb_needed,
     .pre_load = spapr_dtb_pre_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(fdt_initial_size, sPAPRMachineState),
-        VMSTATE_UINT32(fdt_size, sPAPRMachineState),
-        VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, sPAPRMachineState, 0, NULL,
+        VMSTATE_UINT32(fdt_initial_size, SpaprMachineState),
+        VMSTATE_UINT32(fdt_size, SpaprMachineState),
+        VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL,
                                      fdt_size),
         VMSTATE_END_OF_LIST()
     },
@@ -2059,9 +2079,9 @@
         VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
 
         /* RTC offset */
-        VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3),
+        VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3),
 
-        VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
+        VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2),
         VMSTATE_END_OF_LIST()
     },
     .subsections = (const VMStateDescription*[]) {
@@ -2077,13 +2097,15 @@
         &vmstate_spapr_irq_map,
         &vmstate_spapr_cap_nested_kvm_hv,
         &vmstate_spapr_dtb,
+        &vmstate_spapr_cap_large_decr,
+        &vmstate_spapr_cap_ccf_assist,
         NULL
     }
 };
 
 static int htab_save_setup(QEMUFile *f, void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     /* "Iteration" header */
     if (!spapr->htab_shift) {
@@ -2105,7 +2127,7 @@
     return 0;
 }
 
-static void htab_save_chunk(QEMUFile *f, sPAPRMachineState *spapr,
+static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr,
                             int chunkstart, int n_valid, int n_invalid)
 {
     qemu_put_be32(f, chunkstart);
@@ -2122,7 +2144,7 @@
     qemu_put_be16(f, 0);
 }
 
-static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
+static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr,
                                  int64_t max_ns)
 {
     bool has_timeout = max_ns != -1;
@@ -2170,7 +2192,7 @@
     spapr->htab_save_index = index;
 }
 
-static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr,
+static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr,
                                 int64_t max_ns)
 {
     bool final = max_ns < 0;
@@ -2248,7 +2270,7 @@
 
 static int htab_save_iterate(QEMUFile *f, void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
     int fd;
     int rc = 0;
 
@@ -2285,7 +2307,7 @@
 
 static int htab_save_complete(QEMUFile *f, void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
     int fd;
 
     /* Iteration header */
@@ -2325,7 +2347,7 @@
 
 static int htab_load(QEMUFile *f, void *opaque, int version_id)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
     uint32_t section_hdr;
     int fd = -1;
     Error *local_err = NULL;
@@ -2415,7 +2437,7 @@
 
 static void htab_save_cleanup(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     close_htab_fd(spapr);
 }
@@ -2435,7 +2457,7 @@
     machine->boot_order = g_strdup(boot_device);
 }
 
-static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr)
+static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr)
 {
     MachineState *machine = MACHINE(spapr);
     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
@@ -2502,7 +2524,7 @@
     return &ms->possible_cpus->cpus[index];
 }
 
-static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp)
+static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
 {
     Error *local_err = NULL;
     bool vsmt_user = !!spapr->vsmt;
@@ -2574,11 +2596,11 @@
     error_propagate(errp, local_err);
 }
 
-static void spapr_init_cpus(sPAPRMachineState *spapr)
+static void spapr_init_cpus(SpaprMachineState *spapr)
 {
     MachineState *machine = MACHINE(spapr);
     MachineClass *mc = MACHINE_GET_CLASS(machine);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
     const char *type = spapr_get_cpu_core_type(machine->cpu_type);
     const CPUArchIdList *possible_cpus;
     int boot_cores_nr = smp_cpus / smp_threads;
@@ -2657,8 +2679,8 @@
 /* pSeries LPAR / sPAPR hardware init */
 static void spapr_machine_init(MachineState *machine)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
+    SpaprMachineState *spapr = SPAPR_MACHINE(machine);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
     const char *kernel_filename = machine->kernel_filename;
     const char *initrd_filename = machine->initrd_filename;
     PCIHostState *phb;
@@ -2800,6 +2822,9 @@
 
         /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */
         kvmppc_enable_clear_ref_mod_hcalls();
+
+        /* Enable H_PAGE_INIT */
+        kvmppc_enable_h_page_init();
     }
 
     /* allocate RAM */
@@ -3051,7 +3076,7 @@
 #define CAST(type, obj, name) \
     ((type *)object_dynamic_cast(OBJECT(obj), (name)))
     SCSIDevice *d = CAST(SCSIDevice,  dev, TYPE_SCSI_DEVICE);
-    sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
+    SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
     VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON);
 
     if (d) {
@@ -3131,14 +3156,14 @@
 
 static char *spapr_get_kvm_type(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return g_strdup(spapr->kvm_type);
 }
 
 static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->kvm_type);
     spapr->kvm_type = g_strdup(value);
@@ -3146,7 +3171,7 @@
 
 static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return spapr->use_hotplug_event_source;
 }
@@ -3154,7 +3179,7 @@
 static void spapr_set_modern_hotplug_events(Object *obj, bool value,
                                             Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     spapr->use_hotplug_event_source = value;
 }
@@ -3166,7 +3191,7 @@
 
 static char *spapr_get_resize_hpt(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     switch (spapr->resize_hpt) {
     case SPAPR_RESIZE_HPT_DEFAULT:
@@ -3183,7 +3208,7 @@
 
 static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     if (strcmp(value, "default") == 0) {
         spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT;
@@ -3212,7 +3237,7 @@
 
 static char *spapr_get_ic_mode(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     if (spapr->irq == &spapr_irq_xics_legacy) {
         return g_strdup("legacy");
@@ -3228,7 +3253,7 @@
 
 static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
         error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode");
@@ -3249,14 +3274,14 @@
 
 static char *spapr_get_host_model(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return g_strdup(spapr->host_model);
 }
 
 static void spapr_set_host_model(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->host_model);
     spapr->host_model = g_strdup(value);
@@ -3264,14 +3289,14 @@
 
 static char *spapr_get_host_serial(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return g_strdup(spapr->host_serial);
 }
 
 static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->host_serial);
     spapr->host_serial = g_strdup(value);
@@ -3279,8 +3304,8 @@
 
 static void spapr_instance_init(Object *obj)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 
     spapr->htab_fd = -1;
     spapr->use_hotplug_event_source = true;
@@ -3337,7 +3362,7 @@
 
 static void spapr_machine_finalizefn(Object *obj)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->kvm_type);
 }
@@ -3357,7 +3382,7 @@
     }
 }
 
-int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp)
 {
     uint64_t addr;
@@ -3374,7 +3399,7 @@
 static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
                            bool dedicated_hp_event_source, Error **errp)
 {
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
     int i;
     uint64_t addr = addr_start;
@@ -3423,7 +3448,7 @@
                               Error **errp)
 {
     Error *local_err = NULL;
-    sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
+    SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev);
     PCDIMMDevice *dimm = PC_DIMM(dev);
     uint64_t size, addr;
 
@@ -3457,8 +3482,8 @@
 static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                   Error **errp)
 {
-    const sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
+    const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
     PCDIMMDevice *dimm = PC_DIMM(dev);
     Error *local_err = NULL;
     uint64_t size;
@@ -3494,16 +3519,16 @@
     pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp);
 }
 
-struct sPAPRDIMMState {
+struct SpaprDimmState {
     PCDIMMDevice *dimm;
     uint32_t nr_lmbs;
-    QTAILQ_ENTRY(sPAPRDIMMState) next;
+    QTAILQ_ENTRY(SpaprDimmState) next;
 };
 
-static sPAPRDIMMState *spapr_pending_dimm_unplugs_find(sPAPRMachineState *s,
+static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s,
                                                        PCDIMMDevice *dimm)
 {
-    sPAPRDIMMState *dimm_state = NULL;
+    SpaprDimmState *dimm_state = NULL;
 
     QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) {
         if (dimm_state->dimm == dimm) {
@@ -3513,11 +3538,11 @@
     return dimm_state;
 }
 
-static sPAPRDIMMState *spapr_pending_dimm_unplugs_add(sPAPRMachineState *spapr,
+static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr,
                                                       uint32_t nr_lmbs,
                                                       PCDIMMDevice *dimm)
 {
-    sPAPRDIMMState *ds = NULL;
+    SpaprDimmState *ds = NULL;
 
     /*
      * If this request is for a DIMM whose removal had failed earlier
@@ -3527,7 +3552,7 @@
      */
     ds = spapr_pending_dimm_unplugs_find(spapr, dimm);
     if (!ds) {
-        ds = g_malloc0(sizeof(sPAPRDIMMState));
+        ds = g_malloc0(sizeof(SpaprDimmState));
         ds->nr_lmbs = nr_lmbs;
         ds->dimm = dimm;
         QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next);
@@ -3535,17 +3560,17 @@
     return ds;
 }
 
-static void spapr_pending_dimm_unplugs_remove(sPAPRMachineState *spapr,
-                                              sPAPRDIMMState *dimm_state)
+static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr,
+                                              SpaprDimmState *dimm_state)
 {
     QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next);
     g_free(dimm_state);
 }
 
-static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms,
+static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms,
                                                         PCDIMMDevice *dimm)
 {
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm),
                                                   &error_abort);
     uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
@@ -3574,8 +3599,8 @@
 void spapr_lmb_release(DeviceState *dev)
 {
     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
-    sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
+    SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
 
     /* This information will get lost if a migration occurs
      * during the unplug process. In this case recover it. */
@@ -3600,8 +3625,8 @@
 
 static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
-    sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
+    SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
 
     pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev));
     object_property_set_bool(OBJECT(dev), false, "realized", NULL);
@@ -3611,13 +3636,13 @@
 static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
                                         DeviceState *dev, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
     Error *local_err = NULL;
     PCDIMMDevice *dimm = PC_DIMM(dev);
     uint32_t nr_lmbs;
     uint64_t size, addr_start, addr;
     int i;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
 
     size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort);
     nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
@@ -3674,12 +3699,12 @@
 static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
 {
     MachineState *ms = MACHINE(hotplug_dev);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
     CPUCore *cc = CPU_CORE(dev);
     CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL);
 
     if (smc->pre_2_10_has_unused_icps) {
-        sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
+        SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
         int i;
 
         for (i = 0; i < cc->nr_threads; i++) {
@@ -3698,9 +3723,9 @@
 void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
                                Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
     int index;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     CPUCore *cc = CPU_CORE(dev);
 
     if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) {
@@ -3722,10 +3747,10 @@
     spapr_hotplug_req_remove_by_index(drc);
 }
 
-int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                            void *fdt, int *fdt_start_offset, Error **errp)
 {
-    sPAPRCPUCore *core = SPAPR_CPU_CORE(drc->dev);
+    SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev);
     CPUState *cs = CPU(core->threads[0]);
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     DeviceClass *dc = DEVICE_GET_CLASS(cs);
@@ -3746,13 +3771,13 @@
 static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                             Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
     MachineClass *mc = MACHINE_GET_CLASS(spapr);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-    sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev));
     CPUCore *cc = CPU_CORE(dev);
     CPUState *cs;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     Error *local_err = NULL;
     CPUArchId *core_slot;
     int index;
@@ -3855,10 +3880,10 @@
     error_propagate(errp, local_err);
 }
 
-int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
     int intc_phandle;
 
     intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp);
@@ -3881,9 +3906,9 @@
 static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
 
     if (dev->hotplugged && !smc->dr_phb_enabled) {
@@ -3909,10 +3934,10 @@
 static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                            Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
-    sPAPRDRConnector *drc;
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+    SpaprDrc *drc;
     bool hotplugged = spapr_drc_hotplugged(dev);
     Error *local_err = NULL;
 
@@ -3953,8 +3978,8 @@
 static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
-    sPAPRDRConnector *drc;
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+    SpaprDrc *drc;
 
     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
     assert(drc);
@@ -3992,9 +4017,9 @@
 static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
                                                 DeviceState *dev, Error **errp)
 {
-    sPAPRMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
     MachineClass *mc = MACHINE_GET_CLASS(sms);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
         if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
@@ -4101,7 +4126,7 @@
     return machine->possible_cpus;
 }
 
-static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index,
+static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
                                 uint64_t *buid, hwaddr *pio,
                                 hwaddr *mmio32, hwaddr *mmio64,
                                 unsigned n_dma, uint32_t *liobns, Error **errp)
@@ -4153,14 +4178,14 @@
 
 static ICSState *spapr_ics_get(XICSFabric *dev, int irq)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(dev);
 
     return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL;
 }
 
 static void spapr_ics_resend(XICSFabric *dev)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(dev);
 
     ics_resend(spapr->ics);
 }
@@ -4175,7 +4200,7 @@
 static void spapr_pic_print_info(InterruptStatsProvider *obj,
                                  Monitor *mon)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     spapr->irq->print_info(spapr, mon);
 }
@@ -4187,7 +4212,7 @@
 
 void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
     int vcpu_id;
 
     vcpu_id = spapr_vcpu_id(spapr, cpu_index);
@@ -4221,7 +4246,7 @@
 static void spapr_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc);
     FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
     NMIClass *nc = NMI_CLASS(oc);
     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
@@ -4286,11 +4311,13 @@
     smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
     smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
     smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
-    smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
-    smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
-    smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+    smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
+    smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND;
     smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
     smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
+    smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
+    smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
     spapr_caps_add_properties(smc, &error_abort);
     smc->irq = &spapr_irq_xics;
     smc->dr_phb_enabled = true;
@@ -4300,10 +4327,10 @@
     .name          = TYPE_SPAPR_MACHINE,
     .parent        = TYPE_MACHINE,
     .abstract      = true,
-    .instance_size = sizeof(sPAPRMachineState),
+    .instance_size = sizeof(SpaprMachineState),
     .instance_init = spapr_instance_init,
     .instance_finalize = spapr_machine_finalizefn,
-    .class_size    = sizeof(sPAPRMachineClass),
+    .class_size    = sizeof(SpaprMachineClass),
     .class_init    = spapr_machine_class_init,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_FW_PATH_PROVIDER },
@@ -4353,7 +4380,7 @@
  */
 static void spapr_machine_3_1_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { TYPE_SPAPR_MACHINE, "host-model", "passthrough" },
         { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" },
@@ -4366,6 +4393,10 @@
     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
     smc->update_dt_enabled = false;
     smc->dr_phb_enabled = false;
+    smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
 }
 
 DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
@@ -4376,7 +4407,7 @@
 
 static void spapr_machine_3_0_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_3_1_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
@@ -4392,7 +4423,7 @@
  */
 static void spapr_machine_2_12_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" },
         { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" },
@@ -4414,7 +4445,7 @@
 
 static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_2_12_class_options(mc);
     smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
@@ -4430,7 +4461,7 @@
 
 static void spapr_machine_2_11_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_2_12_class_options(mc);
     smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
@@ -4457,7 +4488,7 @@
 
 static void spapr_machine_2_9_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" },
     };
@@ -4494,7 +4525,7 @@
  * pseries-2.7
  */
 
-static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
+static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
                               uint64_t *buid, hwaddr *pio,
                               hwaddr *mmio32, hwaddr *mmio64,
                               unsigned n_dma, uint32_t *liobns, Error **errp)
@@ -4545,7 +4576,7 @@
 
 static void spapr_machine_2_7_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", },
         { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", },
@@ -4587,7 +4618,7 @@
 
 static void spapr_machine_2_5_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { "spapr-vlan", "use-rx-buffer-pools", "off" },
     };
@@ -4606,7 +4637,7 @@
 
 static void spapr_machine_2_4_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_2_5_class_options(mc);
     smc->dr_lmb_enabled = false;
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index 64f98ae..edc5ed0 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -31,10 +31,11 @@
 #include "target/ppc/mmu-hash64.h"
 #include "cpu-models.h"
 #include "kvm_ppc.h"
+#include "sysemu/qtest.h"
 
 #include "hw/ppc/spapr.h"
 
-typedef struct sPAPRCapPossible {
+typedef struct SpaprCapPossible {
     int num;            /* size of vals array below */
     const char *help;   /* help text for vals */
     /*
@@ -46,9 +47,9 @@
      *   point is observed
      */
     const char *vals[];
-} sPAPRCapPossible;
+} SpaprCapPossible;
 
-typedef struct sPAPRCapabilityInfo {
+typedef struct SpaprCapabilityInfo {
     const char *name;
     const char *description;
     int index;
@@ -58,18 +59,18 @@
     ObjectPropertyAccessor *set;
     const char *type;
     /* Possible values if this is a custom string type */
-    sPAPRCapPossible *possible;
+    SpaprCapPossible *possible;
     /* Make sure the virtual hardware can support this capability */
-    void (*apply)(sPAPRMachineState *spapr, uint8_t val, Error **errp);
-    void (*cpu_apply)(sPAPRMachineState *spapr, PowerPCCPU *cpu,
+    void (*apply)(SpaprMachineState *spapr, uint8_t val, Error **errp);
+    void (*cpu_apply)(SpaprMachineState *spapr, PowerPCCPU *cpu,
                       uint8_t val, Error **errp);
-} sPAPRCapabilityInfo;
+} SpaprCapabilityInfo;
 
 static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name,
                                void *opaque, Error **errp)
 {
-    sPAPRCapabilityInfo *cap = opaque;
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprCapabilityInfo *cap = opaque;
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
     bool value = spapr_get_cap(spapr, cap->index) == SPAPR_CAP_ON;
 
     visit_type_bool(v, name, &value, errp);
@@ -78,8 +79,8 @@
 static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
                                void *opaque, Error **errp)
 {
-    sPAPRCapabilityInfo *cap = opaque;
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprCapabilityInfo *cap = opaque;
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
     bool value;
     Error *local_err = NULL;
 
@@ -97,8 +98,8 @@
 static void  spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
                                   void *opaque, Error **errp)
 {
-    sPAPRCapabilityInfo *cap = opaque;
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprCapabilityInfo *cap = opaque;
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
     char *val = NULL;
     uint8_t value = spapr_get_cap(spapr, cap->index);
 
@@ -116,8 +117,8 @@
 static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
                                  void *opaque, Error **errp)
 {
-    sPAPRCapabilityInfo *cap = opaque;
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprCapabilityInfo *cap = opaque;
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
     Error *local_err = NULL;
     uint8_t i;
     char *val;
@@ -149,8 +150,8 @@
 static void spapr_cap_get_pagesize(Object *obj, Visitor *v, const char *name,
                                    void *opaque, Error **errp)
 {
-    sPAPRCapabilityInfo *cap = opaque;
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprCapabilityInfo *cap = opaque;
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
     uint8_t val = spapr_get_cap(spapr, cap->index);
     uint64_t pagesize = (1ULL << val);
 
@@ -160,8 +161,8 @@
 static void spapr_cap_set_pagesize(Object *obj, Visitor *v, const char *name,
                                    void *opaque, Error **errp)
 {
-    sPAPRCapabilityInfo *cap = opaque;
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprCapabilityInfo *cap = opaque;
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
     uint64_t pagesize;
     uint8_t val;
     Error *local_err = NULL;
@@ -182,7 +183,7 @@
     spapr->eff.caps[cap->index] = val;
 }
 
-static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
+static void cap_htm_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
 {
     if (!val) {
         /* TODO: We don't support disabling htm yet */
@@ -198,7 +199,7 @@
     }
 }
 
-static void cap_vsx_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
+static void cap_vsx_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
 {
     PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
     CPUPPCState *env = &cpu->env;
@@ -215,7 +216,7 @@
     }
 }
 
-static void cap_dfp_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
+static void cap_dfp_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
 {
     PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
     CPUPPCState *env = &cpu->env;
@@ -229,83 +230,97 @@
     }
 }
 
-sPAPRCapPossible cap_cfpc_possible = {
+SpaprCapPossible cap_cfpc_possible = {
     .num = 3,
     .vals = {"broken", "workaround", "fixed"},
     .help = "broken - no protection, workaround - workaround available,"
             " fixed - fixed in hardware",
 };
 
-static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val,
+static void cap_safe_cache_apply(SpaprMachineState *spapr, uint8_t val,
                                  Error **errp)
 {
+    Error *local_err = NULL;
     uint8_t kvm_val =  kvmppc_get_cap_safe_cache();
 
     if (tcg_enabled() && val) {
-        /* TODO - for now only allow broken for TCG */
-        error_setg(errp,
-"Requested safe cache capability level not supported by tcg, try a different value for cap-cfpc");
+        /* TCG only supports broken, allow other values and print a warning */
+        error_setg(&local_err,
+                   "TCG doesn't support requested feature, cap-cfpc=%s",
+                   cap_cfpc_possible.vals[val]);
     } else if (kvm_enabled() && (val > kvm_val)) {
         error_setg(errp,
 "Requested safe cache capability level not supported by kvm, try cap-cfpc=%s",
                    cap_cfpc_possible.vals[kvm_val]);
     }
+
+    if (local_err != NULL)
+        warn_report_err(local_err);
 }
 
-sPAPRCapPossible cap_sbbc_possible = {
+SpaprCapPossible cap_sbbc_possible = {
     .num = 3,
     .vals = {"broken", "workaround", "fixed"},
     .help = "broken - no protection, workaround - workaround available,"
             " fixed - fixed in hardware",
 };
 
-static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val,
+static void cap_safe_bounds_check_apply(SpaprMachineState *spapr, uint8_t val,
                                         Error **errp)
 {
+    Error *local_err = NULL;
     uint8_t kvm_val =  kvmppc_get_cap_safe_bounds_check();
 
     if (tcg_enabled() && val) {
-        /* TODO - for now only allow broken for TCG */
-        error_setg(errp,
-"Requested safe bounds check capability level not supported by tcg, try a different value for cap-sbbc");
+        /* TCG only supports broken, allow other values and print a warning */
+        error_setg(&local_err,
+                   "TCG doesn't support requested feature, cap-sbbc=%s",
+                   cap_sbbc_possible.vals[val]);
     } else if (kvm_enabled() && (val > kvm_val)) {
         error_setg(errp,
 "Requested safe bounds check capability level not supported by kvm, try cap-sbbc=%s",
                    cap_sbbc_possible.vals[kvm_val]);
     }
+
+    if (local_err != NULL)
+        warn_report_err(local_err);
 }
 
-sPAPRCapPossible cap_ibs_possible = {
-    .num = 4,
+SpaprCapPossible cap_ibs_possible = {
+    .num = 5,
     /* Note workaround only maintained for compatibility */
-    .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"},
-    .help = "broken - no protection, fixed-ibs - indirect branch serialisation,"
-            " fixed-ccd - cache count disabled",
+    .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"},
+    .help = "broken - no protection, workaround - count cache flush"
+            ", fixed-ibs - indirect branch serialisation,"
+            " fixed-ccd - cache count disabled,"
+            " fixed-na - fixed in hardware (no longer applicable)",
 };
 
-static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
+static void cap_safe_indirect_branch_apply(SpaprMachineState *spapr,
                                            uint8_t val, Error **errp)
 {
+    Error *local_err = NULL;
     uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
 
-    if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */
-        error_setg(errp,
-"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s",
-                   cap_ibs_possible.vals[kvm_val]);
-    } else if (tcg_enabled() && val) {
-        /* TODO - for now only allow broken for TCG */
-        error_setg(errp,
-"Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs");
-    } else if (kvm_enabled() && val && (val != kvm_val)) {
+    if (tcg_enabled() && val) {
+        /* TCG only supports broken, allow other values and print a warning */
+        error_setg(&local_err,
+                   "TCG doesn't support requested feature, cap-ibs=%s",
+                   cap_ibs_possible.vals[val]);
+    } else if (kvm_enabled() && (val > kvm_val)) {
         error_setg(errp,
 "Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s",
                    cap_ibs_possible.vals[kvm_val]);
     }
+
+    if (local_err != NULL) {
+        warn_report_err(local_err);
+    }
 }
 
 #define VALUE_DESC_TRISTATE     " (broken, workaround, fixed)"
 
-void spapr_check_pagesize(sPAPRMachineState *spapr, hwaddr pagesize,
+void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
                           Error **errp)
 {
     hwaddr maxpagesize = (1ULL << spapr->eff.caps[SPAPR_CAP_HPT_MAXPAGESIZE]);
@@ -322,7 +337,7 @@
     }
 }
 
-static void cap_hpt_maxpagesize_apply(sPAPRMachineState *spapr,
+static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr,
                                       uint8_t val, Error **errp)
 {
     if (val < 12) {
@@ -359,7 +374,7 @@
     return true;
 }
 
-static void cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr,
+static void cap_hpt_maxpagesize_cpu_apply(SpaprMachineState *spapr,
                                           PowerPCCPU *cpu,
                                           uint8_t val, Error **errp)
 {
@@ -368,7 +383,7 @@
     ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, &maxshift);
 }
 
-static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
+static void cap_nested_kvm_hv_apply(SpaprMachineState *spapr,
                                     uint8_t val, Error **errp)
 {
     if (!val) {
@@ -390,7 +405,75 @@
     }
 }
 
-sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
+static void cap_large_decr_apply(SpaprMachineState *spapr,
+                                 uint8_t val, Error **errp)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+    if (!val) {
+        return; /* Disabled by default */
+    }
+
+    if (tcg_enabled()) {
+        if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
+                              spapr->max_compat_pvr)) {
+            error_setg(errp,
+                "Large decrementer only supported on POWER9, try -cpu POWER9");
+            return;
+        }
+    } else if (kvm_enabled()) {
+        int kvm_nr_bits = kvmppc_get_cap_large_decr();
+
+        if (!kvm_nr_bits) {
+            error_setg(errp,
+                       "No large decrementer support, try cap-large-decr=off");
+        } else if (pcc->lrg_decr_bits != kvm_nr_bits) {
+            error_setg(errp,
+"KVM large decrementer size (%d) differs to model (%d), try -cap-large-decr=off",
+                kvm_nr_bits, pcc->lrg_decr_bits);
+        }
+    }
+}
+
+static void cap_large_decr_cpu_apply(SpaprMachineState *spapr,
+                                     PowerPCCPU *cpu,
+                                     uint8_t val, Error **errp)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong lpcr = env->spr[SPR_LPCR];
+
+    if (kvm_enabled()) {
+        if (kvmppc_enable_cap_large_decr(cpu, val)) {
+            error_setg(errp,
+                       "No large decrementer support, try cap-large-decr=off");
+        }
+    }
+
+    if (val) {
+        lpcr |= LPCR_LD;
+    } else {
+        lpcr &= ~LPCR_LD;
+    }
+    ppc_store_lpcr(cpu, lpcr);
+}
+
+static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
+                                 Error **errp)
+{
+    uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist();
+
+    if (tcg_enabled() && val) {
+        /* TODO - for now only allow broken for TCG */
+        error_setg(errp,
+"Requested count cache flush assist capability level not supported by tcg, try cap-ccf-assist=off");
+    } else if (kvm_enabled() && (val > kvm_val)) {
+        error_setg(errp,
+"Requested count cache flush assist capability level not supported by kvm, try cap-ccf-assist=off");
+    }
+}
+
+SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
     [SPAPR_CAP_HTM] = {
         .name = "htm",
         .description = "Allow Hardware Transactional Memory (HTM)",
@@ -441,7 +524,8 @@
     [SPAPR_CAP_IBS] = {
         .name = "ibs",
         .description =
-            "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)",
+            "Indirect Branch Speculation (broken, workaround, fixed-ibs,"
+            "fixed-ccd, fixed-na)",
         .index = SPAPR_CAP_IBS,
         .get = spapr_cap_get_string,
         .set = spapr_cap_set_string,
@@ -468,16 +552,40 @@
         .type = "bool",
         .apply = cap_nested_kvm_hv_apply,
     },
+    [SPAPR_CAP_LARGE_DECREMENTER] = {
+        .name = "large-decr",
+        .description = "Allow Large Decrementer",
+        .index = SPAPR_CAP_LARGE_DECREMENTER,
+        .get = spapr_cap_get_bool,
+        .set = spapr_cap_set_bool,
+        .type = "bool",
+        .apply = cap_large_decr_apply,
+        .cpu_apply = cap_large_decr_cpu_apply,
+    },
+    [SPAPR_CAP_CCF_ASSIST] = {
+        .name = "ccf-assist",
+        .description = "Count Cache Flush Assist via HW Instruction",
+        .index = SPAPR_CAP_CCF_ASSIST,
+        .get = spapr_cap_get_bool,
+        .set = spapr_cap_set_bool,
+        .type = "bool",
+        .apply = cap_ccf_assist_apply,
+    },
 };
 
-static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
+static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
                                                const char *cputype)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-    sPAPRCapabilities caps;
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprCapabilities caps;
 
     caps = smc->default_caps;
 
+    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
+                               0, spapr->max_compat_pvr)) {
+        caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
+    }
+
     if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
                                0, spapr->max_compat_pvr)) {
         caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
@@ -514,7 +622,7 @@
 
 int spapr_caps_pre_load(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     /* Set to default so we can tell if this came in with the migration */
     spapr->mig = spapr->def;
@@ -523,7 +631,7 @@
 
 int spapr_caps_pre_save(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     spapr->mig = spapr->eff;
     return 0;
@@ -533,12 +641,12 @@
  * caps specific one.  Otherwise it wouldn't be called when the source
  * caps are all defaults, which could still conflict with overridden
  * caps on the destination */
-int spapr_caps_post_migration(sPAPRMachineState *spapr)
+int spapr_caps_post_migration(SpaprMachineState *spapr)
 {
     int i;
     bool ok = true;
-    sPAPRCapabilities dstcaps = spapr->eff;
-    sPAPRCapabilities srccaps;
+    SpaprCapabilities dstcaps = spapr->eff;
+    SpaprCapabilities srccaps;
 
     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
     for (i = 0; i < SPAPR_CAP_NUM; i++) {
@@ -549,7 +657,7 @@
     }
 
     for (i = 0; i < SPAPR_CAP_NUM; i++) {
-        sPAPRCapabilityInfo *info = &capability_table[i];
+        SpaprCapabilityInfo *info = &capability_table[i];
 
         if (srccaps.caps[i] > dstcaps.caps[i]) {
             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
@@ -570,7 +678,7 @@
 #define SPAPR_CAP_MIG_STATE(sname, cap)                 \
 static bool spapr_cap_##sname##_needed(void *opaque)    \
 {                                                       \
-    sPAPRMachineState *spapr = opaque;                  \
+    SpaprMachineState *spapr = opaque;                  \
                                                         \
     return spapr->cmd_line_caps[cap] &&                 \
            (spapr->eff.caps[cap] !=                     \
@@ -584,7 +692,7 @@
     .needed = spapr_cap_##sname##_needed,               \
     .fields = (VMStateField[]) {                        \
         VMSTATE_UINT8(mig.caps[cap],                    \
-                      sPAPRMachineState),               \
+                      SpaprMachineState),               \
         VMSTATE_END_OF_LIST()                           \
     },                                                  \
 }
@@ -596,10 +704,12 @@
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
+SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
+SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
 
-void spapr_caps_init(sPAPRMachineState *spapr)
+void spapr_caps_init(SpaprMachineState *spapr)
 {
-    sPAPRCapabilities default_caps;
+    SpaprCapabilities default_caps;
     int i;
 
     /* Compute the actual set of caps we should run with */
@@ -615,12 +725,12 @@
     }
 }
 
-void spapr_caps_apply(sPAPRMachineState *spapr)
+void spapr_caps_apply(SpaprMachineState *spapr)
 {
     int i;
 
     for (i = 0; i < SPAPR_CAP_NUM; i++) {
-        sPAPRCapabilityInfo *info = &capability_table[i];
+        SpaprCapabilityInfo *info = &capability_table[i];
 
         /*
          * If the apply function can't set the desired level and thinks it's
@@ -630,12 +740,12 @@
     }
 }
 
-void spapr_caps_cpu_apply(sPAPRMachineState *spapr, PowerPCCPU *cpu)
+void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu)
 {
     int i;
 
     for (i = 0; i < SPAPR_CAP_NUM; i++) {
-        sPAPRCapabilityInfo *info = &capability_table[i];
+        SpaprCapabilityInfo *info = &capability_table[i];
 
         /*
          * If the apply function can't set the desired level and thinks it's
@@ -647,14 +757,14 @@
     }
 }
 
-void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp)
+void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp)
 {
     Error *local_err = NULL;
     ObjectClass *klass = OBJECT_CLASS(smc);
     int i;
 
     for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
-        sPAPRCapabilityInfo *cap = &capability_table[i];
+        SpaprCapabilityInfo *cap = &capability_table[i];
         const char *name = g_strdup_printf("cap-%s", cap->name);
         char *desc;
 
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index ef6cbb9..f04e06c 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -28,7 +28,7 @@
     CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
     target_ulong lpcr;
 
     cpu_reset(cs);
@@ -116,7 +116,7 @@
 
 static bool slb_shadow_needed(void *opaque)
 {
-    sPAPRCPUState *spapr_cpu = opaque;
+    SpaprCpuState *spapr_cpu = opaque;
 
     return spapr_cpu->slb_shadow_addr != 0;
 }
@@ -127,15 +127,15 @@
     .minimum_version_id = 1,
     .needed = slb_shadow_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64(slb_shadow_addr, sPAPRCPUState),
-        VMSTATE_UINT64(slb_shadow_size, sPAPRCPUState),
+        VMSTATE_UINT64(slb_shadow_addr, SpaprCpuState),
+        VMSTATE_UINT64(slb_shadow_size, SpaprCpuState),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool dtl_needed(void *opaque)
 {
-    sPAPRCPUState *spapr_cpu = opaque;
+    SpaprCpuState *spapr_cpu = opaque;
 
     return spapr_cpu->dtl_addr != 0;
 }
@@ -146,15 +146,15 @@
     .minimum_version_id = 1,
     .needed = dtl_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64(dtl_addr, sPAPRCPUState),
-        VMSTATE_UINT64(dtl_size, sPAPRCPUState),
+        VMSTATE_UINT64(dtl_addr, SpaprCpuState),
+        VMSTATE_UINT64(dtl_size, SpaprCpuState),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool vpa_needed(void *opaque)
 {
-    sPAPRCPUState *spapr_cpu = opaque;
+    SpaprCpuState *spapr_cpu = opaque;
 
     return spapr_cpu->vpa_addr != 0;
 }
@@ -165,7 +165,7 @@
     .minimum_version_id = 1,
     .needed = vpa_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64(vpa_addr, sPAPRCPUState),
+        VMSTATE_UINT64(vpa_addr, SpaprCpuState),
         VMSTATE_END_OF_LIST()
     },
     .subsections = (const VMStateDescription * []) {
@@ -188,7 +188,7 @@
     }
 };
 
-static void spapr_unrealize_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
+static void spapr_unrealize_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc)
 {
     if (!sc->pre_3_0_migration) {
         vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
@@ -206,7 +206,7 @@
 
 static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp)
 {
-    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
+    SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
     CPUCore *cc = CPU_CORE(dev);
     int i;
 
@@ -216,8 +216,8 @@
     g_free(sc->threads);
 }
 
-static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr,
-                               sPAPRCPUCore *sc, Error **errp)
+static void spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
+                               SpaprCpuCore *sc, Error **errp)
 {
     CPUPPCState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
@@ -256,9 +256,9 @@
     error_propagate(errp, local_err);
 }
 
-static PowerPCCPU *spapr_create_vcpu(sPAPRCPUCore *sc, int i, Error **errp)
+static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp)
 {
-    sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(sc);
+    SpaprCpuCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(sc);
     CPUCore *cc = CPU_CORE(sc);
     Object *obj;
     char *id;
@@ -285,7 +285,7 @@
         goto err;
     }
 
-    cpu->machine_data = g_new0(sPAPRCPUState, 1);
+    cpu->machine_data = g_new0(SpaprCpuState, 1);
 
     object_unref(obj);
     return cpu;
@@ -296,9 +296,9 @@
     return NULL;
 }
 
-static void spapr_delete_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
+static void spapr_delete_vcpu(PowerPCCPU *cpu, SpaprCpuCore *sc)
 {
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 
     cpu->machine_data = NULL;
     g_free(spapr_cpu);
@@ -310,10 +310,10 @@
     /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
      * tries to add a sPAPR CPU core to a non-pseries machine.
      */
-    sPAPRMachineState *spapr =
-        (sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
+    SpaprMachineState *spapr =
+        (SpaprMachineState *) object_dynamic_cast(qdev_get_machine(),
                                                   TYPE_SPAPR_MACHINE);
-    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
+    SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
     CPUCore *cc = CPU_CORE(OBJECT(dev));
     Error *local_err = NULL;
     int i, j;
@@ -352,8 +352,8 @@
 }
 
 static Property spapr_cpu_core_properties[] = {
-    DEFINE_PROP_INT32("node-id", sPAPRCPUCore, node_id, CPU_UNSET_NUMA_NODE_ID),
-    DEFINE_PROP_BOOL("pre-3.0-migration", sPAPRCPUCore, pre_3_0_migration,
+    DEFINE_PROP_INT32("node-id", SpaprCpuCore, node_id, CPU_UNSET_NUMA_NODE_ID),
+    DEFINE_PROP_BOOL("pre-3.0-migration", SpaprCpuCore, pre_3_0_migration,
                      false),
     DEFINE_PROP_END_OF_LIST()
 };
@@ -361,7 +361,7 @@
 static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
-    sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
+    SpaprCpuCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
 
     dc->realize = spapr_cpu_core_realize;
     dc->unrealize = spapr_cpu_core_unrealize;
@@ -382,8 +382,8 @@
         .name = TYPE_SPAPR_CPU_CORE,
         .parent = TYPE_CPU_CORE,
         .abstract = true,
-        .instance_size = sizeof(sPAPRCPUCore),
-        .class_size = sizeof(sPAPRCPUCoreClass),
+        .instance_size = sizeof(SpaprCpuCore),
+        .class_size = sizeof(SpaprCpuCoreClass),
     },
     DEFINE_SPAPR_CPU_CORE_TYPE("970_v2.2"),
     DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.0"),
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 2943cf4..597f236 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -29,16 +29,16 @@
 #define DRC_INDEX_TYPE_SHIFT 28
 #define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
 
-sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc)
+SpaprDrcType spapr_drc_type(SpaprDrc *drc)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     return 1 << drck->typeshift;
 }
 
-uint32_t spapr_drc_index(sPAPRDRConnector *drc)
+uint32_t spapr_drc_index(SpaprDrc *drc)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     /* no set format for a drc index: it only needs to be globally
      * unique. this is how we encode the DRC type on bare-metal
@@ -48,7 +48,7 @@
         | (drc->id & DRC_INDEX_ID_MASK);
 }
 
-static uint32_t drc_isolate_physical(sPAPRDRConnector *drc)
+static uint32_t drc_isolate_physical(SpaprDrc *drc)
 {
     switch (drc->state) {
     case SPAPR_DRC_STATE_PHYSICAL_POWERON:
@@ -72,7 +72,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-static uint32_t drc_unisolate_physical(sPAPRDRConnector *drc)
+static uint32_t drc_unisolate_physical(SpaprDrc *drc)
 {
     switch (drc->state) {
     case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
@@ -99,7 +99,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-static uint32_t drc_isolate_logical(sPAPRDRConnector *drc)
+static uint32_t drc_isolate_logical(SpaprDrc *drc)
 {
     switch (drc->state) {
     case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
@@ -146,7 +146,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-static uint32_t drc_unisolate_logical(sPAPRDRConnector *drc)
+static uint32_t drc_unisolate_logical(SpaprDrc *drc)
 {
     switch (drc->state) {
     case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
@@ -170,7 +170,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-static uint32_t drc_set_usable(sPAPRDRConnector *drc)
+static uint32_t drc_set_usable(SpaprDrc *drc)
 {
     switch (drc->state) {
     case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
@@ -202,7 +202,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-static uint32_t drc_set_unusable(sPAPRDRConnector *drc)
+static uint32_t drc_set_unusable(SpaprDrc *drc)
 {
     switch (drc->state) {
     case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
@@ -226,9 +226,9 @@
     return RTAS_OUT_SUCCESS;
 }
 
-static const char *spapr_drc_name(sPAPRDRConnector *drc)
+static const char *spapr_drc_name(SpaprDrc *drc)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     /* human-readable name for a DRC to encode into the DT
      * description. this is mainly only used within a guest in place
@@ -261,7 +261,7 @@
  * based on the current allocation/indicator/power states
  * for the DR connector.
  */
-static sPAPRDREntitySense physical_entity_sense(sPAPRDRConnector *drc)
+static SpaprDREntitySense physical_entity_sense(SpaprDrc *drc)
 {
     /* this assumes all PCI devices are assigned to a 'live insertion'
      * power domain, where QEMU manages power state automatically as
@@ -272,7 +272,7 @@
         : SPAPR_DR_ENTITY_SENSE_EMPTY;
 }
 
-static sPAPRDREntitySense logical_entity_sense(sPAPRDRConnector *drc)
+static SpaprDREntitySense logical_entity_sense(SpaprDrc *drc)
 {
     switch (drc->state) {
     case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
@@ -290,7 +290,7 @@
 static void prop_get_index(Object *obj, Visitor *v, const char *name,
                            void *opaque, Error **errp)
 {
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj);
     uint32_t value = spapr_drc_index(drc);
     visit_type_uint32(v, name, &value, errp);
 }
@@ -298,7 +298,7 @@
 static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
 {
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj);
     QNull *null = NULL;
     Error *err = NULL;
     int fdt_offset_next, fdt_offset, fdt_depth;
@@ -374,7 +374,7 @@
     } while (fdt_depth != 0);
 }
 
-void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
+void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp)
 {
     trace_spapr_drc_attach(spapr_drc_index(drc));
 
@@ -393,9 +393,9 @@
                              NULL, 0, NULL);
 }
 
-static void spapr_drc_release(sPAPRDRConnector *drc)
+static void spapr_drc_release(SpaprDrc *drc)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     drck->release(drc->dev);
 
@@ -407,9 +407,9 @@
     drc->dev = NULL;
 }
 
-void spapr_drc_detach(sPAPRDRConnector *drc)
+void spapr_drc_detach(SpaprDrc *drc)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     trace_spapr_drc_detach(spapr_drc_index(drc));
 
@@ -425,9 +425,9 @@
     spapr_drc_release(drc);
 }
 
-void spapr_drc_reset(sPAPRDRConnector *drc)
+void spapr_drc_reset(SpaprDrc *drc)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     trace_spapr_drc_reset(spapr_drc_index(drc));
 
@@ -456,8 +456,8 @@
 
 bool spapr_drc_needed(void *opaque)
 {
-    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrc *drc = (SpaprDrc *)opaque;
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     /* If no dev is plugged in there is no need to migrate the DRC state */
     if (!drc->dev) {
@@ -477,14 +477,14 @@
     .minimum_version_id = 1,
     .needed = spapr_drc_needed,
     .fields  = (VMStateField []) {
-        VMSTATE_UINT32(state, sPAPRDRConnector),
+        VMSTATE_UINT32(state, SpaprDrc),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static void realize(DeviceState *d, Error **errp)
 {
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
     Object *root_container;
     gchar *link_name;
     gchar *child_name;
@@ -517,7 +517,7 @@
 
 static void unrealize(DeviceState *d, Error **errp)
 {
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
     Object *root_container;
     gchar *name;
 
@@ -529,10 +529,10 @@
     g_free(name);
 }
 
-sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
+SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
                                          uint32_t id)
 {
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(type));
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(object_new(type));
     char *prop_name;
 
     drc->id = id;
@@ -549,8 +549,8 @@
 
 static void spapr_dr_connector_instance_init(Object *obj)
 {
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
 
     object_property_add_uint32_ptr(obj, "id", &drc->id, NULL);
     object_property_add(obj, "index", "uint32", prop_get_index,
@@ -574,8 +574,8 @@
 
 static bool drc_physical_needed(void *opaque)
 {
-    sPAPRDRCPhysical *drcp = (sPAPRDRCPhysical *)opaque;
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(drcp);
+    SpaprDrcPhysical *drcp = (SpaprDrcPhysical *)opaque;
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(drcp);
 
     if ((drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_ACTIVE))
         || (!drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_INACTIVE))) {
@@ -590,15 +590,15 @@
     .minimum_version_id = 1,
     .needed = drc_physical_needed,
     .fields  = (VMStateField []) {
-        VMSTATE_UINT32(dr_indicator, sPAPRDRCPhysical),
+        VMSTATE_UINT32(dr_indicator, SpaprDrcPhysical),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static void drc_physical_reset(void *opaque)
 {
-    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(opaque);
-    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(drc);
+    SpaprDrc *drc = SPAPR_DR_CONNECTOR(opaque);
+    SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(drc);
 
     if (drc->dev) {
         drcp->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE;
@@ -609,7 +609,7 @@
 
 static void realize_physical(DeviceState *d, Error **errp)
 {
-    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
+    SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
     Error *local_err = NULL;
 
     realize(d, &local_err);
@@ -625,7 +625,7 @@
 
 static void unrealize_physical(DeviceState *d, Error **errp)
 {
-    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
+    SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
     Error *local_err = NULL;
 
     unrealize(d, &local_err);
@@ -641,7 +641,7 @@
 static void spapr_drc_physical_class_init(ObjectClass *k, void *data)
 {
     DeviceClass *dk = DEVICE_CLASS(k);
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
 
     dk->realize = realize_physical;
     dk->unrealize = unrealize_physical;
@@ -654,7 +654,7 @@
 
 static void spapr_drc_logical_class_init(ObjectClass *k, void *data)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
 
     drck->dr_entity_sense = logical_entity_sense;
     drck->isolate = drc_isolate_logical;
@@ -665,7 +665,7 @@
 
 static void spapr_drc_cpu_class_init(ObjectClass *k, void *data)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
 
     drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU;
     drck->typename = "CPU";
@@ -676,7 +676,7 @@
 
 static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
 
     drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI;
     drck->typename = "28";
@@ -687,7 +687,7 @@
 
 static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
 
     drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB;
     drck->typename = "MEM";
@@ -698,7 +698,7 @@
 
 static void spapr_drc_phb_class_init(ObjectClass *k, void *data)
 {
-    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
+    SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
 
     drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB;
     drck->typename = "PHB";
@@ -710,9 +710,9 @@
 static const TypeInfo spapr_dr_connector_info = {
     .name          = TYPE_SPAPR_DR_CONNECTOR,
     .parent        = TYPE_DEVICE,
-    .instance_size = sizeof(sPAPRDRConnector),
+    .instance_size = sizeof(SpaprDrc),
     .instance_init = spapr_dr_connector_instance_init,
-    .class_size    = sizeof(sPAPRDRConnectorClass),
+    .class_size    = sizeof(SpaprDrcClass),
     .class_init    = spapr_dr_connector_class_init,
     .abstract      = true,
 };
@@ -720,7 +720,7 @@
 static const TypeInfo spapr_drc_physical_info = {
     .name          = TYPE_SPAPR_DRC_PHYSICAL,
     .parent        = TYPE_SPAPR_DR_CONNECTOR,
-    .instance_size = sizeof(sPAPRDRCPhysical),
+    .instance_size = sizeof(SpaprDrcPhysical),
     .class_init    = spapr_drc_physical_class_init,
     .abstract      = true,
 };
@@ -753,13 +753,13 @@
 static const TypeInfo spapr_drc_phb_info = {
     .name          = TYPE_SPAPR_DRC_PHB,
     .parent        = TYPE_SPAPR_DRC_LOGICAL,
-    .instance_size = sizeof(sPAPRDRConnector),
+    .instance_size = sizeof(SpaprDrc),
     .class_init    = spapr_drc_phb_class_init,
 };
 
 /* helper functions for external users */
 
-sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
+SpaprDrc *spapr_drc_by_index(uint32_t index)
 {
     Object *obj;
     gchar *name;
@@ -771,9 +771,9 @@
     return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
 }
 
-sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id)
+SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id)
 {
-    sPAPRDRConnectorClass *drck
+    SpaprDrcClass *drck
         = SPAPR_DR_CONNECTOR_CLASS(object_class_by_name(type));
 
     return spapr_drc_by_index(drck->typeshift << DRC_INDEX_TYPE_SHIFT
@@ -787,7 +787,7 @@
  * @path: path in the DT to generate properties
  * @owner: parent Object/DeviceState for which to generate DRC
  *         descriptions for
- * @drc_type_mask: mask of sPAPRDRConnectorType values corresponding
+ * @drc_type_mask: mask of SpaprDrcType values corresponding
  *   to the types of DRCs to generate entries for
  *
  * generate OF properties to describe DRC topology/indices to guests
@@ -826,8 +826,8 @@
     object_property_iter_init(&iter, root_container);
     while ((prop = object_property_iter_next(&iter))) {
         Object *obj;
-        sPAPRDRConnector *drc;
-        sPAPRDRConnectorClass *drck;
+        SpaprDrc *drc;
+        SpaprDrcClass *drck;
         uint32_t drc_index, drc_power_domain;
 
         if (!strstart(prop->type, "link<", NULL)) {
@@ -918,8 +918,8 @@
 
 static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state)
 {
-    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
-    sPAPRDRConnectorClass *drck;
+    SpaprDrc *drc = spapr_drc_by_index(idx);
+    SpaprDrcClass *drck;
 
     if (!drc) {
         return RTAS_OUT_NO_SUCH_INDICATOR;
@@ -943,7 +943,7 @@
 
 static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state)
 {
-    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
+    SpaprDrc *drc = spapr_drc_by_index(idx);
 
     if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_LOGICAL)) {
         return RTAS_OUT_NO_SUCH_INDICATOR;
@@ -965,7 +965,7 @@
 
 static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state)
 {
-    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
+    SpaprDrc *drc = spapr_drc_by_index(idx);
 
     if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_PHYSICAL)) {
         return RTAS_OUT_NO_SUCH_INDICATOR;
@@ -982,7 +982,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_set_indicator(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                uint32_t token,
                                uint32_t nargs, target_ulong args,
                                uint32_t nret, target_ulong rets)
@@ -1017,7 +1017,7 @@
     rtas_st(rets, 0, ret);
 }
 
-static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_get_sensor_state(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                   uint32_t token, uint32_t nargs,
                                   target_ulong args, uint32_t nret,
                                   target_ulong rets)
@@ -1025,8 +1025,8 @@
     uint32_t sensor_type;
     uint32_t sensor_index;
     uint32_t sensor_state = 0;
-    sPAPRDRConnector *drc;
-    sPAPRDRConnectorClass *drck;
+    SpaprDrc *drc;
+    SpaprDrcClass *drck;
     uint32_t ret = RTAS_OUT_SUCCESS;
 
     if (nargs != 2 || nret != 2) {
@@ -1079,7 +1079,7 @@
 }
 
 static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
-                                         sPAPRMachineState *spapr,
+                                         SpaprMachineState *spapr,
                                          uint32_t token, uint32_t nargs,
                                          target_ulong args, uint32_t nret,
                                          target_ulong rets)
@@ -1087,9 +1087,9 @@
     uint64_t wa_addr;
     uint64_t wa_offset;
     uint32_t drc_index;
-    sPAPRDRConnector *drc;
-    sPAPRDRConnectorClass *drck;
-    sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
+    SpaprDrc *drc;
+    SpaprDrcClass *drck;
+    SpaprDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
     int rc;
 
     if (nargs != 2 || nret != 1) {
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index ab9a1f0..ae0f093 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -229,18 +229,18 @@
     [EVENT_CLASS_IO]                    = "ibm,io-events",
 };
 
-struct sPAPREventSource {
+struct SpaprEventSource {
     int irq;
     uint32_t mask;
     bool enabled;
 };
 
-static sPAPREventSource *spapr_event_sources_new(void)
+static SpaprEventSource *spapr_event_sources_new(void)
 {
-    return g_new0(sPAPREventSource, EVENT_CLASS_MAX);
+    return g_new0(SpaprEventSource, EVENT_CLASS_MAX);
 }
 
-static void spapr_event_sources_register(sPAPREventSource *event_sources,
+static void spapr_event_sources_register(SpaprEventSource *event_sources,
                                         EventClassIndex index, int irq)
 {
     /* we only support 1 irq per event class at the moment */
@@ -251,8 +251,8 @@
     event_sources[index].enabled = true;
 }
 
-static const sPAPREventSource *
-spapr_event_sources_get_source(sPAPREventSource *event_sources,
+static const SpaprEventSource *
+spapr_event_sources_get_source(SpaprEventSource *event_sources,
                                EventClassIndex index)
 {
     g_assert(index < EVENT_CLASS_MAX);
@@ -261,11 +261,11 @@
     return &event_sources[index];
 }
 
-void spapr_dt_events(sPAPRMachineState *spapr, void *fdt)
+void spapr_dt_events(SpaprMachineState *spapr, void *fdt)
 {
     uint32_t irq_ranges[EVENT_CLASS_MAX * 2];
     int i, count = 0, event_sources;
-    sPAPREventSource *events = spapr->event_sources;
+    SpaprEventSource *events = spapr->event_sources;
 
     g_assert(events);
 
@@ -274,7 +274,7 @@
     for (i = 0, count = 0; i < EVENT_CLASS_MAX; i++) {
         int node_offset;
         uint32_t interrupts[2];
-        const sPAPREventSource *source =
+        const SpaprEventSource *source =
             spapr_event_sources_get_source(events, i);
         const char *source_name = event_names[i];
 
@@ -298,10 +298,10 @@
                       irq_ranges, count * sizeof(uint32_t))));
 }
 
-static const sPAPREventSource *
-rtas_event_log_to_source(sPAPRMachineState *spapr, int log_type)
+static const SpaprEventSource *
+rtas_event_log_to_source(SpaprMachineState *spapr, int log_type)
 {
-    const sPAPREventSource *source;
+    const SpaprEventSource *source;
 
     g_assert(spapr->event_sources);
 
@@ -325,9 +325,9 @@
     return source;
 }
 
-static int rtas_event_log_to_irq(sPAPRMachineState *spapr, int log_type)
+static int rtas_event_log_to_irq(SpaprMachineState *spapr, int log_type)
 {
-    const sPAPREventSource *source;
+    const SpaprEventSource *source;
 
     source = rtas_event_log_to_source(spapr, log_type);
     g_assert(source);
@@ -336,24 +336,24 @@
     return source->irq;
 }
 
-static uint32_t spapr_event_log_entry_type(sPAPREventLogEntry *entry)
+static uint32_t spapr_event_log_entry_type(SpaprEventLogEntry *entry)
 {
     return entry->summary & RTAS_LOG_TYPE_MASK;
 }
 
-static void rtas_event_log_queue(sPAPRMachineState *spapr,
-                                 sPAPREventLogEntry *entry)
+static void rtas_event_log_queue(SpaprMachineState *spapr,
+                                 SpaprEventLogEntry *entry)
 {
     QTAILQ_INSERT_TAIL(&spapr->pending_events, entry, next);
 }
 
-static sPAPREventLogEntry *rtas_event_log_dequeue(sPAPRMachineState *spapr,
+static SpaprEventLogEntry *rtas_event_log_dequeue(SpaprMachineState *spapr,
                                                   uint32_t event_mask)
 {
-    sPAPREventLogEntry *entry = NULL;
+    SpaprEventLogEntry *entry = NULL;
 
     QTAILQ_FOREACH(entry, &spapr->pending_events, next) {
-        const sPAPREventSource *source =
+        const SpaprEventSource *source =
             rtas_event_log_to_source(spapr,
                                      spapr_event_log_entry_type(entry));
 
@@ -371,11 +371,11 @@
 
 static bool rtas_event_log_contains(uint32_t event_mask)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
-    sPAPREventLogEntry *entry = NULL;
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprEventLogEntry *entry = NULL;
 
     QTAILQ_FOREACH(entry, &spapr->pending_events, next) {
-        const sPAPREventSource *source =
+        const SpaprEventSource *source =
             rtas_event_log_to_source(spapr,
                                      spapr_event_log_entry_type(entry));
 
@@ -401,7 +401,7 @@
 static void spapr_init_maina(struct rtas_event_log_v6_maina *maina,
                              int section_count)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
     struct tm tm;
     int year;
 
@@ -424,15 +424,15 @@
 
 static void spapr_powerdown_req(Notifier *n, void *opaque)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
-    sPAPREventLogEntry *entry;
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprEventLogEntry *entry;
     struct rtas_event_log_v6 *v6hdr;
     struct rtas_event_log_v6_maina *maina;
     struct rtas_event_log_v6_mainb *mainb;
     struct rtas_event_log_v6_epow *epow;
     struct epow_extended_log *new_epow;
 
-    entry = g_new(sPAPREventLogEntry, 1);
+    entry = g_new(SpaprEventLogEntry, 1);
     new_epow = g_malloc0(sizeof(*new_epow));
     entry->extended_log = new_epow;
 
@@ -473,18 +473,18 @@
 }
 
 static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
-                                    sPAPRDRConnectorType drc_type,
+                                    SpaprDrcType drc_type,
                                     union drc_identifier *drc_id)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
-    sPAPREventLogEntry *entry;
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprEventLogEntry *entry;
     struct hp_extended_log *new_hp;
     struct rtas_event_log_v6 *v6hdr;
     struct rtas_event_log_v6_maina *maina;
     struct rtas_event_log_v6_mainb *mainb;
     struct rtas_event_log_v6_hp *hp;
 
-    entry = g_new(sPAPREventLogEntry, 1);
+    entry = g_new(SpaprEventLogEntry, 1);
     new_hp = g_malloc0(sizeof(struct hp_extended_log));
     entry->extended_log = new_hp;
 
@@ -558,9 +558,9 @@
                    rtas_event_log_to_irq(spapr, RTAS_LOG_TYPE_HOTPLUG)));
 }
 
-void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc)
+void spapr_hotplug_req_add_by_index(SpaprDrc *drc)
 {
-    sPAPRDRConnectorType drc_type = spapr_drc_type(drc);
+    SpaprDrcType drc_type = spapr_drc_type(drc);
     union drc_identifier drc_id;
 
     drc_id.index = spapr_drc_index(drc);
@@ -568,9 +568,9 @@
                             RTAS_LOG_V6_HP_ACTION_ADD, drc_type, &drc_id);
 }
 
-void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc)
+void spapr_hotplug_req_remove_by_index(SpaprDrc *drc)
 {
-    sPAPRDRConnectorType drc_type = spapr_drc_type(drc);
+    SpaprDrcType drc_type = spapr_drc_type(drc);
     union drc_identifier drc_id;
 
     drc_id.index = spapr_drc_index(drc);
@@ -578,7 +578,7 @@
                             RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, &drc_id);
 }
 
-void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_add_by_count(SpaprDrcType drc_type,
                                        uint32_t count)
 {
     union drc_identifier drc_id;
@@ -588,7 +588,7 @@
                             RTAS_LOG_V6_HP_ACTION_ADD, drc_type, &drc_id);
 }
 
-void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_remove_by_count(SpaprDrcType drc_type,
                                           uint32_t count)
 {
     union drc_identifier drc_id;
@@ -598,7 +598,7 @@
                             RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, &drc_id);
 }
 
-void spapr_hotplug_req_add_by_count_indexed(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_add_by_count_indexed(SpaprDrcType drc_type,
                                             uint32_t count, uint32_t index)
 {
     union drc_identifier drc_id;
@@ -609,7 +609,7 @@
                             RTAS_LOG_V6_HP_ACTION_ADD, drc_type, &drc_id);
 }
 
-void spapr_hotplug_req_remove_by_count_indexed(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_remove_by_count_indexed(SpaprDrcType drc_type,
                                                uint32_t count, uint32_t index)
 {
     union drc_identifier drc_id;
@@ -620,14 +620,14 @@
                             RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, &drc_id);
 }
 
-static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void check_exception(PowerPCCPU *cpu, SpaprMachineState *spapr,
                             uint32_t token, uint32_t nargs,
                             target_ulong args,
                             uint32_t nret, target_ulong rets)
 {
     uint32_t mask, buf, len, event_len;
     uint64_t xinfo;
-    sPAPREventLogEntry *event;
+    SpaprEventLogEntry *event;
     struct rtas_error_log header;
     int i;
 
@@ -671,7 +671,7 @@
      */
     for (i = 0; i < EVENT_CLASS_MAX; i++) {
         if (rtas_event_log_contains(EVENT_CLASS_MASK(i))) {
-            const sPAPREventSource *source =
+            const SpaprEventSource *source =
                 spapr_event_sources_get_source(spapr->event_sources, i);
 
             g_assert(source->enabled);
@@ -685,7 +685,7 @@
     rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
 }
 
-static void event_scan(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void event_scan(PowerPCCPU *cpu, SpaprMachineState *spapr,
                        uint32_t token, uint32_t nargs,
                        target_ulong args,
                        uint32_t nret, target_ulong rets)
@@ -697,9 +697,9 @@
     rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
 }
 
-void spapr_clear_pending_events(sPAPRMachineState *spapr)
+void spapr_clear_pending_events(SpaprMachineState *spapr)
 {
-    sPAPREventLogEntry *entry = NULL, *next_entry;
+    SpaprEventLogEntry *entry = NULL, *next_entry;
 
     QTAILQ_FOREACH_SAFE(entry, &spapr->pending_events, next, next_entry) {
         QTAILQ_REMOVE(&spapr->pending_events, entry, next);
@@ -708,7 +708,7 @@
     }
 }
 
-void spapr_events_init(sPAPRMachineState *spapr)
+void spapr_events_init(SpaprMachineState *spapr)
 {
     int epow_irq = SPAPR_IRQ_EPOW;
 
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 476bad6..0761e10 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -34,7 +34,7 @@
     return true;
 }
 
-static bool is_ram_address(sPAPRMachineState *spapr, hwaddr addr)
+static bool is_ram_address(SpaprMachineState *spapr, hwaddr addr)
 {
     MachineState *machine = MACHINE(spapr);
     DeviceMemoryState *dms = machine->device_memory;
@@ -50,7 +50,7 @@
     return false;
 }
 
-static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_enter(PowerPCCPU *cpu, SpaprMachineState *spapr,
                             target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
@@ -160,7 +160,7 @@
     return REMOVE_SUCCESS;
 }
 
-static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_remove(PowerPCCPU *cpu, SpaprMachineState *spapr,
                              target_ulong opcode, target_ulong *args)
 {
     CPUPPCState *env = &cpu->env;
@@ -208,7 +208,7 @@
 
 #define H_BULK_REMOVE_MAX_BATCH        4
 
-static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_bulk_remove(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                   target_ulong opcode, target_ulong *args)
 {
     CPUPPCState *env = &cpu->env;
@@ -260,7 +260,7 @@
     return rc;
 }
 
-static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_protect(PowerPCCPU *cpu, SpaprMachineState *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     CPUPPCState *env = &cpu->env;
@@ -299,7 +299,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_read(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_read(PowerPCCPU *cpu, SpaprMachineState *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
@@ -328,7 +328,7 @@
     return H_SUCCESS;
 }
 
-struct sPAPRPendingHPT {
+struct SpaprPendingHpt {
     /* These fields are read-only after initialization */
     int shift;
     QemuThread thread;
@@ -342,7 +342,7 @@
     void *hpt;
 };
 
-static void free_pending_hpt(sPAPRPendingHPT *pending)
+static void free_pending_hpt(SpaprPendingHpt *pending)
 {
     if (pending->hpt) {
         qemu_vfree(pending->hpt);
@@ -353,7 +353,7 @@
 
 static void *hpt_prepare_thread(void *opaque)
 {
-    sPAPRPendingHPT *pending = opaque;
+    SpaprPendingHpt *pending = opaque;
     size_t size = 1ULL << pending->shift;
 
     pending->hpt = qemu_memalign(size, size);
@@ -379,9 +379,9 @@
 }
 
 /* Must be called with BQL held */
-static void cancel_hpt_prepare(sPAPRMachineState *spapr)
+static void cancel_hpt_prepare(SpaprMachineState *spapr)
 {
-    sPAPRPendingHPT *pending = spapr->pending_hpt;
+    SpaprPendingHpt *pending = spapr->pending_hpt;
 
     /* Let the thread know it's cancelled */
     spapr->pending_hpt = NULL;
@@ -438,13 +438,13 @@
 }
 
 static target_ulong h_resize_hpt_prepare(PowerPCCPU *cpu,
-                                         sPAPRMachineState *spapr,
+                                         SpaprMachineState *spapr,
                                          target_ulong opcode,
                                          target_ulong *args)
 {
     target_ulong flags = args[0];
     int shift = args[1];
-    sPAPRPendingHPT *pending = spapr->pending_hpt;
+    SpaprPendingHpt *pending = spapr->pending_hpt;
     uint64_t current_ram_size;
     int rc;
 
@@ -503,7 +503,7 @@
 
     /* start new prepare */
 
-    pending = g_new0(sPAPRPendingHPT, 1);
+    pending = g_new0(SpaprPendingHpt, 1);
     pending->shift = shift;
     pending->ret = H_HARDWARE;
 
@@ -672,7 +672,7 @@
     }
 }
 
-static void push_sregs_to_kvm_pr(sPAPRMachineState *spapr)
+static void push_sregs_to_kvm_pr(SpaprMachineState *spapr)
 {
     CPUState *cs;
 
@@ -691,13 +691,13 @@
 }
 
 static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu,
-                                        sPAPRMachineState *spapr,
+                                        SpaprMachineState *spapr,
                                         target_ulong opcode,
                                         target_ulong *args)
 {
     target_ulong flags = args[0];
     target_ulong shift = args[1];
-    sPAPRPendingHPT *pending = spapr->pending_hpt;
+    SpaprPendingHpt *pending = spapr->pending_hpt;
     int rc;
     size_t newsize;
 
@@ -759,7 +759,7 @@
     return rc;
 }
 
-static target_ulong h_set_sprg0(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_set_sprg0(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 target_ulong opcode, target_ulong *args)
 {
     cpu_synchronize_state(CPU(cpu));
@@ -768,7 +768,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_set_dabr(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                target_ulong opcode, target_ulong *args)
 {
     if (!has_spr(cpu, SPR_DABR)) {
@@ -786,7 +786,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_set_xdabr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_set_xdabr(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 target_ulong opcode, target_ulong *args)
 {
     target_ulong dabrx = args[1];
@@ -807,7 +807,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_page_init(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_page_init(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
@@ -882,7 +882,7 @@
 {
     CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
     uint16_t size;
     uint8_t tmp;
 
@@ -918,7 +918,7 @@
 
 static target_ulong deregister_vpa(PowerPCCPU *cpu, target_ulong vpa)
 {
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 
     if (spapr_cpu->slb_shadow_addr) {
         return H_RESOURCE;
@@ -934,7 +934,7 @@
 
 static target_ulong register_slb_shadow(PowerPCCPU *cpu, target_ulong addr)
 {
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
     uint32_t size;
 
     if (addr == 0) {
@@ -963,7 +963,7 @@
 
 static target_ulong deregister_slb_shadow(PowerPCCPU *cpu, target_ulong addr)
 {
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 
     spapr_cpu->slb_shadow_addr = 0;
     spapr_cpu->slb_shadow_size = 0;
@@ -972,7 +972,7 @@
 
 static target_ulong register_dtl(PowerPCCPU *cpu, target_ulong addr)
 {
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
     uint32_t size;
 
     if (addr == 0) {
@@ -998,7 +998,7 @@
 
 static target_ulong deregister_dtl(PowerPCCPU *cpu, target_ulong addr)
 {
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 
     spapr_cpu->dtl_addr = 0;
     spapr_cpu->dtl_size = 0;
@@ -1006,7 +1006,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_register_vpa(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     target_ulong flags = args[0];
@@ -1049,7 +1049,7 @@
     return ret;
 }
 
-static target_ulong h_cede(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_cede(PowerPCCPU *cpu, SpaprMachineState *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     CPUPPCState *env = &cpu->env;
@@ -1065,7 +1065,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_rtas(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_rtas(PowerPCCPU *cpu, SpaprMachineState *spapr,
                            target_ulong opcode, target_ulong *args)
 {
     target_ulong rtas_r3 = args[0];
@@ -1077,7 +1077,7 @@
                            nret, rtas_r3 + 12 + 4*nargs);
 }
 
-static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_logical_load(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     CPUState *cs = CPU(cpu);
@@ -1101,7 +1101,7 @@
     return H_PARAMETER;
 }
 
-static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_logical_store(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
     CPUState *cs = CPU(cpu);
@@ -1127,7 +1127,7 @@
     return H_PARAMETER;
 }
 
-static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_logical_memop(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                     target_ulong opcode, target_ulong *args)
 {
     CPUState *cs = CPU(cpu);
@@ -1196,14 +1196,14 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_logical_icbi(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     /* Nothing to do on emulation, KVM will trap this in the kernel */
     return H_SUCCESS;
 }
 
-static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_logical_dcbf(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                    target_ulong opcode, target_ulong *args)
 {
     /* Nothing to do on emulation, KVM will trap this in the kernel */
@@ -1263,7 +1263,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_set_mode(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                target_ulong opcode, target_ulong *args)
 {
     target_ulong resource = args[1];
@@ -1282,7 +1282,7 @@
     return ret;
 }
 
-static target_ulong h_clean_slb(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_clean_slb(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 target_ulong opcode, target_ulong *args)
 {
     qemu_log_mask(LOG_UNIMP, "Unimplemented SPAPR hcall 0x"TARGET_FMT_lx"%s\n",
@@ -1290,7 +1290,7 @@
     return H_FUNCTION;
 }
 
-static target_ulong h_invalidate_pid(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_invalidate_pid(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                      target_ulong opcode, target_ulong *args)
 {
     qemu_log_mask(LOG_UNIMP, "Unimplemented SPAPR hcall 0x"TARGET_FMT_lx"%s\n",
@@ -1298,7 +1298,7 @@
     return H_FUNCTION;
 }
 
-static void spapr_check_setup_free_hpt(sPAPRMachineState *spapr,
+static void spapr_check_setup_free_hpt(SpaprMachineState *spapr,
                                        uint64_t patbe_old, uint64_t patbe_new)
 {
     /*
@@ -1331,7 +1331,7 @@
 #define FLAG_GTSE               0x01
 
 static target_ulong h_register_process_table(PowerPCCPU *cpu,
-                                             sPAPRMachineState *spapr,
+                                             SpaprMachineState *spapr,
                                              target_ulong opcode,
                                              target_ulong *args)
 {
@@ -1339,6 +1339,7 @@
     target_ulong proc_tbl = args[1];
     target_ulong page_size = args[2];
     target_ulong table_size = args[3];
+    target_ulong update_lpcr = 0;
     uint64_t cproc;
 
     if (flags & ~FLAGS_MASK) { /* Check no reserved bits are set */
@@ -1394,10 +1395,13 @@
     spapr->patb_entry = cproc; /* Save new process table */
 
     /* Update the UPRT, HR and GTSE bits in the LPCR for all cpus */
-    spapr_set_all_lpcrs(((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ?
-                         (LPCR_UPRT | LPCR_HR) : 0) |
-                        ((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
-                        LPCR_UPRT | LPCR_HR | LPCR_GTSE);
+    if (flags & FLAG_RADIX)     /* Radix must use process tables, also set HR */
+        update_lpcr |= (LPCR_UPRT | LPCR_HR);
+    else if (flags & FLAG_HASH_PROC_TBL) /* Hash with process tables */
+        update_lpcr |= LPCR_UPRT;
+    if (flags & FLAG_GTSE)      /* Guest translation shootdown enable */
+        update_lpcr |= FLAG_GTSE;
+    spapr_set_all_lpcrs(update_lpcr, LPCR_UPRT | LPCR_HR | LPCR_GTSE);
 
     if (kvm_enabled()) {
         return kvmppc_configure_v3_mmu(cpu, flags & FLAG_RADIX,
@@ -1410,7 +1414,7 @@
 #define H_SIGNAL_SYS_RESET_ALLBUTSELF  -2
 
 static target_ulong h_signal_sys_reset(PowerPCCPU *cpu,
-                                       sPAPRMachineState *spapr,
+                                       SpaprMachineState *spapr,
                                        target_ulong opcode, target_ulong *args)
 {
     target_long target = args[0];
@@ -1445,7 +1449,7 @@
     }
 }
 
-static uint32_t cas_check_pvr(sPAPRMachineState *spapr, PowerPCCPU *cpu,
+static uint32_t cas_check_pvr(SpaprMachineState *spapr, PowerPCCPU *cpu,
                               target_ulong *addr, bool *raw_mode_supported,
                               Error **errp)
 {
@@ -1496,7 +1500,7 @@
 }
 
 static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
-                                                  sPAPRMachineState *spapr,
+                                                  SpaprMachineState *spapr,
                                                   target_ulong opcode,
                                                   target_ulong *args)
 {
@@ -1504,7 +1508,7 @@
     target_ulong addr = ppc64_phys_to_real(args[0]);
     target_ulong ov_table;
     uint32_t cas_pvr;
-    sPAPROptionVector *ov1_guest, *ov5_guest, *ov5_cas_old, *ov5_updates;
+    SpaprOptionVector *ov1_guest, *ov5_guest, *ov5_cas_old, *ov5_updates;
     bool guest_radix;
     Error *local_err = NULL;
     bool raw_mode_supported = false;
@@ -1647,7 +1651,7 @@
 }
 
 static target_ulong h_home_node_associativity(PowerPCCPU *cpu,
-                                              sPAPRMachineState *spapr,
+                                              SpaprMachineState *spapr,
                                               target_ulong opcode,
                                               target_ulong *args)
 {
@@ -1683,7 +1687,7 @@
 }
 
 static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
-                                              sPAPRMachineState *spapr,
+                                              SpaprMachineState *spapr,
                                               target_ulong opcode,
                                               target_ulong *args)
 {
@@ -1693,6 +1697,8 @@
     uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC);
     uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC);
     uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS);
+    uint8_t count_cache_flush_assist = spapr_get_cap(spapr,
+                                                     SPAPR_CAP_CCF_ASSIST);
 
     switch (safe_cache) {
     case SPAPR_CAP_WORKAROUND:
@@ -1723,12 +1729,20 @@
     }
 
     switch (safe_indirect_branch) {
+    case SPAPR_CAP_FIXED_NA:
+        break;
     case SPAPR_CAP_FIXED_CCD:
         characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS;
         break;
     case SPAPR_CAP_FIXED_IBS:
         characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
         break;
+    case SPAPR_CAP_WORKAROUND:
+        behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE;
+        if (count_cache_flush_assist) {
+            characteristics |= H_CPU_CHAR_BCCTR_FLUSH_ASSIST;
+        }
+        break;
     default: /* broken */
         assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
         break;
@@ -1739,13 +1753,13 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_update_dt(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_update_dt(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 target_ulong opcode, target_ulong *args)
 {
     target_ulong dt = ppc64_phys_to_real(args[0]);
     struct fdt_header hdr = { 0 };
     unsigned cb;
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     void *fdt;
 
     cpu_physical_memory_read(dt, &hdr, sizeof(hdr));
@@ -1804,7 +1818,7 @@
 target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
                              target_ulong *args)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
 
     if ((opcode <= MAX_HCALL_OPCODE)
         && ((opcode & 0x3) == 0)) {
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 37e98f9..5aff4d5 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -32,7 +32,7 @@
 
 #include <libfdt.h>
 
-enum sPAPRTCEAccess {
+enum SpaprTceAccess {
     SPAPR_TCE_FAULT = 0,
     SPAPR_TCE_RO = 1,
     SPAPR_TCE_WO = 2,
@@ -42,11 +42,11 @@
 #define IOMMU_PAGE_SIZE(shift)      (1ULL << (shift))
 #define IOMMU_PAGE_MASK(shift)      (~(IOMMU_PAGE_SIZE(shift) - 1))
 
-static QLIST_HEAD(, sPAPRTCETable) spapr_tce_tables;
+static QLIST_HEAD(, SpaprTceTable) spapr_tce_tables;
 
-sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn)
+SpaprTceTable *spapr_tce_find_by_liobn(target_ulong liobn)
 {
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
 
     if (liobn & 0xFFFFFFFF00000000ULL) {
         hcall_dprintf("Request for out-of-bounds LIOBN 0x" TARGET_FMT_lx "\n",
@@ -115,7 +115,7 @@
                                                IOMMUAccessFlags flag,
                                                int iommu_idx)
 {
-    sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
+    SpaprTceTable *tcet = container_of(iommu, SpaprTceTable, iommu);
     uint64_t tce;
     IOMMUTLBEntry ret = {
         .target_as = &address_space_memory,
@@ -141,9 +141,39 @@
     return ret;
 }
 
+static void spapr_tce_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
+{
+    MemoryRegion *mr = MEMORY_REGION(iommu_mr);
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
+    hwaddr addr, granularity;
+    IOMMUTLBEntry iotlb;
+    SpaprTceTable *tcet = container_of(iommu_mr, SpaprTceTable, iommu);
+
+    if (tcet->skipping_replay) {
+        return;
+    }
+
+    granularity = memory_region_iommu_get_min_page_size(iommu_mr);
+
+    for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
+        iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, n->iommu_idx);
+        if (iotlb.perm != IOMMU_NONE) {
+            n->notify(n, &iotlb);
+        }
+
+        /*
+         * if (2^64 - MR size) < granularity, it's possible to get an
+         * infinite loop here.  This should catch such a wraparound.
+         */
+        if ((addr + granularity) < addr) {
+            break;
+        }
+    }
+}
+
 static int spapr_tce_table_pre_save(void *opaque)
 {
-    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
+    SpaprTceTable *tcet = SPAPR_TCE_TABLE(opaque);
 
     tcet->mig_table = tcet->table;
     tcet->mig_nb_table = tcet->nb_table;
@@ -156,7 +186,7 @@
 
 static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu)
 {
-    sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
+    SpaprTceTable *tcet = container_of(iommu, SpaprTceTable, iommu);
 
     return 1ULL << tcet->page_shift;
 }
@@ -164,7 +194,7 @@
 static int spapr_tce_get_attr(IOMMUMemoryRegion *iommu,
                               enum IOMMUMemoryRegionAttr attr, void *data)
 {
-    sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
+    SpaprTceTable *tcet = container_of(iommu, SpaprTceTable, iommu);
 
     if (attr == IOMMU_ATTR_SPAPR_TCE_FD && kvmppc_has_cap_spapr_vfio()) {
         *(int *) data = tcet->fd;
@@ -178,7 +208,7 @@
                                           IOMMUNotifierFlag old,
                                           IOMMUNotifierFlag new)
 {
-    struct sPAPRTCETable *tbl = container_of(iommu, sPAPRTCETable, iommu);
+    struct SpaprTceTable *tbl = container_of(iommu, SpaprTceTable, iommu);
 
     if (old == IOMMU_NOTIFIER_NONE && new != IOMMU_NOTIFIER_NONE) {
         spapr_tce_set_need_vfio(tbl, true);
@@ -189,7 +219,7 @@
 
 static int spapr_tce_table_post_load(void *opaque, int version_id)
 {
-    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
+    SpaprTceTable *tcet = SPAPR_TCE_TABLE(opaque);
     uint32_t old_nb_table = tcet->nb_table;
     uint64_t old_bus_offset = tcet->bus_offset;
     uint32_t old_page_shift = tcet->page_shift;
@@ -223,7 +253,7 @@
 
 static bool spapr_tce_table_ex_needed(void *opaque)
 {
-    sPAPRTCETable *tcet = opaque;
+    SpaprTceTable *tcet = opaque;
 
     return tcet->bus_offset || tcet->page_shift != 0xC;
 }
@@ -234,8 +264,8 @@
     .minimum_version_id = 1,
     .needed = spapr_tce_table_ex_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64(bus_offset, sPAPRTCETable),
-        VMSTATE_UINT32(page_shift, sPAPRTCETable),
+        VMSTATE_UINT64(bus_offset, SpaprTceTable),
+        VMSTATE_UINT32(page_shift, SpaprTceTable),
         VMSTATE_END_OF_LIST()
     },
 };
@@ -248,12 +278,12 @@
     .post_load = spapr_tce_table_post_load,
     .fields      = (VMStateField []) {
         /* Sanity check */
-        VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable, NULL),
+        VMSTATE_UINT32_EQUAL(liobn, SpaprTceTable, NULL),
 
         /* IOMMU state */
-        VMSTATE_UINT32(mig_nb_table, sPAPRTCETable),
-        VMSTATE_BOOL(bypass, sPAPRTCETable),
-        VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, mig_nb_table, 0,
+        VMSTATE_UINT32(mig_nb_table, SpaprTceTable),
+        VMSTATE_BOOL(bypass, SpaprTceTable),
+        VMSTATE_VARRAY_UINT32_ALLOC(mig_table, SpaprTceTable, mig_nb_table, 0,
                                     vmstate_info_uint64, uint64_t),
 
         VMSTATE_END_OF_LIST()
@@ -266,7 +296,7 @@
 
 static void spapr_tce_table_realize(DeviceState *dev, Error **errp)
 {
-    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
+    SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev);
     Object *tcetobj = OBJECT(tcet);
     gchar *tmp;
 
@@ -288,7 +318,7 @@
                      tcet);
 }
 
-void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio)
+void spapr_tce_set_need_vfio(SpaprTceTable *tcet, bool need_vfio)
 {
     size_t table_size = tcet->nb_table * sizeof(uint64_t);
     uint64_t *oldtable;
@@ -317,9 +347,9 @@
     tcet->fd = newfd;
 }
 
-sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
+SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
 {
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
     gchar *tmp;
 
     if (spapr_tce_find_by_liobn(liobn)) {
@@ -341,7 +371,7 @@
     return tcet;
 }
 
-void spapr_tce_table_enable(sPAPRTCETable *tcet,
+void spapr_tce_table_enable(SpaprTceTable *tcet,
                             uint32_t page_shift, uint64_t bus_offset,
                             uint32_t nb_table)
 {
@@ -366,7 +396,7 @@
                                 MEMORY_REGION(&tcet->iommu));
 }
 
-void spapr_tce_table_disable(sPAPRTCETable *tcet)
+void spapr_tce_table_disable(SpaprTceTable *tcet)
 {
     if (!tcet->nb_table) {
         return;
@@ -385,7 +415,7 @@
 
 static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
 {
-    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
+    SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev);
 
     vmstate_unregister(DEVICE(tcet), &vmstate_spapr_tce_table, tcet);
 
@@ -394,14 +424,14 @@
     spapr_tce_table_disable(tcet);
 }
 
-MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
+MemoryRegion *spapr_tce_get_iommu(SpaprTceTable *tcet)
 {
     return &tcet->root;
 }
 
 static void spapr_tce_reset(DeviceState *dev)
 {
-    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
+    SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev);
     size_t table_size = tcet->nb_table * sizeof(uint64_t);
 
     if (tcet->nb_table) {
@@ -409,7 +439,7 @@
     }
 }
 
-static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
+static target_ulong put_tce_emu(SpaprTceTable *tcet, target_ulong ioba,
                                 target_ulong tce)
 {
     IOMMUTLBEntry entry;
@@ -435,7 +465,7 @@
 }
 
 static target_ulong h_put_tce_indirect(PowerPCCPU *cpu,
-                                       sPAPRMachineState *spapr,
+                                       SpaprMachineState *spapr,
                                        target_ulong opcode, target_ulong *args)
 {
     int i;
@@ -445,7 +475,7 @@
     target_ulong tce_list = args[2];
     target_ulong npages = args[3];
     target_ulong ret = H_PARAMETER, tce = 0;
-    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn);
     CPUState *cs = CPU(cpu);
     hwaddr page_mask, page_size;
 
@@ -480,7 +510,7 @@
     return ret;
 }
 
-static target_ulong h_stuff_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_stuff_tce(PowerPCCPU *cpu, SpaprMachineState *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     int i;
@@ -489,7 +519,7 @@
     target_ulong tce_value = args[2];
     target_ulong npages = args[3];
     target_ulong ret = H_PARAMETER;
-    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn);
     hwaddr page_mask, page_size;
 
     if (!tcet) {
@@ -519,14 +549,14 @@
     return ret;
 }
 
-static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_put_tce(PowerPCCPU *cpu, SpaprMachineState *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     target_ulong liobn = args[0];
     target_ulong ioba = args[1];
     target_ulong tce = args[2];
     target_ulong ret = H_PARAMETER;
-    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn);
 
     if (tcet) {
         hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift);
@@ -544,7 +574,7 @@
     return ret;
 }
 
-static target_ulong get_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
+static target_ulong get_tce_emu(SpaprTceTable *tcet, target_ulong ioba,
                                 target_ulong *tce)
 {
     unsigned long index = (ioba - tcet->bus_offset) >> tcet->page_shift;
@@ -560,14 +590,14 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_get_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_get_tce(PowerPCCPU *cpu, SpaprMachineState *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     target_ulong liobn = args[0];
     target_ulong ioba = args[1];
     target_ulong tce = 0;
     target_ulong ret = H_PARAMETER;
-    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn);
 
     if (tcet) {
         hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift);
@@ -619,7 +649,7 @@
 }
 
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
-                      sPAPRTCETable *tcet)
+                      SpaprTceTable *tcet)
 {
     if (!tcet) {
         return 0;
@@ -650,7 +680,7 @@
 static TypeInfo spapr_tce_table_info = {
     .name = TYPE_SPAPR_TCE_TABLE,
     .parent = TYPE_DEVICE,
-    .instance_size = sizeof(sPAPRTCETable),
+    .instance_size = sizeof(SpaprTceTable),
     .class_init = spapr_tce_table_class_init,
 };
 
@@ -659,6 +689,7 @@
     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
 
     imrc->translate = spapr_tce_translate_iommu;
+    imrc->replay = spapr_tce_replay;
     imrc->get_min_page_size = spapr_tce_get_min_page_size;
     imrc->notify_flag_changed = spapr_tce_notify_flag_changed;
     imrc->get_attr = spapr_tce_get_attr;
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 4145079..253e4de 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -20,13 +20,13 @@
 
 #include "trace.h"
 
-void spapr_irq_msi_init(sPAPRMachineState *spapr, uint32_t nr_msis)
+void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis)
 {
     spapr->irq_map_nr = nr_msis;
     spapr->irq_map = bitmap_new(spapr->irq_map_nr);
 }
 
-int spapr_irq_msi_alloc(sPAPRMachineState *spapr, uint32_t num, bool align,
+int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
                         Error **errp)
 {
     int irq;
@@ -51,12 +51,12 @@
     return irq + SPAPR_IRQ_MSI;
 }
 
-void spapr_irq_msi_free(sPAPRMachineState *spapr, int irq, uint32_t num)
+void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
 {
     bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
 }
 
-void spapr_irq_msi_reset(sPAPRMachineState *spapr)
+void spapr_irq_msi_reset(SpaprMachineState *spapr)
 {
     bitmap_clear(spapr->irq_map, 0, spapr->irq_map_nr);
 }
@@ -66,7 +66,7 @@
  * XICS IRQ backend.
  */
 
-static ICSState *spapr_ics_create(sPAPRMachineState *spapr,
+static ICSState *spapr_ics_create(SpaprMachineState *spapr,
                                   int nr_irqs, Error **errp)
 {
     Error *local_err = NULL;
@@ -92,7 +92,7 @@
     return NULL;
 }
 
-static void spapr_irq_init_xics(sPAPRMachineState *spapr, int nr_irqs,
+static void spapr_irq_init_xics(SpaprMachineState *spapr, int nr_irqs,
                                 Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -126,7 +126,7 @@
 #define ICS_IRQ_FREE(ics, srcno)   \
     (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))
 
-static int spapr_irq_claim_xics(sPAPRMachineState *spapr, int irq, bool lsi,
+static int spapr_irq_claim_xics(SpaprMachineState *spapr, int irq, bool lsi,
                                 Error **errp)
 {
     ICSState *ics = spapr->ics;
@@ -147,7 +147,7 @@
     return 0;
 }
 
-static void spapr_irq_free_xics(sPAPRMachineState *spapr, int irq, int num)
+static void spapr_irq_free_xics(SpaprMachineState *spapr, int irq, int num)
 {
     ICSState *ics = spapr->ics;
     uint32_t srcno = irq - ics->offset;
@@ -164,7 +164,7 @@
     }
 }
 
-static qemu_irq spapr_qirq_xics(sPAPRMachineState *spapr, int irq)
+static qemu_irq spapr_qirq_xics(SpaprMachineState *spapr, int irq)
 {
     ICSState *ics = spapr->ics;
     uint32_t srcno = irq - ics->offset;
@@ -176,7 +176,7 @@
     return NULL;
 }
 
-static void spapr_irq_print_info_xics(sPAPRMachineState *spapr, Monitor *mon)
+static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
 {
     CPUState *cs;
 
@@ -189,12 +189,12 @@
     ics_pic_print_info(spapr->ics, mon);
 }
 
-static void spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
+static void spapr_irq_cpu_intc_create_xics(SpaprMachineState *spapr,
                                            PowerPCCPU *cpu, Error **errp)
 {
     Error *local_err = NULL;
     Object *obj;
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 
     obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
                      &local_err);
@@ -206,7 +206,7 @@
     spapr_cpu->icp = ICP(obj);
 }
 
-static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
+static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
 {
     if (!kvm_irqchip_in_kernel()) {
         CPUState *cs;
@@ -220,17 +220,17 @@
 
 static void spapr_irq_set_irq_xics(void *opaque, int srcno, int val)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     ics_simple_set_irq(spapr->ics, srcno, val);
 }
 
-static void spapr_irq_reset_xics(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
 {
     /* TODO: create the KVM XICS device */
 }
 
-static const char *spapr_irq_get_nodename_xics(sPAPRMachineState *spapr)
+static const char *spapr_irq_get_nodename_xics(SpaprMachineState *spapr)
 {
     return XICS_NODENAME;
 }
@@ -239,7 +239,7 @@
 #define SPAPR_IRQ_XICS_NR_MSIS     \
     (XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI)
 
-sPAPRIrq spapr_irq_xics = {
+SpaprIrq spapr_irq_xics = {
     .nr_irqs     = SPAPR_IRQ_XICS_NR_IRQS,
     .nr_msis     = SPAPR_IRQ_XICS_NR_MSIS,
     .ov5         = SPAPR_OV5_XIVE_LEGACY,
@@ -260,7 +260,7 @@
 /*
  * XIVE IRQ backend.
  */
-static void spapr_irq_init_xive(sPAPRMachineState *spapr, int nr_irqs,
+static void spapr_irq_init_xive(SpaprMachineState *spapr, int nr_irqs,
                                 Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -294,7 +294,7 @@
     spapr_xive_hcall_init(spapr);
 }
 
-static int spapr_irq_claim_xive(sPAPRMachineState *spapr, int irq, bool lsi,
+static int spapr_irq_claim_xive(SpaprMachineState *spapr, int irq, bool lsi,
                                 Error **errp)
 {
     if (!spapr_xive_irq_claim(spapr->xive, irq, lsi)) {
@@ -304,7 +304,7 @@
     return 0;
 }
 
-static void spapr_irq_free_xive(sPAPRMachineState *spapr, int irq, int num)
+static void spapr_irq_free_xive(SpaprMachineState *spapr, int irq, int num)
 {
     int i;
 
@@ -313,9 +313,9 @@
     }
 }
 
-static qemu_irq spapr_qirq_xive(sPAPRMachineState *spapr, int irq)
+static qemu_irq spapr_qirq_xive(SpaprMachineState *spapr, int irq)
 {
-    sPAPRXive *xive = spapr->xive;
+    SpaprXive *xive = spapr->xive;
 
     if (irq >= xive->nr_irqs) {
         return NULL;
@@ -327,7 +327,7 @@
     return spapr->qirqs[irq];
 }
 
-static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
+static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
                                       Monitor *mon)
 {
     CPUState *cs;
@@ -341,12 +341,12 @@
     spapr_xive_pic_print_info(spapr->xive, mon);
 }
 
-static void spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
+static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr,
                                            PowerPCCPU *cpu, Error **errp)
 {
     Error *local_err = NULL;
     Object *obj;
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
 
     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
     if (local_err) {
@@ -363,12 +363,12 @@
     spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
 }
 
-static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id)
+static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
 {
     return 0;
 }
 
-static void spapr_irq_reset_xive(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
 {
     CPUState *cs;
 
@@ -385,12 +385,12 @@
 
 static void spapr_irq_set_irq_xive(void *opaque, int srcno, int val)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     xive_source_set_irq(&spapr->xive->source, srcno, val);
 }
 
-static const char *spapr_irq_get_nodename_xive(sPAPRMachineState *spapr)
+static const char *spapr_irq_get_nodename_xive(SpaprMachineState *spapr)
 {
     return spapr->xive->nodename;
 }
@@ -403,7 +403,7 @@
 #define SPAPR_IRQ_XIVE_NR_IRQS     0x2000
 #define SPAPR_IRQ_XIVE_NR_MSIS     (SPAPR_IRQ_XIVE_NR_IRQS - SPAPR_IRQ_MSI)
 
-sPAPRIrq spapr_irq_xive = {
+SpaprIrq spapr_irq_xive = {
     .nr_irqs     = SPAPR_IRQ_XIVE_NR_IRQS,
     .nr_msis     = SPAPR_IRQ_XIVE_NR_MSIS,
     .ov5         = SPAPR_OV5_XIVE_EXPLOIT,
@@ -434,13 +434,13 @@
  * Returns the sPAPR IRQ backend negotiated by CAS. XICS is the
  * default.
  */
-static sPAPRIrq *spapr_irq_current(sPAPRMachineState *spapr)
+static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
 {
     return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ?
         &spapr_irq_xive : &spapr_irq_xics;
 }
 
-static void spapr_irq_init_dual(sPAPRMachineState *spapr, int nr_irqs,
+static void spapr_irq_init_dual(SpaprMachineState *spapr, int nr_irqs,
                                 Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
@@ -464,7 +464,7 @@
     }
 }
 
-static int spapr_irq_claim_dual(sPAPRMachineState *spapr, int irq, bool lsi,
+static int spapr_irq_claim_dual(SpaprMachineState *spapr, int irq, bool lsi,
                                 Error **errp)
 {
     Error *local_err = NULL;
@@ -485,30 +485,30 @@
     return ret;
 }
 
-static void spapr_irq_free_dual(sPAPRMachineState *spapr, int irq, int num)
+static void spapr_irq_free_dual(SpaprMachineState *spapr, int irq, int num)
 {
     spapr_irq_xics.free(spapr, irq, num);
     spapr_irq_xive.free(spapr, irq, num);
 }
 
-static qemu_irq spapr_qirq_dual(sPAPRMachineState *spapr, int irq)
+static qemu_irq spapr_qirq_dual(SpaprMachineState *spapr, int irq)
 {
     return spapr_irq_current(spapr)->qirq(spapr, irq);
 }
 
-static void spapr_irq_print_info_dual(sPAPRMachineState *spapr, Monitor *mon)
+static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon)
 {
     spapr_irq_current(spapr)->print_info(spapr, mon);
 }
 
-static void spapr_irq_dt_populate_dual(sPAPRMachineState *spapr,
+static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
                                        uint32_t nr_servers, void *fdt,
                                        uint32_t phandle)
 {
     spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
 }
 
-static void spapr_irq_cpu_intc_create_dual(sPAPRMachineState *spapr,
+static void spapr_irq_cpu_intc_create_dual(SpaprMachineState *spapr,
                                            PowerPCCPU *cpu, Error **errp)
 {
     Error *local_err = NULL;
@@ -522,7 +522,7 @@
     spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
 }
 
-static int spapr_irq_post_load_dual(sPAPRMachineState *spapr, int version_id)
+static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
 {
     /*
      * Force a reset of the XIVE backend after migration. The machine
@@ -535,7 +535,7 @@
     return spapr_irq_current(spapr)->post_load(spapr, version_id);
 }
 
-static void spapr_irq_reset_dual(sPAPRMachineState *spapr, Error **errp)
+static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
 {
     /*
      * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
@@ -548,12 +548,12 @@
 
 static void spapr_irq_set_irq_dual(void *opaque, int srcno, int val)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     spapr_irq_current(spapr)->set_irq(spapr, srcno, val);
 }
 
-static const char *spapr_irq_get_nodename_dual(sPAPRMachineState *spapr)
+static const char *spapr_irq_get_nodename_dual(SpaprMachineState *spapr)
 {
     return spapr_irq_current(spapr)->get_nodename(spapr);
 }
@@ -564,7 +564,7 @@
 #define SPAPR_IRQ_DUAL_NR_IRQS     0x2000
 #define SPAPR_IRQ_DUAL_NR_MSIS     (SPAPR_IRQ_DUAL_NR_IRQS - SPAPR_IRQ_MSI)
 
-sPAPRIrq spapr_irq_dual = {
+SpaprIrq spapr_irq_dual = {
     .nr_irqs     = SPAPR_IRQ_DUAL_NR_IRQS,
     .nr_msis     = SPAPR_IRQ_DUAL_NR_MSIS,
     .ov5         = SPAPR_OV5_XIVE_BOTH,
@@ -585,7 +585,7 @@
 /*
  * sPAPR IRQ frontend routines for devices
  */
-void spapr_irq_init(sPAPRMachineState *spapr, Error **errp)
+void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
 {
     MachineState *machine = MACHINE(spapr);
 
@@ -611,34 +611,34 @@
                                       spapr->irq->nr_irqs);
 }
 
-int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp)
+int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
 {
     return spapr->irq->claim(spapr, irq, lsi, errp);
 }
 
-void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
+void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
 {
     spapr->irq->free(spapr, irq, num);
 }
 
-qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq)
+qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
 {
     return spapr->irq->qirq(spapr, irq);
 }
 
-int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id)
+int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
 {
     return spapr->irq->post_load(spapr, version_id);
 }
 
-void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp)
+void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
 {
     if (spapr->irq->reset) {
         spapr->irq->reset(spapr, errp);
     }
 }
 
-int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp)
+int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
 {
     const char *nodename = spapr->irq->get_nodename(spapr);
     int offset, phandle;
@@ -684,7 +684,7 @@
     return -1;
 }
 
-int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp)
+int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
 {
     ICSState *ics = spapr->ics;
     int first = -1;
@@ -716,7 +716,7 @@
 
 #define SPAPR_IRQ_XICS_LEGACY_NR_IRQS     0x400
 
-sPAPRIrq spapr_irq_xics_legacy = {
+SpaprIrq spapr_irq_xics_legacy = {
     .nr_irqs     = SPAPR_IRQ_XICS_LEGACY_NR_IRQS,
     .nr_msis     = SPAPR_IRQ_XICS_LEGACY_NR_IRQS,
     .ov5         = SPAPR_OV5_XIVE_LEGACY,
diff --git a/hw/ppc/spapr_ovec.c b/hw/ppc/spapr_ovec.c
index 12510b2..a65b7c7 100644
--- a/hw/ppc/spapr_ovec.c
+++ b/hw/ppc/spapr_ovec.c
@@ -16,7 +16,6 @@
 #include "qemu/bitmap.h"
 #include "exec/address-spaces.h"
 #include "qemu/error-report.h"
-#include "sysemu/qtest.h"
 #include "trace.h"
 #include <libfdt.h>
 
@@ -27,7 +26,7 @@
  * allows us to more safely make assumptions about the bitmap size and
  * simplify the calling code somewhat
  */
-struct sPAPROptionVector {
+struct SpaprOptionVector {
     unsigned long *bitmap;
     int32_t bitmap_size; /* only used for migration */
 };
@@ -37,25 +36,25 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_BITMAP(bitmap, sPAPROptionVector, 1, bitmap_size),
+        VMSTATE_BITMAP(bitmap, SpaprOptionVector, 1, bitmap_size),
         VMSTATE_END_OF_LIST()
     }
 };
 
-sPAPROptionVector *spapr_ovec_new(void)
+SpaprOptionVector *spapr_ovec_new(void)
 {
-    sPAPROptionVector *ov;
+    SpaprOptionVector *ov;
 
-    ov = g_new0(sPAPROptionVector, 1);
+    ov = g_new0(SpaprOptionVector, 1);
     ov->bitmap = bitmap_new(OV_MAXBITS);
     ov->bitmap_size = OV_MAXBITS;
 
     return ov;
 }
 
-sPAPROptionVector *spapr_ovec_clone(sPAPROptionVector *ov_orig)
+SpaprOptionVector *spapr_ovec_clone(SpaprOptionVector *ov_orig)
 {
-    sPAPROptionVector *ov;
+    SpaprOptionVector *ov;
 
     g_assert(ov_orig);
 
@@ -65,9 +64,9 @@
     return ov;
 }
 
-void spapr_ovec_intersect(sPAPROptionVector *ov,
-                          sPAPROptionVector *ov1,
-                          sPAPROptionVector *ov2)
+void spapr_ovec_intersect(SpaprOptionVector *ov,
+                          SpaprOptionVector *ov1,
+                          SpaprOptionVector *ov2)
 {
     g_assert(ov);
     g_assert(ov1);
@@ -77,9 +76,9 @@
 }
 
 /* returns true if options bits were removed, false otherwise */
-bool spapr_ovec_diff(sPAPROptionVector *ov,
-                     sPAPROptionVector *ov_old,
-                     sPAPROptionVector *ov_new)
+bool spapr_ovec_diff(SpaprOptionVector *ov,
+                     SpaprOptionVector *ov_old,
+                     SpaprOptionVector *ov_new)
 {
     unsigned long *change_mask = bitmap_new(OV_MAXBITS);
     unsigned long *removed_bits = bitmap_new(OV_MAXBITS);
@@ -103,7 +102,7 @@
     return bits_were_removed;
 }
 
-void spapr_ovec_cleanup(sPAPROptionVector *ov)
+void spapr_ovec_cleanup(SpaprOptionVector *ov)
 {
     if (ov) {
         g_free(ov->bitmap);
@@ -111,7 +110,7 @@
     }
 }
 
-void spapr_ovec_set(sPAPROptionVector *ov, long bitnr)
+void spapr_ovec_set(SpaprOptionVector *ov, long bitnr)
 {
     g_assert(ov);
     g_assert(bitnr < OV_MAXBITS);
@@ -119,7 +118,7 @@
     set_bit(bitnr, ov->bitmap);
 }
 
-void spapr_ovec_clear(sPAPROptionVector *ov, long bitnr)
+void spapr_ovec_clear(SpaprOptionVector *ov, long bitnr)
 {
     g_assert(ov);
     g_assert(bitnr < OV_MAXBITS);
@@ -127,16 +126,11 @@
     clear_bit(bitnr, ov->bitmap);
 }
 
-bool spapr_ovec_test(sPAPROptionVector *ov, long bitnr)
+bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr)
 {
     g_assert(ov);
     g_assert(bitnr < OV_MAXBITS);
 
-    /* support memory unplug for qtest */
-    if (qtest_enabled() && bitnr == OV5_HP_EVT) {
-        return true;
-    }
-
     return test_bit(bitnr, ov->bitmap) ? true : false;
 }
 
@@ -184,9 +178,9 @@
     return table_addr;
 }
 
-sPAPROptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector)
+SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector)
 {
-    sPAPROptionVector *ov;
+    SpaprOptionVector *ov;
     target_ulong addr;
     uint16_t vector_len;
     int i;
@@ -216,7 +210,7 @@
 }
 
 int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
-                           sPAPROptionVector *ov, const char *name)
+                           SpaprOptionVector *ov, const char *name)
 {
     uint8_t vec[OV_MAXBYTES + 1];
     uint16_t vec_len;
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 69059c3..20915d2 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -61,9 +61,9 @@
 #define RTAS_TYPE_MSI           1
 #define RTAS_TYPE_MSIX          2
 
-sPAPRPHBState *spapr_pci_find_phb(sPAPRMachineState *spapr, uint64_t buid)
+SpaprPhbState *spapr_pci_find_phb(SpaprMachineState *spapr, uint64_t buid)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
 
     QLIST_FOREACH(sphb, &spapr->phbs, list) {
         if (sphb->buid != buid) {
@@ -75,10 +75,10 @@
     return NULL;
 }
 
-PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid,
+PCIDevice *spapr_pci_find_dev(SpaprMachineState *spapr, uint64_t buid,
                               uint32_t config_addr)
 {
-    sPAPRPHBState *sphb = spapr_pci_find_phb(spapr, buid);
+    SpaprPhbState *sphb = spapr_pci_find_phb(spapr, buid);
     PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
     int bus_num = (config_addr >> 16) & 0xFF;
     int devfn = (config_addr >> 8) & 0xFF;
@@ -96,7 +96,7 @@
     return ((arg >> 20) & 0xf00) | (arg & 0xff);
 }
 
-static void finish_read_pci_config(sPAPRMachineState *spapr, uint64_t buid,
+static void finish_read_pci_config(SpaprMachineState *spapr, uint64_t buid,
                                    uint32_t addr, uint32_t size,
                                    target_ulong rets)
 {
@@ -126,7 +126,7 @@
     rtas_st(rets, 1, val);
 }
 
-static void rtas_ibm_read_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_ibm_read_pci_config(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                      uint32_t token, uint32_t nargs,
                                      target_ulong args,
                                      uint32_t nret, target_ulong rets)
@@ -146,7 +146,7 @@
     finish_read_pci_config(spapr, buid, addr, size, rets);
 }
 
-static void rtas_read_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_read_pci_config(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
@@ -164,7 +164,7 @@
     finish_read_pci_config(spapr, 0, addr, size, rets);
 }
 
-static void finish_write_pci_config(sPAPRMachineState *spapr, uint64_t buid,
+static void finish_write_pci_config(SpaprMachineState *spapr, uint64_t buid,
                                     uint32_t addr, uint32_t size,
                                     uint32_t val, target_ulong rets)
 {
@@ -192,7 +192,7 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void rtas_ibm_write_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_ibm_write_pci_config(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                       uint32_t token, uint32_t nargs,
                                       target_ulong args,
                                       uint32_t nret, target_ulong rets)
@@ -213,7 +213,7 @@
     finish_write_pci_config(spapr, buid, addr, size, val, rets);
 }
 
-static void rtas_write_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_write_pci_config(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                   uint32_t token, uint32_t nargs,
                                   target_ulong args,
                                   uint32_t nret, target_ulong rets)
@@ -262,12 +262,12 @@
     }
 }
 
-static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 uint32_t token, uint32_t nargs,
                                 target_ulong args, uint32_t nret,
                                 target_ulong rets)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     uint32_t config_addr = rtas_ld(args, 0);
     uint64_t buid = rtas_ldq(args, 1);
     unsigned int func = rtas_ld(args, 3);
@@ -275,14 +275,14 @@
     unsigned int seq_num = rtas_ld(args, 5);
     unsigned int ret_intr_type;
     unsigned int irq, max_irqs = 0;
-    sPAPRPHBState *phb = NULL;
+    SpaprPhbState *phb = NULL;
     PCIDevice *pdev = NULL;
     spapr_pci_msi *msi;
     int *config_addr_key;
     Error *err = NULL;
     int i;
 
-    /* Fins sPAPRPHBState */
+    /* Fins SpaprPhbState */
     phb = spapr_pci_find_phb(spapr, buid);
     if (phb) {
         pdev = spapr_pci_find_dev(spapr, buid, config_addr);
@@ -439,7 +439,7 @@
 }
 
 static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
-                                                   sPAPRMachineState *spapr,
+                                                   SpaprMachineState *spapr,
                                                    uint32_t token,
                                                    uint32_t nargs,
                                                    target_ulong args,
@@ -449,11 +449,11 @@
     uint32_t config_addr = rtas_ld(args, 0);
     uint64_t buid = rtas_ldq(args, 1);
     unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3);
-    sPAPRPHBState *phb = NULL;
+    SpaprPhbState *phb = NULL;
     PCIDevice *pdev = NULL;
     spapr_pci_msi *msi;
 
-    /* Find sPAPRPHBState */
+    /* Find SpaprPhbState */
     phb = spapr_pci_find_phb(spapr, buid);
     if (phb) {
         pdev = spapr_pci_find_dev(spapr, buid, config_addr);
@@ -480,12 +480,12 @@
 }
 
 static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu,
-                                    sPAPRMachineState *spapr,
+                                    SpaprMachineState *spapr,
                                     uint32_t token, uint32_t nargs,
                                     target_ulong args, uint32_t nret,
                                     target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     uint32_t addr, option;
     uint64_t buid;
     int ret;
@@ -516,12 +516,12 @@
 }
 
 static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu,
-                                           sPAPRMachineState *spapr,
+                                           SpaprMachineState *spapr,
                                            uint32_t token, uint32_t nargs,
                                            target_ulong args, uint32_t nret,
                                            target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     PCIDevice *pdev;
     uint32_t addr, option;
     uint64_t buid;
@@ -570,12 +570,12 @@
 }
 
 static void rtas_ibm_read_slot_reset_state2(PowerPCCPU *cpu,
-                                            sPAPRMachineState *spapr,
+                                            SpaprMachineState *spapr,
                                             uint32_t token, uint32_t nargs,
                                             target_ulong args, uint32_t nret,
                                             target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     uint64_t buid;
     int state, ret;
 
@@ -612,12 +612,12 @@
 }
 
 static void rtas_ibm_set_slot_reset(PowerPCCPU *cpu,
-                                    sPAPRMachineState *spapr,
+                                    SpaprMachineState *spapr,
                                     uint32_t token, uint32_t nargs,
                                     target_ulong args, uint32_t nret,
                                     target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     uint32_t option;
     uint64_t buid;
     int ret;
@@ -646,12 +646,12 @@
 }
 
 static void rtas_ibm_configure_pe(PowerPCCPU *cpu,
-                                  sPAPRMachineState *spapr,
+                                  SpaprMachineState *spapr,
                                   uint32_t token, uint32_t nargs,
                                   target_ulong args, uint32_t nret,
                                   target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     uint64_t buid;
     int ret;
 
@@ -679,12 +679,12 @@
 
 /* To support it later */
 static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu,
-                                       sPAPRMachineState *spapr,
+                                       SpaprMachineState *spapr,
                                        uint32_t token, uint32_t nargs,
                                        target_ulong args, uint32_t nret,
                                        target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     int option;
     uint64_t buid;
 
@@ -741,7 +741,7 @@
      * Here we use the number returned by pci_spapr_map_irq to find a
      * corresponding qemu_irq.
      */
-    sPAPRPHBState *phb = opaque;
+    SpaprPhbState *phb = opaque;
 
     trace_spapr_pci_lsi_set(phb->dtbusname, irq_num, phb->lsi_table[irq_num].irq);
     qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
@@ -749,7 +749,7 @@
 
 static PCIINTxRoute spapr_route_intx_pin_to_irq(void *opaque, int pin)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(opaque);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(opaque);
     PCIINTxRoute route;
 
     route.mode = PCI_INTX_ENABLED;
@@ -766,7 +766,7 @@
 static void spapr_msi_write(void *opaque, hwaddr addr,
                             uint64_t data, unsigned size)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
     uint32_t irq = data;
 
     trace_spapr_pci_msi_write(addr, data, irq);
@@ -786,12 +786,12 @@
  */
 static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 {
-    sPAPRPHBState *phb = opaque;
+    SpaprPhbState *phb = opaque;
 
     return &phb->iommu_as;
 }
 
-static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
+static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb,  PCIDevice *pdev)
 {
     char *path = NULL, *buf = NULL, *host = NULL;
 
@@ -822,7 +822,7 @@
     return NULL;
 }
 
-static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
+static char *spapr_phb_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev)
 {
     char *buf;
     const char *devtype = "qemu";
@@ -1249,11 +1249,11 @@
     }
 }
 
-static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
+static uint32_t spapr_phb_get_pci_drc_index(SpaprPhbState *phb,
                                             PCIDevice *pdev);
 
 static void spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
-                                       sPAPRPHBState *sphb)
+                                       SpaprPhbState *sphb)
 {
     ResourceProps rp;
     bool is_bridge = false;
@@ -1358,7 +1358,7 @@
 }
 
 /* create OF node for pci device and required OF DT properties */
-static int spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev,
+static int spapr_create_pci_child_dt(SpaprPhbState *phb, PCIDevice *dev,
                                      void *fdt, int node_offset)
 {
     int offset;
@@ -1382,7 +1382,7 @@
     object_unparent(OBJECT(dev));
 }
 
-static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb,
+static SpaprDrc *spapr_phb_get_pci_func_drc(SpaprPhbState *phb,
                                                     uint32_t busnr,
                                                     int32_t devfn)
 {
@@ -1390,17 +1390,17 @@
                            (phb->index << 16) | (busnr << 8) | devfn);
 }
 
-static sPAPRDRConnector *spapr_phb_get_pci_drc(sPAPRPHBState *phb,
+static SpaprDrc *spapr_phb_get_pci_drc(SpaprPhbState *phb,
                                                PCIDevice *pdev)
 {
     uint32_t busnr = pci_bus_num(PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))));
     return spapr_phb_get_pci_func_drc(phb, busnr, pdev->devfn);
 }
 
-static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
+static uint32_t spapr_phb_get_pci_drc_index(SpaprPhbState *phb,
                                             PCIDevice *pdev)
 {
-    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev);
+    SpaprDrc *drc = spapr_phb_get_pci_drc(phb, pdev);
 
     if (!drc) {
         return 0;
@@ -1409,11 +1409,11 @@
     return spapr_drc_index(drc);
 }
 
-int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_pci_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp)
 {
     HotplugHandler *plug_handler = qdev_get_hotplug_handler(drc->dev);
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(plug_handler);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(plug_handler);
     PCIDevice *pdev = PCI_DEVICE(drc->dev);
 
     *fdt_start_offset = spapr_create_pci_child_dt(sphb, pdev, fdt, 0);
@@ -1423,9 +1423,9 @@
 static void spapr_pci_plug(HotplugHandler *plug_handler,
                            DeviceState *plugged_dev, Error **errp)
 {
-    sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
+    SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
     PCIDevice *pdev = PCI_DEVICE(plugged_dev);
-    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev);
+    SpaprDrc *drc = spapr_phb_get_pci_drc(phb, pdev);
     Error *local_err = NULL;
     PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev)));
     uint32_t slotnr = PCI_SLOT(pdev->devfn);
@@ -1472,9 +1472,9 @@
         int i;
 
         for (i = 0; i < 8; i++) {
-            sPAPRDRConnector *func_drc;
-            sPAPRDRConnectorClass *func_drck;
-            sPAPRDREntitySense state;
+            SpaprDrc *func_drc;
+            SpaprDrcClass *func_drck;
+            SpaprDREntitySense state;
 
             func_drc = spapr_phb_get_pci_func_drc(phb, pci_bus_num(bus),
                                                   PCI_DEVFN(slotnr, i));
@@ -1513,9 +1513,9 @@
 static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
                                      DeviceState *plugged_dev, Error **errp)
 {
-    sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
+    SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler));
     PCIDevice *pdev = PCI_DEVICE(plugged_dev);
-    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev);
+    SpaprDrc *drc = spapr_phb_get_pci_drc(phb, pdev);
 
     if (!phb->dr_enabled) {
         error_setg(errp, QERR_BUS_NO_HOTPLUG,
@@ -1529,9 +1529,9 @@
     if (!spapr_drc_unplug_requested(drc)) {
         PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev)));
         uint32_t slotnr = PCI_SLOT(pdev->devfn);
-        sPAPRDRConnector *func_drc;
-        sPAPRDRConnectorClass *func_drck;
-        sPAPRDREntitySense state;
+        SpaprDrc *func_drc;
+        SpaprDrcClass *func_drck;
+        SpaprDREntitySense state;
         int i;
 
         /* ensure any other present functions are pending unplug */
@@ -1573,7 +1573,7 @@
 
 static void spapr_phb_finalizefn(Object *obj)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(obj);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(obj);
 
     g_free(sphb->dtbusname);
     sphb->dtbusname = NULL;
@@ -1581,11 +1581,11 @@
 
 static void spapr_phb_unrealize(DeviceState *dev, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
     SysBusDevice *s = SYS_BUS_DEVICE(dev);
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(phb);
-    sPAPRTCETable *tcet;
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(phb);
+    SpaprTceTable *tcet;
     int i;
     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
 
@@ -1608,7 +1608,7 @@
 
     if (sphb->dr_enabled) {
         for (i = PCI_SLOT_MAX * 8 - 1; i >= 0; i--) {
-            sPAPRDRConnector *drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PCI,
+            SpaprDrc *drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PCI,
                                                     (sphb->index << 16) | i);
 
             if (drc) {
@@ -1645,18 +1645,18 @@
     /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
      * tries to add a sPAPR PHB to a non-pseries machine.
      */
-    sPAPRMachineState *spapr =
-        (sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
+    SpaprMachineState *spapr =
+        (SpaprMachineState *) object_dynamic_cast(qdev_get_machine(),
                                                   TYPE_SPAPR_MACHINE);
-    sPAPRMachineClass *smc = spapr ? SPAPR_MACHINE_GET_CLASS(spapr) : NULL;
+    SpaprMachineClass *smc = spapr ? SPAPR_MACHINE_GET_CLASS(spapr) : NULL;
     SysBusDevice *s = SYS_BUS_DEVICE(dev);
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
     char *namebuf;
     int i;
     PCIBus *bus;
     uint64_t msi_window_size = 4096;
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
 
     if (!spapr) {
@@ -1855,10 +1855,10 @@
     return 0;
 }
 
-void spapr_phb_dma_reset(sPAPRPHBState *sphb)
+void spapr_phb_dma_reset(SpaprPhbState *sphb)
 {
     int i;
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
 
     for (i = 0; i < SPAPR_PCI_DMA_MAX_WINDOWS; ++i) {
         tcet = spapr_tce_find_by_liobn(sphb->dma_liobn[i]);
@@ -1876,7 +1876,7 @@
 
 static void spapr_phb_reset(DeviceState *qdev)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);
 
     spapr_phb_dma_reset(sphb);
 
@@ -1889,27 +1889,27 @@
 }
 
 static Property spapr_phb_properties[] = {
-    DEFINE_PROP_UINT32("index", sPAPRPHBState, index, -1),
-    DEFINE_PROP_UINT64("mem_win_size", sPAPRPHBState, mem_win_size,
+    DEFINE_PROP_UINT32("index", SpaprPhbState, index, -1),
+    DEFINE_PROP_UINT64("mem_win_size", SpaprPhbState, mem_win_size,
                        SPAPR_PCI_MEM32_WIN_SIZE),
-    DEFINE_PROP_UINT64("mem64_win_size", sPAPRPHBState, mem64_win_size,
+    DEFINE_PROP_UINT64("mem64_win_size", SpaprPhbState, mem64_win_size,
                        SPAPR_PCI_MEM64_WIN_SIZE),
-    DEFINE_PROP_UINT64("io_win_size", sPAPRPHBState, io_win_size,
+    DEFINE_PROP_UINT64("io_win_size", SpaprPhbState, io_win_size,
                        SPAPR_PCI_IO_WIN_SIZE),
-    DEFINE_PROP_BOOL("dynamic-reconfiguration", sPAPRPHBState, dr_enabled,
+    DEFINE_PROP_BOOL("dynamic-reconfiguration", SpaprPhbState, dr_enabled,
                      true),
     /* Default DMA window is 0..1GB */
-    DEFINE_PROP_UINT64("dma_win_addr", sPAPRPHBState, dma_win_addr, 0),
-    DEFINE_PROP_UINT64("dma_win_size", sPAPRPHBState, dma_win_size, 0x40000000),
-    DEFINE_PROP_UINT64("dma64_win_addr", sPAPRPHBState, dma64_win_addr,
+    DEFINE_PROP_UINT64("dma_win_addr", SpaprPhbState, dma_win_addr, 0),
+    DEFINE_PROP_UINT64("dma_win_size", SpaprPhbState, dma_win_size, 0x40000000),
+    DEFINE_PROP_UINT64("dma64_win_addr", SpaprPhbState, dma64_win_addr,
                        0x800000000000000ULL),
-    DEFINE_PROP_BOOL("ddw", sPAPRPHBState, ddw_enabled, true),
-    DEFINE_PROP_UINT64("pgsz", sPAPRPHBState, page_size_mask,
+    DEFINE_PROP_BOOL("ddw", SpaprPhbState, ddw_enabled, true),
+    DEFINE_PROP_UINT64("pgsz", SpaprPhbState, page_size_mask,
                        (1ULL << 12) | (1ULL << 16)),
-    DEFINE_PROP_UINT32("numa_node", sPAPRPHBState, numa_node, -1),
-    DEFINE_PROP_BOOL("pre-2.8-migration", sPAPRPHBState,
+    DEFINE_PROP_UINT32("numa_node", SpaprPhbState, numa_node, -1),
+    DEFINE_PROP_BOOL("pre-2.8-migration", SpaprPhbState,
                      pre_2_8_migration, false),
-    DEFINE_PROP_BOOL("pcie-extended-configuration-space", sPAPRPHBState,
+    DEFINE_PROP_BOOL("pcie-extended-configuration-space", SpaprPhbState,
                      pcie_ecs, true),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -1939,7 +1939,7 @@
 
 static int spapr_pci_pre_save(void *opaque)
 {
-    sPAPRPHBState *sphb = opaque;
+    SpaprPhbState *sphb = opaque;
     GHashTableIter iter;
     gpointer key, value;
     int i;
@@ -1977,7 +1977,7 @@
 
 static int spapr_pci_post_load(void *opaque, int version_id)
 {
-    sPAPRPHBState *sphb = opaque;
+    SpaprPhbState *sphb = opaque;
     gpointer key, value;
     int i;
 
@@ -1997,7 +1997,7 @@
 
 static bool pre_2_8_migration(void *opaque, int version_id)
 {
-    sPAPRPHBState *sphb = opaque;
+    SpaprPhbState *sphb = opaque;
 
     return sphb->pre_2_8_migration;
 }
@@ -2009,16 +2009,16 @@
     .pre_save = spapr_pci_pre_save,
     .post_load = spapr_pci_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64_EQUAL(buid, sPAPRPHBState, NULL),
-        VMSTATE_UINT32_TEST(mig_liobn, sPAPRPHBState, pre_2_8_migration),
-        VMSTATE_UINT64_TEST(mig_mem_win_addr, sPAPRPHBState, pre_2_8_migration),
-        VMSTATE_UINT64_TEST(mig_mem_win_size, sPAPRPHBState, pre_2_8_migration),
-        VMSTATE_UINT64_TEST(mig_io_win_addr, sPAPRPHBState, pre_2_8_migration),
-        VMSTATE_UINT64_TEST(mig_io_win_size, sPAPRPHBState, pre_2_8_migration),
-        VMSTATE_STRUCT_ARRAY(lsi_table, sPAPRPHBState, PCI_NUM_PINS, 0,
+        VMSTATE_UINT64_EQUAL(buid, SpaprPhbState, NULL),
+        VMSTATE_UINT32_TEST(mig_liobn, SpaprPhbState, pre_2_8_migration),
+        VMSTATE_UINT64_TEST(mig_mem_win_addr, SpaprPhbState, pre_2_8_migration),
+        VMSTATE_UINT64_TEST(mig_mem_win_size, SpaprPhbState, pre_2_8_migration),
+        VMSTATE_UINT64_TEST(mig_io_win_addr, SpaprPhbState, pre_2_8_migration),
+        VMSTATE_UINT64_TEST(mig_io_win_size, SpaprPhbState, pre_2_8_migration),
+        VMSTATE_STRUCT_ARRAY(lsi_table, SpaprPhbState, PCI_NUM_PINS, 0,
                              vmstate_spapr_pci_lsi, struct spapr_pci_lsi),
-        VMSTATE_INT32(msi_devs_num, sPAPRPHBState),
-        VMSTATE_STRUCT_VARRAY_ALLOC(msi_devs, sPAPRPHBState, msi_devs_num, 0,
+        VMSTATE_INT32(msi_devs_num, SpaprPhbState),
+        VMSTATE_STRUCT_VARRAY_ALLOC(msi_devs, SpaprPhbState, msi_devs_num, 0,
                                     vmstate_spapr_pci_msi, spapr_pci_msi_mig),
         VMSTATE_END_OF_LIST()
     },
@@ -2027,7 +2027,7 @@
 static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge,
                                            PCIBus *rootbus)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(host_bridge);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(host_bridge);
 
     return sphb->dtbusname;
 }
@@ -2055,7 +2055,7 @@
 static const TypeInfo spapr_phb_info = {
     .name          = TYPE_SPAPR_PCI_HOST_BRIDGE,
     .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(sPAPRPHBState),
+    .instance_size = sizeof(SpaprPhbState),
     .instance_finalize = spapr_phb_finalizefn,
     .class_init    = spapr_phb_class_init,
     .interfaces    = (InterfaceInfo[]) {
@@ -2064,19 +2064,19 @@
     }
 };
 
-typedef struct sPAPRFDT {
+typedef struct SpaprFdt {
     void *fdt;
     int node_off;
-    sPAPRPHBState *sphb;
-} sPAPRFDT;
+    SpaprPhbState *sphb;
+} SpaprFdt;
 
 static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
                                           void *opaque)
 {
     PCIBus *sec_bus;
-    sPAPRFDT *p = opaque;
+    SpaprFdt *p = opaque;
     int offset;
-    sPAPRFDT s_fdt;
+    SpaprFdt s_fdt;
 
     offset = spapr_create_pci_child_dt(p->sphb, pdev, p->fdt, p->node_off);
     if (!offset) {
@@ -2128,7 +2128,7 @@
     pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, *bus_no, 1);
 }
 
-static void spapr_phb_pci_enumerate(sPAPRPHBState *phb)
+static void spapr_phb_pci_enumerate(SpaprPhbState *phb)
 {
     PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
     unsigned int bus_no = 0;
@@ -2139,7 +2139,7 @@
 
 }
 
-int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
+int spapr_populate_pci_dt(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
                           uint32_t nr_msis, int *node_offset)
 {
     int bus_off, i, j, ret;
@@ -2187,10 +2187,10 @@
                                 cpu_to_be32(0x0),
                                 cpu_to_be32(0x0),
                                 cpu_to_be32(phb->numa_node)};
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
     PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
-    sPAPRFDT s_fdt;
-    sPAPRDRConnector *drc;
+    SpaprFdt s_fdt;
+    SpaprDrc *drc;
 
     /* Start populating the FDT */
     nodename = g_strdup_printf("pci@%" PRIx64, phb->buid);
@@ -2345,8 +2345,8 @@
 
 void spapr_pci_switch_vga(bool big_endian)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
-    sPAPRPHBState *sphb;
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprPhbState *sphb;
 
     /*
      * For backward compatibility with existing guests, we switch
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 71491db..5f5dde5 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -28,12 +28,12 @@
 #include "qemu/error-report.h"
 #include "sysemu/qtest.h"
 
-bool spapr_phb_eeh_available(sPAPRPHBState *sphb)
+bool spapr_phb_eeh_available(SpaprPhbState *sphb)
 {
     return vfio_eeh_as_ok(&sphb->iommu_as);
 }
 
-static void spapr_phb_vfio_eeh_reenable(sPAPRPHBState *sphb)
+static void spapr_phb_vfio_eeh_reenable(SpaprPhbState *sphb)
 {
     vfio_eeh_as_op(&sphb->iommu_as, VFIO_EEH_PE_ENABLE);
 }
@@ -49,7 +49,7 @@
     spapr_phb_vfio_eeh_reenable(SPAPR_PCI_HOST_BRIDGE(qdev));
 }
 
-int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb,
+int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
                                   unsigned int addr, int option)
 {
     uint32_t op;
@@ -96,7 +96,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-int spapr_phb_vfio_eeh_get_state(sPAPRPHBState *sphb, int *state)
+int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb, int *state)
 {
     int ret;
 
@@ -145,14 +145,14 @@
                            spapr_phb_vfio_eeh_clear_dev_msix, NULL);
 }
 
-static void spapr_phb_vfio_eeh_pre_reset(sPAPRPHBState *sphb)
+static void spapr_phb_vfio_eeh_pre_reset(SpaprPhbState *sphb)
 {
        PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
 
        pci_for_each_bus(phb->bus, spapr_phb_vfio_eeh_clear_bus_msix, NULL);
 }
 
-int spapr_phb_vfio_eeh_reset(sPAPRPHBState *sphb, int option)
+int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option)
 {
     uint32_t op;
     int ret;
@@ -181,7 +181,7 @@
     return RTAS_OUT_SUCCESS;
 }
 
-int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb)
+int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
 {
     int ret;
 
diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c
index 644bac9..4060987 100644
--- a/hw/ppc/spapr_rng.c
+++ b/hw/ppc/spapr_rng.c
@@ -29,15 +29,15 @@
 #include "kvm_ppc.h"
 
 #define SPAPR_RNG(obj) \
-    OBJECT_CHECK(sPAPRRngState, (obj), TYPE_SPAPR_RNG)
+    OBJECT_CHECK(SpaprRngState, (obj), TYPE_SPAPR_RNG)
 
-struct sPAPRRngState {
+struct SpaprRngState {
     /*< private >*/
     DeviceState ds;
     RngBackend *backend;
     bool use_kvm;
 };
-typedef struct sPAPRRngState sPAPRRngState;
+typedef struct SpaprRngState SpaprRngState;
 
 struct HRandomData {
     QemuSemaphore sem;
@@ -64,10 +64,10 @@
 }
 
 /* Handler for the H_RANDOM hypercall */
-static target_ulong h_random(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_random(PowerPCCPU *cpu, SpaprMachineState *spapr,
                              target_ulong opcode, target_ulong *args)
 {
-    sPAPRRngState *rngstate;
+    SpaprRngState *rngstate;
     HRandomData hrdata;
 
     rngstate = SPAPR_RNG(object_resolve_path_type("", TYPE_SPAPR_RNG, NULL));
@@ -109,7 +109,7 @@
 static void spapr_rng_realize(DeviceState *dev, Error **errp)
 {
 
-    sPAPRRngState *rngstate = SPAPR_RNG(dev);
+    SpaprRngState *rngstate = SPAPR_RNG(dev);
 
     if (rngstate->use_kvm) {
         if (kvmppc_enable_hwrng() == 0) {
@@ -133,8 +133,8 @@
 }
 
 static Property spapr_rng_properties[] = {
-    DEFINE_PROP_BOOL("use-kvm", sPAPRRngState, use_kvm, false),
-    DEFINE_PROP_LINK("rng", sPAPRRngState, backend, TYPE_RNG_BACKEND,
+    DEFINE_PROP_BOOL("use-kvm", SpaprRngState, use_kvm, false),
+    DEFINE_PROP_LINK("rng", SpaprRngState, backend, TYPE_RNG_BACKEND,
                      RngBackend *),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -152,7 +152,7 @@
 static const TypeInfo spapr_rng_info = {
     .name          = TYPE_SPAPR_RNG,
     .parent        = TYPE_DEVICE,
-    .instance_size = sizeof(sPAPRRngState),
+    .instance_size = sizeof(SpaprRngState),
     .instance_init = spapr_rng_instance_init,
     .class_init    = spapr_rng_class_init,
 };
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 7a2cb78..24c45b1 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -50,13 +50,13 @@
 #include "target/ppc/mmu-hash64.h"
 #include "target/ppc/mmu-book3s-v3.h"
 
-static void rtas_display_character(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_display_character(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                    uint32_t token, uint32_t nargs,
                                    target_ulong args,
                                    uint32_t nret, target_ulong rets)
 {
     uint8_t c = rtas_ld(args, 0);
-    VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
+    SpaprVioDevice *sdev = vty_lookup(spapr, 0);
 
     if (!sdev) {
         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
@@ -66,7 +66,7 @@
     }
 }
 
-static void rtas_power_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_power_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
                            uint32_t token, uint32_t nargs, target_ulong args,
                            uint32_t nret, target_ulong rets)
 {
@@ -79,7 +79,7 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void rtas_system_reboot(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_system_reboot(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                uint32_t token, uint32_t nargs,
                                target_ulong args,
                                uint32_t nret, target_ulong rets)
@@ -93,7 +93,7 @@
 }
 
 static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
-                                         sPAPRMachineState *spapr,
+                                         SpaprMachineState *spapr,
                                          uint32_t token, uint32_t nargs,
                                          target_ulong args,
                                          uint32_t nret, target_ulong rets)
@@ -123,7 +123,7 @@
     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
 }
 
-static void rtas_start_cpu(PowerPCCPU *callcpu, sPAPRMachineState *spapr,
+static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
                            uint32_t token, uint32_t nargs,
                            target_ulong args,
                            uint32_t nret, target_ulong rets)
@@ -194,7 +194,7 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr,
                            uint32_t token, uint32_t nargs,
                            target_ulong args,
                            uint32_t nret, target_ulong rets)
@@ -226,7 +226,7 @@
 }
 
 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
-                                          sPAPRMachineState *spapr,
+                                          SpaprMachineState *spapr,
                                           uint32_t token, uint32_t nargs,
                                           target_ulong args,
                                           uint32_t nret, target_ulong rets)
@@ -268,7 +268,7 @@
 }
 
 static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
-                                          sPAPRMachineState *spapr,
+                                          SpaprMachineState *spapr,
                                           uint32_t token, uint32_t nargs,
                                           target_ulong args,
                                           uint32_t nret, target_ulong rets)
@@ -288,7 +288,7 @@
 }
 
 static void rtas_ibm_os_term(PowerPCCPU *cpu,
-                            sPAPRMachineState *spapr,
+                            SpaprMachineState *spapr,
                             uint32_t token, uint32_t nargs,
                             target_ulong args,
                             uint32_t nret, target_ulong rets)
@@ -298,7 +298,7 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void rtas_set_power_level(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_set_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args, uint32_t nret,
                                  target_ulong rets)
@@ -323,7 +323,7 @@
     rtas_st(rets, 1, 100);
 }
 
-static void rtas_get_power_level(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_get_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                   uint32_t token, uint32_t nargs,
                                   target_ulong args, uint32_t nret,
                                   target_ulong rets)
@@ -353,7 +353,7 @@
     spapr_rtas_fn fn;
 } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];
 
-target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *spapr,
                              uint32_t token, uint32_t nargs, target_ulong args,
                              uint32_t nret, target_ulong rets)
 {
@@ -387,7 +387,7 @@
 
     for (token = 0; token < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; token++) {
         if (strcmp(cmd, rtas_table[token].name) == 0) {
-            sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+            SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
             PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
 
             rtas_table[token].fn(cpu, spapr, token + RTAS_TOKEN_BASE,
@@ -425,7 +425,7 @@
     }
 }
 
-void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr)
+void spapr_load_rtas(SpaprMachineState *spapr, void *fdt, hwaddr addr)
 {
     int rtas_node;
     int ret;
diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c
index cb8a410..f653818 100644
--- a/hw/ppc/spapr_rtas_ddw.c
+++ b/hw/ppc/spapr_rtas_ddw.c
@@ -26,16 +26,16 @@
 
 static int spapr_phb_get_active_win_num_cb(Object *child, void *opaque)
 {
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
 
-    tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
+    tcet = (SpaprTceTable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
     if (tcet && tcet->nb_table) {
         ++*(unsigned *)opaque;
     }
     return 0;
 }
 
-static unsigned spapr_phb_get_active_win_num(sPAPRPHBState *sphb)
+static unsigned spapr_phb_get_active_win_num(SpaprPhbState *sphb)
 {
     unsigned ret = 0;
 
@@ -46,9 +46,9 @@
 
 static int spapr_phb_get_free_liobn_cb(Object *child, void *opaque)
 {
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
 
-    tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
+    tcet = (SpaprTceTable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
     if (tcet && !tcet->nb_table) {
         *(uint32_t *)opaque = tcet->liobn;
         return 1;
@@ -56,7 +56,7 @@
     return 0;
 }
 
-static unsigned spapr_phb_get_free_liobn(sPAPRPHBState *sphb)
+static unsigned spapr_phb_get_free_liobn(SpaprPhbState *sphb)
 {
     uint32_t liobn = 0;
 
@@ -90,12 +90,12 @@
 }
 
 static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
-                                         sPAPRMachineState *spapr,
+                                         SpaprMachineState *spapr,
                                          uint32_t token, uint32_t nargs,
                                          target_ulong args,
                                          uint32_t nret, target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     uint64_t buid;
     uint32_t avail, addr, pgmask = 0;
 
@@ -129,13 +129,13 @@
 }
 
 static void rtas_ibm_create_pe_dma_window(PowerPCCPU *cpu,
-                                          sPAPRMachineState *spapr,
+                                          SpaprMachineState *spapr,
                                           uint32_t token, uint32_t nargs,
                                           target_ulong args,
                                           uint32_t nret, target_ulong rets)
 {
-    sPAPRPHBState *sphb;
-    sPAPRTCETable *tcet = NULL;
+    SpaprPhbState *sphb;
+    SpaprTceTable *tcet = NULL;
     uint32_t addr, page_shift, window_shift, liobn;
     uint64_t buid, win_addr;
     int windows;
@@ -171,8 +171,18 @@
     }
 
     win_addr = (windows == 0) ? sphb->dma_win_addr : sphb->dma64_win_addr;
+    /*
+     * We have just created a window, we know for the fact that it is empty,
+     * use a hack to avoid iterating over the table as it is quite possible
+     * to have billions of TCEs, all empty.
+     * Note that we cannot delay this to the first H_PUT_TCE as this hcall is
+     * mostly likely to be handled in KVM so QEMU just does not know if it
+     * happened.
+     */
+    tcet->skipping_replay = true;
     spapr_tce_table_enable(tcet, page_shift, win_addr,
                            1ULL << (window_shift - page_shift));
+    tcet->skipping_replay = false;
     if (!tcet->nb_table) {
         goto hw_error_exit;
     }
@@ -196,13 +206,13 @@
 }
 
 static void rtas_ibm_remove_pe_dma_window(PowerPCCPU *cpu,
-                                          sPAPRMachineState *spapr,
+                                          SpaprMachineState *spapr,
                                           uint32_t token, uint32_t nargs,
                                           target_ulong args,
                                           uint32_t nret, target_ulong rets)
 {
-    sPAPRPHBState *sphb;
-    sPAPRTCETable *tcet;
+    SpaprPhbState *sphb;
+    SpaprTceTable *tcet;
     uint32_t liobn;
 
     if ((nargs != 1) || (nret != 1)) {
@@ -231,12 +241,12 @@
 }
 
 static void rtas_ibm_reset_pe_dma_window(PowerPCCPU *cpu,
-                                         sPAPRMachineState *spapr,
+                                         SpaprMachineState *spapr,
                                          uint32_t token, uint32_t nargs,
                                          target_ulong args,
                                          uint32_t nret, target_ulong rets)
 {
-    sPAPRPHBState *sphb;
+    SpaprPhbState *sphb;
     uint64_t buid;
     uint32_t addr;
 
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index eb95a70..d732a3e 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -34,7 +34,7 @@
 #include "qapi/qapi-events-target.h"
 #include "qemu/cutils.h"
 
-void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns)
+void spapr_rtc_read(SpaprRtcState *rtc, struct tm *tm, uint32_t *ns)
 {
     int64_t host_ns = qemu_clock_get_ns(rtc_clock);
     int64_t guest_ns;
@@ -53,7 +53,7 @@
     }
 }
 
-int spapr_rtc_import_offset(sPAPRRTCState *rtc, int64_t legacy_offset)
+int spapr_rtc_import_offset(SpaprRtcState *rtc, int64_t legacy_offset)
 {
     if (!rtc) {
         return -ENODEV;
@@ -64,7 +64,7 @@
     return 0;
 }
 
-static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_get_time_of_day(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
@@ -89,12 +89,12 @@
     rtas_st(rets, 7, ns);
 }
 
-static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_set_time_of_day(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args,
                                  uint32_t nret, target_ulong rets)
 {
-    sPAPRRTCState *rtc = &spapr->rtc;
+    SpaprRtcState *rtc = &spapr->rtc;
     struct tm tm;
     time_t new_s;
     int64_t host_ns;
@@ -134,7 +134,7 @@
 
 static void spapr_rtc_realize(DeviceState *dev, Error **errp)
 {
-    sPAPRRTCState *rtc = SPAPR_RTC(dev);
+    SpaprRtcState *rtc = SPAPR_RTC(dev);
     struct tm tm;
     time_t host_s;
     int64_t rtc_ns;
@@ -154,7 +154,7 @@
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_INT64(ns_offset, sPAPRRTCState),
+        VMSTATE_INT64(ns_offset, SpaprRtcState),
         VMSTATE_END_OF_LIST()
     },
 };
@@ -177,7 +177,7 @@
 static const TypeInfo spapr_rtc_info = {
     .name          = TYPE_SPAPR_RTC,
     .parent        = TYPE_DEVICE,
-    .instance_size = sizeof(sPAPRRTCState),
+    .instance_size = sizeof(SpaprRtcState),
     .class_init    = spapr_rtc_class_init,
 };
 
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 2b7e7ec..583c13d 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -46,8 +46,8 @@
 
 static char *spapr_vio_get_dev_name(DeviceState *qdev)
 {
-    VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    SpaprVioDevice *dev = VIO_SPAPR_DEVICE(qdev);
+    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 
     /* Device tree style name device@reg */
     return g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
@@ -65,16 +65,16 @@
     .name = TYPE_SPAPR_VIO_BUS,
     .parent = TYPE_BUS,
     .class_init = spapr_vio_bus_class_init,
-    .instance_size = sizeof(VIOsPAPRBus),
+    .instance_size = sizeof(SpaprVioBus),
 };
 
-VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
+SpaprVioDevice *spapr_vio_find_by_reg(SpaprVioBus *bus, uint32_t reg)
 {
     BusChild *kid;
-    VIOsPAPRDevice *dev = NULL;
+    SpaprVioDevice *dev = NULL;
 
     QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)kid->child;
+        dev = (SpaprVioDevice *)kid->child;
         if (dev->reg == reg) {
             return dev;
         }
@@ -83,10 +83,10 @@
     return NULL;
 }
 
-static int vio_make_devnode(VIOsPAPRDevice *dev,
+static int vio_make_devnode(SpaprVioDevice *dev,
                             void *fdt)
 {
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
     int vdevice_off, node_off, ret;
     char *dt_name;
 
@@ -152,13 +152,13 @@
 /*
  * CRQ handling
  */
-static target_ulong h_reg_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_reg_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                               target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong queue_addr = args[1];
     target_ulong queue_len = args[2];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 
     if (!dev) {
         hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
@@ -197,7 +197,7 @@
     return H_SUCCESS;
 }
 
-static target_ulong free_crq(VIOsPAPRDevice *dev)
+static target_ulong free_crq(SpaprVioDevice *dev)
 {
     dev->crq.qladdr = 0;
     dev->crq.qsize = 0;
@@ -208,11 +208,11 @@
     return H_SUCCESS;
 }
 
-static target_ulong h_free_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_free_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 
     if (!dev) {
         hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
@@ -222,13 +222,13 @@
     return free_crq(dev);
 }
 
-static target_ulong h_send_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_send_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong msg_hi = args[1];
     target_ulong msg_lo = args[2];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
     uint64_t crq_mangle[2];
 
     if (!dev) {
@@ -245,11 +245,11 @@
     return H_HARDWARE;
 }
 
-static target_ulong h_enable_crq(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_enable_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                  target_ulong opcode, target_ulong *args)
 {
     target_ulong reg = args[0];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
 
     if (!dev) {
         hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
@@ -260,7 +260,7 @@
 }
 
 /* Returns negative error, 0 success, or positive: queue full */
-int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
+int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
 {
     int rc;
     uint8_t byte;
@@ -303,7 +303,7 @@
 
 /* "quiesce" handling */
 
-static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
+static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
 {
     if (dev->tcet) {
         device_reset(DEVICE(dev->tcet));
@@ -311,7 +311,7 @@
     free_crq(dev);
 }
 
-void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass)
+void spapr_vio_set_bypass(SpaprVioDevice *dev, bool bypass)
 {
     if (!dev->tcet) {
         return;
@@ -323,13 +323,13 @@
     dev->tcet->bypass = bypass;
 }
 
-static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_set_tce_bypass(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 uint32_t token,
                                 uint32_t nargs, target_ulong args,
                                 uint32_t nret, target_ulong rets)
 {
-    VIOsPAPRBus *bus = spapr->vio_bus;
-    VIOsPAPRDevice *dev;
+    SpaprVioBus *bus = spapr->vio_bus;
+    SpaprVioDevice *dev;
     uint32_t unit, enable;
 
     if (nargs != 2) {
@@ -354,14 +354,14 @@
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static void rtas_quiesce(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static void rtas_quiesce(PowerPCCPU *cpu, SpaprMachineState *spapr,
                          uint32_t token,
                          uint32_t nargs, target_ulong args,
                          uint32_t nret, target_ulong rets)
 {
-    VIOsPAPRBus *bus = spapr->vio_bus;
+    SpaprVioBus *bus = spapr->vio_bus;
     BusChild *kid;
-    VIOsPAPRDevice *dev = NULL;
+    SpaprVioDevice *dev = NULL;
 
     if (nargs != 0) {
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -369,18 +369,18 @@
     }
 
     QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)kid->child;
+        dev = (SpaprVioDevice *)kid->child;
         spapr_vio_quiesce_one(dev);
     }
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
 
-static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
+static SpaprVioDevice *reg_conflict(SpaprVioDevice *dev)
 {
-    VIOsPAPRBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);
+    SpaprVioBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);
     BusChild *kid;
-    VIOsPAPRDevice *other;
+    SpaprVioDevice *other;
 
     /*
      * Check for a device other than the given one which is already
@@ -400,8 +400,8 @@
 
 static void spapr_vio_busdev_reset(DeviceState *qdev)
 {
-    VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    SpaprVioDevice *dev = VIO_SPAPR_DEVICE(qdev);
+    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 
     /* Shut down the request queue and TCEs if necessary */
     spapr_vio_quiesce_one(dev);
@@ -465,9 +465,9 @@
 
 static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
-    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprVioDevice *dev = (SpaprVioDevice *)qdev;
+    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
     char *id;
     Error *local_err = NULL;
 
@@ -478,7 +478,7 @@
          * rather than using spapr_vio_find_by_reg() because sdev
          * itself is already in the list.
          */
-        VIOsPAPRDevice *other = reg_conflict(dev);
+        SpaprVioDevice *other = reg_conflict(dev);
 
         if (other) {
             error_setg(errp, "%s and %s devices conflict at address %#x",
@@ -489,7 +489,7 @@
         }
     } else {
         /* Need to assign an address */
-        VIOsPAPRBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);
+        SpaprVioBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);
 
         do {
             dev->reg = bus->next_reg++;
@@ -540,14 +540,14 @@
     pc->realize(dev, errp);
 }
 
-static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPRMachineState *spapr,
+static target_ulong h_vio_signal(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                  target_ulong opcode,
                                  target_ulong *args)
 {
     target_ulong reg = args[0];
     target_ulong mode = args[1];
-    VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
-    VIOsPAPRDeviceClass *pc;
+    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+    SpaprVioDeviceClass *pc;
 
     if (!dev) {
         return H_PARAMETER;
@@ -564,9 +564,9 @@
     return H_SUCCESS;
 }
 
-VIOsPAPRBus *spapr_vio_bus_init(void)
+SpaprVioBus *spapr_vio_bus_init(void)
 {
-    VIOsPAPRBus *bus;
+    SpaprVioBus *bus;
     BusState *qbus;
     DeviceState *dev;
 
@@ -615,14 +615,14 @@
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         /* Sanity check */
-        VMSTATE_UINT32_EQUAL(reg, VIOsPAPRDevice, NULL),
-        VMSTATE_UINT32_EQUAL(irq, VIOsPAPRDevice, NULL),
+        VMSTATE_UINT32_EQUAL(reg, SpaprVioDevice, NULL),
+        VMSTATE_UINT32_EQUAL(irq, SpaprVioDevice, NULL),
 
         /* General VIO device state */
-        VMSTATE_UINT64(signal_state, VIOsPAPRDevice),
-        VMSTATE_UINT64(crq.qladdr, VIOsPAPRDevice),
-        VMSTATE_UINT32(crq.qsize, VIOsPAPRDevice),
-        VMSTATE_UINT32(crq.qnext, VIOsPAPRDevice),
+        VMSTATE_UINT64(signal_state, SpaprVioDevice),
+        VMSTATE_UINT64(crq.qladdr, SpaprVioDevice),
+        VMSTATE_UINT32(crq.qsize, SpaprVioDevice),
+        VMSTATE_UINT32(crq.qnext, SpaprVioDevice),
 
         VMSTATE_END_OF_LIST()
     },
@@ -639,9 +639,9 @@
 static const TypeInfo spapr_vio_type_info = {
     .name = TYPE_VIO_SPAPR_DEVICE,
     .parent = TYPE_DEVICE,
-    .instance_size = sizeof(VIOsPAPRDevice),
+    .instance_size = sizeof(SpaprVioDevice),
     .abstract = true,
-    .class_size = sizeof(VIOsPAPRDeviceClass),
+    .class_size = sizeof(SpaprVioDeviceClass),
     .class_init = vio_spapr_device_class_init,
 };
 
@@ -656,10 +656,10 @@
 
 static int compare_reg(const void *p1, const void *p2)
 {
-    VIOsPAPRDevice const *dev1, *dev2;
+    SpaprVioDevice const *dev1, *dev2;
 
-    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
-    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
+    dev1 = (SpaprVioDevice *)*(DeviceState **)p1;
+    dev2 = (SpaprVioDevice *)*(DeviceState **)p2;
 
     if (dev1->reg < dev2->reg) {
         return -1;
@@ -672,7 +672,7 @@
     return 1;
 }
 
-void spapr_dt_vdevice(VIOsPAPRBus *bus, void *fdt)
+void spapr_dt_vdevice(SpaprVioBus *bus, void *fdt)
 {
     DeviceState *qdev, **qdevs;
     BusChild *kid;
@@ -707,8 +707,8 @@
     /* Hack alert. Give the devices to libfdt in reverse order, we happen
      * to know that will mean they are in forward order in the tree. */
     for (i = num - 1; i >= 0; i--) {
-        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
-        VIOsPAPRDeviceClass *vdc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+        SpaprVioDevice *dev = (SpaprVioDevice *)(qdevs[i]);
+        SpaprVioDeviceClass *vdc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
 
         ret = vio_make_devnode(dev, fdt);
         if (ret < 0) {
@@ -721,9 +721,9 @@
     g_free(qdevs);
 }
 
-gchar *spapr_vio_stdout_path(VIOsPAPRBus *bus)
+gchar *spapr_vio_stdout_path(SpaprVioBus *bus)
 {
-    VIOsPAPRDevice *dev;
+    SpaprVioDevice *dev;
     char *name, *path;
 
     dev = spapr_vty_get_default(bus);
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 26e2312..0e4c740 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -226,10 +226,9 @@
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(PFLASH_BASEADDR, NULL, "virtex.flash", FLASH_SIZE,
+    pflash_cfi01_register(PFLASH_BASEADDR, "virtex.flash", FLASH_SIZE,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          64 * KiB, FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+                          64 * KiB, 1, 0x89, 0x18, 0x0000, 0x0, 1);
 
     cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
     dev = qdev_create(NULL, "xlnx.xps-intc");
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index e0ee304..8c7fc1f 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -26,6 +26,9 @@
 
 config RISCV_VIRT
     bool
+    imply PCI_DEVICES
+    imply TEST_DEVICES
+    select PCI
     select HART
     select SERIAL
     select VIRTIO_MMIO
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 89def14..da7239d 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -160,6 +160,11 @@
 #define LSI_CCNTL1_DDAC      0x08
 #define LSI_CCNTL1_ZMOD      0x80
 
+#define LSI_SBCL_ATN         0x08
+#define LSI_SBCL_BSY         0x20
+#define LSI_SBCL_ACK         0x40
+#define LSI_SBCL_REQ         0x80
+
 /* Enable Response to Reselection */
 #define LSI_SCID_RRE      0x60
 
@@ -189,6 +194,20 @@
     QTAILQ_ENTRY(lsi_request) next;
 } lsi_request;
 
+enum {
+    LSI_NOWAIT, /* SCRIPTS are running or stopped */
+    LSI_WAIT_RESELECT, /* Wait Reselect instruction has been issued */
+    LSI_DMA_SCRIPTS, /* processing DMA from lsi_execute_script */
+    LSI_DMA_IN_PROGRESS, /* DMA operation is in progress */
+};
+
+enum {
+    LSI_MSG_ACTION_COMMAND = 0,
+    LSI_MSG_ACTION_DISCONNECT = 1,
+    LSI_MSG_ACTION_DOUT = 2,
+    LSI_MSG_ACTION_DIN = 3,
+};
+
 typedef struct {
     /*< private >*/
     PCIDevice parent_obj;
@@ -202,15 +221,9 @@
 
     int carry; /* ??? Should this be an a visible register somewhere?  */
     int status;
-    /* Action to take at the end of a MSG IN phase.
-       0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN.  */
     int msg_action;
     int msg_len;
     uint8_t msg[LSI_MAX_MSGIN_LEN];
-    /* 0 if SCRIPTS are running or stopped.
-     * 1 if a Wait Reselect instruction has been issued.
-     * 2 if processing DMA from lsi_execute_script.
-     * 3 if a DMA operation is in progress.  */
     int waiting;
     SCSIBus bus;
     int current_lun;
@@ -258,6 +271,7 @@
     uint8_t sdid;
     uint8_t ssid;
     uint8_t sfbr;
+    uint8_t sbcl;
     uint8_t stest1;
     uint8_t stest2;
     uint8_t stest3;
@@ -283,8 +297,7 @@
     uint8_t sbr;
     uint32_t adder;
 
-    /* Script ram is stored as 32-bit words in host byteorder.  */
-    uint32_t script_ram[2048];
+    uint8_t script_ram[2048 * sizeof(uint32_t)];
 } LSIState;
 
 #define TYPE_LSI53C810  "lsi53c810"
@@ -293,6 +306,22 @@
 #define LSI53C895A(obj) \
     OBJECT_CHECK(LSIState, (obj), TYPE_LSI53C895A)
 
+static const char *scsi_phases[] = {
+    "DOUT",
+    "DIN",
+    "CMD",
+    "STATUS",
+    "RSVOUT",
+    "RSVIN",
+    "MSGOUT",
+    "MSGIN"
+};
+
+static const char *scsi_phase_name(int phase)
+{
+    return scsi_phases[phase & PHASE_MASK];
+}
+
 static inline int lsi_irq_on_rsl(LSIState *s)
 {
     return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE);
@@ -315,9 +344,9 @@
     trace_lsi_reset();
     s->carry = 0;
 
-    s->msg_action = 0;
+    s->msg_action = LSI_MSG_ACTION_COMMAND;
     s->msg_len = 0;
-    s->waiting = 0;
+    s->waiting = LSI_NOWAIT;
     s->dsa = 0;
     s->dnad = 0;
     s->dbc = 0;
@@ -356,6 +385,7 @@
     s->socl = 0;
     s->sdid = 0;
     s->ssid = 0;
+    s->sbcl = 0;
     s->stest1 = 0;
     s->stest2 = 0;
     s->stest3 = 0;
@@ -530,6 +560,8 @@
 
 static inline void lsi_set_phase(LSIState *s, int phase)
 {
+    s->sbcl &= ~PHASE_MASK;
+    s->sbcl |= phase | LSI_SBCL_REQ;
     s->sstat1 = (s->sstat1 & ~PHASE_MASK) | phase;
 }
 
@@ -556,10 +588,10 @@
 static void lsi_resume_script(LSIState *s)
 {
     if (s->waiting != 2) {
-        s->waiting = 0;
+        s->waiting = LSI_NOWAIT;
         lsi_execute_script(s);
     } else {
-        s->waiting = 0;
+        s->waiting = LSI_NOWAIT;
     }
 }
 
@@ -567,6 +599,7 @@
 {
     s->scntl1 &= ~LSI_SCNTL1_CON;
     s->sstat1 &= ~PHASE_MASK;
+    s->sbcl = 0;
 }
 
 static void lsi_bad_selection(LSIState *s, uint32_t id)
@@ -674,7 +707,7 @@
     trace_lsi_reselect(id);
     s->scntl1 |= LSI_SCNTL1_CON;
     lsi_set_phase(s, PHASE_MI);
-    s->msg_action = p->out ? 2 : 3;
+    s->msg_action = p->out ? LSI_MSG_ACTION_DOUT : LSI_MSG_ACTION_DIN;
     s->current->dma_len = p->pending;
     lsi_add_msg_byte(s, 0x80);
     if (s->current->tag & LSI_TAG_VALID) {
@@ -735,7 +768,7 @@
        Since no interrupt stacking is implemented in the emulation, it
        is also required that there are no pending interrupts waiting
        for service from the device driver. */
-    if (s->waiting == 1 ||
+    if (s->waiting == LSI_WAIT_RESELECT ||
         (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON) &&
          !(s->istat0 & (LSI_ISTAT0_SIP | LSI_ISTAT0_DIP)))) {
         /* Reselect device.  */
@@ -780,7 +813,7 @@
     int out;
 
     assert(req->hba_private);
-    if (s->waiting == 1 || req->hba_private != s->current ||
+    if (s->waiting == LSI_WAIT_RESELECT || req->hba_private != s->current ||
         (lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON))) {
         if (lsi_queue_req(s, req, len)) {
             return;
@@ -794,7 +827,7 @@
     s->current->dma_len = len;
     s->command_complete = 1;
     if (s->waiting) {
-        if (s->waiting == 1 || s->dbc == 0) {
+        if (s->waiting == LSI_WAIT_RESELECT || s->dbc == 0) {
             lsi_resume_script(s);
         } else {
             lsi_do_dma(s, out);
@@ -845,7 +878,7 @@
             lsi_add_msg_byte(s, 4); /* DISCONNECT */
             /* wait data */
             lsi_set_phase(s, PHASE_MI);
-            s->msg_action = 1;
+            s->msg_action = LSI_MSG_ACTION_DISCONNECT;
             lsi_queue_command(s);
         } else {
             /* wait command complete */
@@ -866,7 +899,7 @@
     s->sfbr = status;
     pci_dma_write(PCI_DEVICE(s), s->dnad, &status, 1);
     lsi_set_phase(s, PHASE_MI);
-    s->msg_action = 1;
+    s->msg_action = LSI_MSG_ACTION_DISCONNECT;
     lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */
 }
 
@@ -889,16 +922,16 @@
         /* ??? Check if ATN (not yet implemented) is asserted and maybe
            switch to PHASE_MO.  */
         switch (s->msg_action) {
-        case 0:
+        case LSI_MSG_ACTION_COMMAND:
             lsi_set_phase(s, PHASE_CMD);
             break;
-        case 1:
+        case LSI_MSG_ACTION_DISCONNECT:
             lsi_disconnect(s);
             break;
-        case 2:
+        case LSI_MSG_ACTION_DOUT:
             lsi_set_phase(s, PHASE_DO);
             break;
-        case 3:
+        case LSI_MSG_ACTION_DIN:
             lsi_set_phase(s, PHASE_DI);
             break;
         default:
@@ -1050,7 +1083,7 @@
     qemu_log_mask(LOG_UNIMP, "Unimplemented message 0x%02x\n", msg);
     lsi_set_phase(s, PHASE_MI);
     lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */
-    s->msg_action = 0;
+    s->msg_action = LSI_MSG_ACTION_COMMAND;
 }
 
 #define LSI_BUF_SIZE 4096
@@ -1084,7 +1117,7 @@
         lsi_reselect(s, p);
     }
     if (s->current == NULL) {
-        s->waiting = 1;
+        s->waiting = LSI_WAIT_RESELECT;
     }
 }
 
@@ -1184,8 +1217,9 @@
             s->ia = s->dsp - 12;
         }
         if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
-            trace_lsi_execute_script_blockmove_badphase(s->sstat1 & PHASE_MASK,
-                                                        (insn >> 24) & 7);
+            trace_lsi_execute_script_blockmove_badphase(
+                    scsi_phase_name(s->sstat1),
+                    scsi_phase_name(insn >> 24));
             lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
             break;
         }
@@ -1193,16 +1227,16 @@
         s->dnad64 = addr_high;
         switch (s->sstat1 & 0x7) {
         case PHASE_DO:
-            s->waiting = 2;
+            s->waiting = LSI_DMA_SCRIPTS;
             lsi_do_dma(s, 1);
             if (s->waiting)
-                s->waiting = 3;
+                s->waiting = LSI_DMA_IN_PROGRESS;
             break;
         case PHASE_DI:
-            s->waiting = 2;
+            s->waiting = LSI_DMA_SCRIPTS;
             lsi_do_dma(s, 0);
             if (s->waiting)
-                s->waiting = 3;
+                s->waiting = LSI_DMA_IN_PROGRESS;
             break;
         case PHASE_CMD:
             lsi_do_command(s);
@@ -1217,8 +1251,8 @@
             lsi_do_msgin(s);
             break;
         default:
-            qemu_log_mask(LOG_UNIMP, "lsi_scsi: Unimplemented phase %d\n",
-                          s->sstat1 & PHASE_MASK);
+            qemu_log_mask(LOG_UNIMP, "lsi_scsi: Unimplemented phase %s\n",
+                          scsi_phase_name(s->sstat1));
         }
         s->dfifo = s->dbc & 0xff;
         s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3);
@@ -1265,8 +1299,11 @@
                 s->scntl1 |= LSI_SCNTL1_CON;
                 if (insn & (1 << 3)) {
                     s->socl |= LSI_SOCL_ATN;
+                    s->sbcl |= LSI_SBCL_ATN;
                 }
+                s->sbcl |= LSI_SBCL_BSY;
                 lsi_set_phase(s, PHASE_MO);
+                s->waiting = LSI_NOWAIT;
                 break;
             case 1: /* Disconnect */
                 trace_lsi_execute_script_io_disconnect();
@@ -1285,8 +1322,10 @@
                 }
                 break;
             case 2: /* Wait Reselect */
-                if (!lsi_irq_on_rsl(s)) {
-                    lsi_wait_reselect(s);
+                if (s->istat0 & LSI_ISTAT0_SIGP) {
+                    s->dsp = s->dnad;
+                } else if (!lsi_irq_on_rsl(s)) {
+                        lsi_wait_reselect(s);
                 }
                 break;
             case 3: /* Set */
@@ -1297,8 +1336,14 @@
                         insn & (1 << 10) ? " CC" : "");
                 if (insn & (1 << 3)) {
                     s->socl |= LSI_SOCL_ATN;
+                    s->sbcl |= LSI_SBCL_ATN;
                     lsi_set_phase(s, PHASE_MO);
                 }
+
+                if (insn & (1 << 6)) {
+                    s->sbcl |= LSI_SBCL_ACK;
+                }
+
                 if (insn & (1 << 9)) {
                     qemu_log_mask(LOG_UNIMP,
                         "lsi_scsi: Target mode not implemented\n");
@@ -1314,7 +1359,13 @@
                         insn & (1 << 10) ? " CC" : "");
                 if (insn & (1 << 3)) {
                     s->socl &= ~LSI_SOCL_ATN;
+                    s->sbcl &= ~LSI_SBCL_ATN;
                 }
+
+                if (insn & (1 << 6)) {
+                    s->sbcl &= ~LSI_SBCL_ACK;
+                }
+
                 if (insn & (1 << 10))
                     s->carry = 0;
                 break;
@@ -1429,10 +1480,8 @@
                 cond = s->carry != 0;
             }
             if (cond == jmp && (insn & (1 << 17))) {
-                trace_lsi_execute_script_tc_compp(
-                        (s->sstat1 & PHASE_MASK),
-                        jmp ? '=' : '!',
-                        ((insn >> 24) & 7));
+                trace_lsi_execute_script_tc_compp(scsi_phase_name(s->sstat1),
+                        jmp ? '=' : '!', scsi_phase_name(insn >> 24));
                 cond = (s->sstat1 & PHASE_MASK) == ((insn >> 24) & 7);
             }
             if (cond == jmp && (insn & (1 << 18))) {
@@ -1519,7 +1568,7 @@
             }
         }
     }
-    if (insn_processed > 10000 && !s->waiting) {
+    if (insn_processed > 10000 && s->waiting == LSI_NOWAIT) {
         /* Some windows drivers make the device spin waiting for a memory
            location to change.  If we have been executed a lot of code then
            assume this is the case and force an unexpected device disconnect.
@@ -1531,7 +1580,7 @@
         }
         lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
         lsi_disconnect(s);
-    } else if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) {
+    } else if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) {
         if (s->dcntl & LSI_DCNTL_SSM) {
             lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
         } else {
@@ -1591,9 +1640,7 @@
         ret = s->ssid;
         break;
     case 0xb: /* SBCL */
-        /* ??? This is not correct. However it's (hopefully) only
-           used for diagnostics, so should be ok.  */
-        ret = 0;
+        ret = s->sbcl;
         break;
     case 0xc: /* DSTAT */
         ret = s->dstat | LSI_DSTAT_DFE;
@@ -1641,7 +1688,7 @@
         break;
     CASE_GET_REG32(temp, 0x1c)
     case 0x20: /* DFIFO */
-        ret = 0;
+        ret = s->dfifo;
         break;
     case 0x21: /* CTEST4 */
         ret = s->ctest4;
@@ -1864,9 +1911,9 @@
             s->istat0 &= ~LSI_ISTAT0_INTF;
             lsi_update_irq(s);
         }
-        if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) {
+        if (s->waiting == LSI_WAIT_RESELECT && val & LSI_ISTAT0_SIGP) {
             trace_lsi_awoken();
-            s->waiting = 0;
+            s->waiting = LSI_NOWAIT;
             s->dsp = s->dnad;
             lsi_execute_script(s);
         }
@@ -2037,14 +2084,13 @@
                               unsigned size)
 {
     LSIState *s = opaque;
-
     return lsi_reg_readb(s, addr & 0xff);
 }
 
 static const MemoryRegionOps lsi_mmio_ops = {
     .read = lsi_mmio_read,
     .write = lsi_mmio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
     .impl = {
         .min_access_size = 1,
         .max_access_size = 1,
@@ -2055,35 +2101,20 @@
                           uint64_t val, unsigned size)
 {
     LSIState *s = opaque;
-    uint32_t newval;
-    uint32_t mask;
-    int shift;
-
-    newval = s->script_ram[addr >> 2];
-    shift = (addr & 3) * 8;
-    mask = ((uint64_t)1 << (size * 8)) - 1;
-    newval &= ~(mask << shift);
-    newval |= val << shift;
-    s->script_ram[addr >> 2] = newval;
+    stn_le_p(s->script_ram + addr, size, val);
 }
 
 static uint64_t lsi_ram_read(void *opaque, hwaddr addr,
                              unsigned size)
 {
     LSIState *s = opaque;
-    uint32_t val;
-    uint32_t mask;
-
-    val = s->script_ram[addr >> 2];
-    mask = ((uint64_t)1 << (size * 8)) - 1;
-    val >>= (addr & 3) * 8;
-    return val & mask;
+    return ldn_le_p(s->script_ram + addr, size);
 }
 
 static const MemoryRegionOps lsi_ram_ops = {
     .read = lsi_ram_read,
     .write = lsi_ram_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static uint64_t lsi_io_read(void *opaque, hwaddr addr,
@@ -2103,7 +2134,7 @@
 static const MemoryRegionOps lsi_io_ops = {
     .read = lsi_io_read,
     .write = lsi_io_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
     .impl = {
         .min_access_size = 1,
         .max_access_size = 1,
@@ -2143,7 +2174,7 @@
 
 static const VMStateDescription vmstate_lsi_scsi = {
     .name = "lsiscsi",
-    .version_id = 0,
+    .version_id = 1,
     .minimum_version_id = 0,
     .pre_save = lsi_pre_save,
     .post_load = lsi_post_load,
@@ -2202,6 +2233,7 @@
         VMSTATE_UINT8(stime0, LSIState),
         VMSTATE_UINT8(respid0, LSIState),
         VMSTATE_UINT8(respid1, LSIState),
+        VMSTATE_UINT8_V(sbcl, LSIState, 1),
         VMSTATE_UINT32(mmrs, LSIState),
         VMSTATE_UINT32(mmws, LSIState),
         VMSTATE_UINT32(sfs, LSIState),
@@ -2219,7 +2251,7 @@
         VMSTATE_BUFFER_UNSAFE(scratch, LSIState, 0, 18 * sizeof(uint32_t)),
         VMSTATE_UINT8(sbr, LSIState),
 
-        VMSTATE_BUFFER_UNSAFE(script_ram, LSIState, 0, 2048 * sizeof(uint32_t)),
+        VMSTATE_BUFFER_UNSAFE(script_ram, LSIState, 0, 8192),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index d4e83ae..e7e865a 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -296,22 +296,15 @@
     aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
 }
 
-static void scsi_read_complete(void * opaque, int ret)
+static void scsi_read_complete_noio(SCSIDiskReq *r, int ret)
 {
-    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
-    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-    int n;
+    uint32_t n;
 
-    assert(r->req.aiocb != NULL);
-    r->req.aiocb = NULL;
-    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
-    if (scsi_disk_req_check_error(r, ret, true)) {
+    assert(r->req.aiocb == NULL);
+    if (scsi_disk_req_check_error(r, ret, false)) {
         goto done;
     }
 
-    block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
-    trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
-
     n = r->qiov.size / 512;
     r->sector += n;
     r->sector_count -= n;
@@ -319,6 +312,24 @@
 
 done:
     scsi_req_unref(&r->req);
+}
+
+static void scsi_read_complete(void *opaque, int ret)
+{
+    SCSIDiskReq *r = (SCSIDiskReq *)opaque;
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+    assert(r->req.aiocb != NULL);
+    r->req.aiocb = NULL;
+
+    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
+    if (ret < 0) {
+        block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
+    } else {
+        block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
+        trace_scsi_disk_read_complete(r->req.tag, r->qiov.size);
+    }
+    scsi_read_complete_noio(r, ret);
     aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
 }
 
@@ -395,12 +406,12 @@
     scsi_req_ref(&r->req);
     if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
         trace_scsi_disk_read_data_invalid();
-        scsi_read_complete(r, -EINVAL);
+        scsi_read_complete_noio(r, -EINVAL);
         return;
     }
 
     if (!blk_is_available(req->dev->conf.blk)) {
-        scsi_read_complete(r, -ENOMEDIUM);
+        scsi_read_complete_noio(r, -ENOMEDIUM);
         return;
     }
 
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index a9e49c7..26dfc03 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -91,7 +91,7 @@
      OBJECT_CHECK(VSCSIState, (obj), TYPE_VIO_SPAPR_VSCSI_DEVICE)
 
 typedef struct {
-    VIOsPAPRDevice vdev;
+    SpaprVioDevice vdev;
     SCSIBus bus;
     vscsi_req reqs[VSCSI_REQ_LIMIT];
 } VSCSIState;
@@ -1115,7 +1115,7 @@
 }
 
 
-static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
+static int vscsi_do_crq(struct SpaprVioDevice *dev, uint8_t *crq_data)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
     vscsi_crq crq;
@@ -1187,7 +1187,7 @@
     .load_request = vscsi_load_request,
 };
 
-static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
+static void spapr_vscsi_reset(SpaprVioDevice *dev)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
     int i;
@@ -1198,7 +1198,7 @@
     }
 }
 
-static void spapr_vscsi_realize(VIOsPAPRDevice *dev, Error **errp)
+static void spapr_vscsi_realize(SpaprVioDevice *dev, Error **errp)
 {
     VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
 
@@ -1208,7 +1208,7 @@
                  &vscsi_scsi_info, NULL);
 }
 
-void spapr_vscsi_create(VIOsPAPRBus *bus)
+void spapr_vscsi_create(SpaprVioBus *bus)
 {
     DeviceState *dev;
 
@@ -1218,7 +1218,7 @@
     scsi_bus_legacy_handle_cmdline(&VIO_SPAPR_VSCSI_DEVICE(dev)->bus);
 }
 
-static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+static int spapr_vscsi_devnode(SpaprVioDevice *dev, void *fdt, int node_off)
 {
     int ret;
 
@@ -1256,7 +1256,7 @@
 static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+    SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
 
     k->realize = spapr_vscsi_realize;
     k->reset = spapr_vscsi_reset;
diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
index 29aaa75..09f3fc3 100644
--- a/hw/scsi/trace-events
+++ b/hw/scsi/trace-events
@@ -268,7 +268,7 @@
 lsi_wait_reselect(void) "Wait Reselect"
 lsi_execute_script(uint32_t dsp, uint32_t insn, uint32_t addr) "SCRIPTS dsp=0x%"PRIx32" opcode 0x%"PRIx32" arg 0x%"PRIx32
 lsi_execute_script_blockmove_delayed(void) "Delayed select timeout"
-lsi_execute_script_blockmove_badphase(uint8_t phase, uint8_t expected) "Wrong phase got %d expected %d"
+lsi_execute_script_blockmove_badphase(const char *phase, const char *expected) "Wrong phase got %s expected %s"
 lsi_execute_script_io_alreadyreselected(void) "Already reselected, jumping to alternative address"
 lsi_execute_script_io_selected(uint8_t id, const char *atn) "Selected target %d%s"
 lsi_execute_script_io_disconnect(void) "Wait Disconnect"
@@ -278,8 +278,8 @@
 lsi_execute_script_tc_nop(void) "NOP"
 lsi_execute_script_tc_delayedselect_timeout(void) "Delayed select timeout"
 lsi_execute_script_tc_compc(int result) "Compare carry %d"
-lsi_execute_script_tc_compp(uint8_t phase, int op, uint8_t insn_phase) "Compare phase %d %c= %d"
-lsi_execute_script_tc_compd(uint32_t sfbr, uint8_t mask, int op, int result) "Compare data 0x%"PRIx32" & 0x%x %c= 0x%x"
+lsi_execute_script_tc_compp(const char *phase, char op, const char *insn_phase) "Compare phase %s %c= %s"
+lsi_execute_script_tc_compd(uint32_t sfbr, uint8_t mask, char op, int result) "Compare data 0x%"PRIx32" & 0x%x %c= 0x%x"
 lsi_execute_script_tc_jump(uint32_t addr) "Jump to 0x%"PRIx32
 lsi_execute_script_tc_call(uint32_t addr) "Call 0x%"PRIx32
 lsi_execute_script_tc_return(uint32_t addr) "Return to 0x%"PRIx32
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index ce99d28..839f120 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -262,7 +262,13 @@
     /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
     req->resp.tmf.response = VIRTIO_SCSI_S_OK;
 
-    virtio_tswap32s(VIRTIO_DEVICE(s), &req->req.tmf.subtype);
+    /*
+     * req->req.tmf has the QEMU_PACKED attribute. Don't use virtio_tswap32s()
+     * to avoid compiler errors.
+     */
+    req->req.tmf.subtype =
+        virtio_tswap32(VIRTIO_DEVICE(s), req->req.tmf.subtype);
+
     switch (req->req.tmf.subtype) {
     case VIRTIO_SCSI_T_TMF_ABORT_TASK:
     case VIRTIO_SCSI_T_TMF_QUERY_TASK:
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 28ed6be..0bcb769 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -43,7 +43,7 @@
 #include "exec/address-spaces.h"
 
 #define FLASH_BASE 0x00000000
-#define FLASH_SIZE 0x02000000
+#define FLASH_SIZE (16 * MiB)
 
 #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
 #define SDRAM_SIZE 0x04000000
@@ -287,12 +287,19 @@
     sysbus_mmio_map(busdev, 1, 0x1400080c);
     mmio_ide_init_drives(dev, dinfo, NULL);
 
-    /* onboard flash memory */
+    /*
+     * Onboard flash memory
+     * According to the old board user document in Japanese (under
+     * NDA) what is referred to as FROM (Area0) is connected via a
+     * 32-bit bus and CS0 to CN8. The docs mention a Cypress
+     * S29PL127J60TFI130 chipsset.  Per the 'S29PL-J 002-00615
+     * Rev. *E' datasheet, it is a 128Mbit NOR parallel flash
+     * addressable in words of 16bit.
+     */
     dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
+    pflash_cfi02_register(0x0, "r2d.flash", FLASH_SIZE,
                           dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
-                          16 * KiB, FLASH_SIZE >> 16,
-                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
+                          64 * KiB, 1, 2, 0x0001, 0x227e, 0x2220, 0x2200,
                           0x555, 0x2aa, 0);
 
     /* NIC: rtl8139 on-board, and 2 slots. */
diff --git a/hw/vfio/Kconfig b/hw/vfio/Kconfig
index ebda9fd..34da2a3 100644
--- a/hw/vfio/Kconfig
+++ b/hw/vfio/Kconfig
@@ -4,8 +4,9 @@
 
 config VFIO_PCI
     bool
+    default y
     select VFIO
-    depends on LINUX
+    depends on LINUX && PCI
 
 config VFIO_CCW
     bool
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index df2b472..4374cc6 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -729,7 +729,7 @@
     }
 }
 
-static struct vfio_info_cap_header *
+struct vfio_info_cap_header *
 vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id)
 {
     struct vfio_info_cap_header *hdr;
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index becf71a..57fe758 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -143,19 +143,19 @@
                              MemoryRegionSection *section,
                              hwaddr *pgsize)
 {
-    int ret;
+    int ret = 0;
     IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
     uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
-    unsigned entries, pages;
+    unsigned entries, bits_total, bits_per_level, max_levels;
     struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
-    long systempagesize = qemu_getrampagesize();
+    long rampagesize = qemu_getrampagesize();
 
     /*
      * The host might not support the guest supported IOMMU page size,
      * so we will use smaller physical IOMMU pages to back them.
      */
-    if (pagesize > systempagesize) {
-        pagesize = systempagesize;
+    if (pagesize > rampagesize) {
+        pagesize = rampagesize;
     }
     pagesize = 1ULL << (63 - clz64(container->pgsizes &
                                    (pagesize | (pagesize - 1))));
@@ -176,16 +176,38 @@
     create.window_size = int128_get64(section->size);
     create.page_shift = ctz64(pagesize);
     /*
-     * SPAPR host supports multilevel TCE tables, there is some
-     * heuristic to decide how many levels we want for our table:
-     * 0..64 = 1; 65..4096 = 2; 4097..262144 = 3; 262145.. = 4
+     * SPAPR host supports multilevel TCE tables. We try to guess optimal
+     * levels number and if this fails (for example due to the host memory
+     * fragmentation), we increase levels. The DMA address structure is:
+     * rrrrrrrr rxxxxxxx xxxxxxxx xxxxxxxx  xxxxxxxx xxxxxxxx xxxxxxxx iiiiiiii
+     * where:
+     *   r = reserved (bits >= 55 are reserved in the existing hardware)
+     *   i = IOMMU page offset (64K in this example)
+     *   x = bits to index a TCE which can be split to equal chunks to index
+     *      within the level.
+     * The aim is to split "x" to smaller possible number of levels.
      */
     entries = create.window_size >> create.page_shift;
-    pages = MAX((entries * sizeof(uint64_t)) / getpagesize(), 1);
-    pages = MAX(pow2ceil(pages), 1); /* Round up */
-    create.levels = ctz64(pages) / 6 + 1;
-
-    ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
+    /* bits_total is number of "x" needed */
+    bits_total = ctz64(entries * sizeof(uint64_t));
+    /*
+     * bits_per_level is a safe guess of how much we can allocate per level:
+     * 8 is the current minimum for CONFIG_FORCE_MAX_ZONEORDER and MAX_ORDER
+     * is usually bigger than that.
+     * Below we look at getpagesize() as TCEs are allocated from system pages.
+     */
+    bits_per_level = ctz64(getpagesize()) + 8;
+    create.levels = bits_total / bits_per_level;
+    if (bits_total % bits_per_level) {
+        ++create.levels;
+    }
+    max_levels = (64 - create.page_shift) / ctz64(getpagesize());
+    for ( ; create.levels <= max_levels; ++create.levels) {
+        ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
+        if (!ret) {
+            break;
+        }
+    }
     if (ret) {
         error_report("Failed to create a window, ret = %d (%m)", ret);
         return -errno;
@@ -200,6 +222,7 @@
         return -EINVAL;
     }
     trace_vfio_spapr_create_window(create.page_shift,
+                                   create.levels,
                                    create.window_size,
                                    create.start_addr);
     *pgsize = pagesize;
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index decbde4..2201972 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -129,7 +129,7 @@
 vfio_prereg_listener_region_del_skip(uint64_t start, uint64_t end) "0x%"PRIx64" - 0x%"PRIx64
 vfio_prereg_register(uint64_t va, uint64_t size, int ret) "va=0x%"PRIx64" size=0x%"PRIx64" ret=%d"
 vfio_prereg_unregister(uint64_t va, uint64_t size, int ret) "va=0x%"PRIx64" size=0x%"PRIx64" ret=%d"
-vfio_spapr_create_window(int ps, uint64_t ws, uint64_t off) "pageshift=0x%x winsize=0x%"PRIx64" offset=0x%"PRIx64
+vfio_spapr_create_window(int ps, unsigned int levels, uint64_t ws, uint64_t off) "pageshift=0x%x levels=%u winsize=0x%"PRIx64" offset=0x%"PRIx64
 vfio_spapr_remove_window(uint64_t off) "offset=0x%"PRIx64
 vfio_spapr_group_attach(int groupfd, int tablefd) "Attached groupfd %d to liobn fd %d"
 
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index ab3e52b..e05ef75 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -162,12 +162,12 @@
     memory_region_add_subregion(address_space, buffers, ram);
 }
 
-static pflash_t *xtfpga_flash_init(MemoryRegion *address_space,
-                                   const XtfpgaBoardDesc *board,
-                                   DriveInfo *dinfo, int be)
+static PFlashCFI01 *xtfpga_flash_init(MemoryRegion *address_space,
+                                      const XtfpgaBoardDesc *board,
+                                      DriveInfo *dinfo, int be)
 {
     SysBusDevice *s;
-    DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
+    DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
 
     qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
                         &error_abort);
@@ -181,7 +181,7 @@
     s = SYS_BUS_DEVICE(dev);
     memory_region_add_subregion(address_space, board->flash->base,
                                 sysbus_mmio_get_region(s, 0));
-    return OBJECT_CHECK(pflash_t, (dev), "cfi.pflash01");
+    return PFLASH_CFI01(dev);
 }
 
 static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
@@ -229,7 +229,7 @@
     XtensaMxPic *mx_pic = NULL;
     qemu_irq *extints;
     DriveInfo *dinfo;
-    pflash_t *flash = NULL;
+    PFlashCFI01 *flash = NULL;
     QemuOpts *machine_opts = qemu_get_machine_opts();
     const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
     const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
index 67c3aa3..a0f4887 100644
--- a/include/hw/block/flash.h
+++ b/include/hw/block/flash.h
@@ -5,32 +5,46 @@
 
 #include "exec/memory.h"
 
-#define TYPE_CFI_PFLASH01 "cfi.pflash01"
-#define TYPE_CFI_PFLASH02 "cfi.pflash02"
-
-typedef struct pflash_t pflash_t;
-
 /* pflash_cfi01.c */
-pflash_t *pflash_cfi01_register(hwaddr base,
-                                DeviceState *qdev, const char *name,
-                                hwaddr size,
-                                BlockBackend *blk,
-                                uint32_t sector_len, int nb_blocs, int width,
-                                uint16_t id0, uint16_t id1,
-                                uint16_t id2, uint16_t id3, int be);
+
+#define TYPE_PFLASH_CFI01 "cfi.pflash01"
+#define PFLASH_CFI01(obj) \
+    OBJECT_CHECK(PFlashCFI01, (obj), TYPE_PFLASH_CFI01)
+
+typedef struct PFlashCFI01 PFlashCFI01;
+
+PFlashCFI01 *pflash_cfi01_register(hwaddr base,
+                                   const char *name,
+                                   hwaddr size,
+                                   BlockBackend *blk,
+                                   uint32_t sector_len,
+                                   int width,
+                                   uint16_t id0, uint16_t id1,
+                                   uint16_t id2, uint16_t id3,
+                                   int be);
+BlockBackend *pflash_cfi01_get_blk(PFlashCFI01 *fl);
+MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl);
 
 /* pflash_cfi02.c */
-pflash_t *pflash_cfi02_register(hwaddr base,
-                                DeviceState *qdev, const char *name,
-                                hwaddr size,
-                                BlockBackend *blk, uint32_t sector_len,
-                                int nb_blocs, int nb_mappings, int width,
-                                uint16_t id0, uint16_t id1,
-                                uint16_t id2, uint16_t id3,
-                                uint16_t unlock_addr0, uint16_t unlock_addr1,
-                                int be);
 
-MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl);
+#define TYPE_PFLASH_CFI02 "cfi.pflash02"
+#define PFLASH_CFI02(obj) \
+    OBJECT_CHECK(PFlashCFI02, (obj), TYPE_PFLASH_CFI02)
+
+typedef struct PFlashCFI02 PFlashCFI02;
+
+PFlashCFI02 *pflash_cfi02_register(hwaddr base,
+                                   const char *name,
+                                   hwaddr size,
+                                   BlockBackend *blk,
+                                   uint32_t sector_len,
+                                   int nb_mappings,
+                                   int width,
+                                   uint16_t id0, uint16_t id1,
+                                   uint16_t id2, uint16_t id3,
+                                   uint16_t unlock_addr0,
+                                   uint16_t unlock_addr1,
+                                   int be);
 
 /* nand.c */
 DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 54222a2..276ff15 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -6,6 +6,7 @@
 #include "hw/boards.h"
 #include "hw/isa/isa.h"
 #include "hw/block/fdc.h"
+#include "hw/block/flash.h"
 #include "net/net.h"
 #include "hw/i386/ioapic.h"
 
@@ -39,6 +40,7 @@
     PCIBus *bus;
     FWCfgState *fw_cfg;
     qemu_irq *gsi;
+    PFlashCFI01 *flash[2];
 
     /* Configuration options: */
     uint64_t max_ram_below_4g;
@@ -277,8 +279,8 @@
 int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
 
 /* pc_sysfw.c */
-void pc_system_firmware_init(MemoryRegion *rom_memory,
-                             bool isapc_ram_fw);
+void pc_system_flash_create(PCMachineState *pcms);
+void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory);
 
 /* acpi-build.c */
 void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index ab0e3a0..b4aad26 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -28,11 +28,11 @@
 #define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge"
 
 #define SPAPR_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(sPAPRPHBState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
+    OBJECT_CHECK(SpaprPhbState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
 
 #define SPAPR_PCI_DMA_MAX_WINDOWS    2
 
-typedef struct sPAPRPHBState sPAPRPHBState;
+typedef struct SpaprPhbState SpaprPhbState;
 
 typedef struct spapr_pci_msi {
     uint32_t first_irq;
@@ -44,7 +44,7 @@
     spapr_pci_msi value;
 } spapr_pci_msi_mig;
 
-struct sPAPRPHBState {
+struct SpaprPhbState {
     PCIHostState parent_obj;
 
     uint32_t index;
@@ -72,7 +72,7 @@
     int32_t msi_devs_num;
     spapr_pci_msi_mig *msi_devs;
 
-    QLIST_ENTRY(sPAPRPHBState) list;
+    QLIST_ENTRY(SpaprPhbState) list;
 
     bool ddw_enabled;
     uint64_t page_size_mask;
@@ -105,56 +105,56 @@
 
 #define SPAPR_PCI_MSI_WINDOW         0x40000000000ULL
 
-static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
+static inline qemu_irq spapr_phb_lsi_qirq(struct SpaprPhbState *phb, int pin)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
 
     return spapr_qirq(spapr, phb->lsi_table[pin].irq);
 }
 
-int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t intc_phandle, void *fdt,
+int spapr_populate_pci_dt(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
                           uint32_t nr_msis, int *node_offset);
 
 void spapr_pci_rtas_init(void);
 
-sPAPRPHBState *spapr_pci_find_phb(sPAPRMachineState *spapr, uint64_t buid);
-PCIDevice *spapr_pci_find_dev(sPAPRMachineState *spapr, uint64_t buid,
+SpaprPhbState *spapr_pci_find_phb(SpaprMachineState *spapr, uint64_t buid);
+PCIDevice *spapr_pci_find_dev(SpaprMachineState *spapr, uint64_t buid,
                               uint32_t config_addr);
 
 /* DRC callbacks */
 void spapr_phb_remove_pci_device_cb(DeviceState *dev);
-int spapr_pci_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_pci_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp);
 
 /* VFIO EEH hooks */
 #ifdef CONFIG_LINUX
-bool spapr_phb_eeh_available(sPAPRPHBState *sphb);
-int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb,
+bool spapr_phb_eeh_available(SpaprPhbState *sphb);
+int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
                                   unsigned int addr, int option);
-int spapr_phb_vfio_eeh_get_state(sPAPRPHBState *sphb, int *state);
-int spapr_phb_vfio_eeh_reset(sPAPRPHBState *sphb, int option);
-int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb);
+int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb, int *state);
+int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option);
+int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb);
 void spapr_phb_vfio_reset(DeviceState *qdev);
 #else
-static inline bool spapr_phb_eeh_available(sPAPRPHBState *sphb)
+static inline bool spapr_phb_eeh_available(SpaprPhbState *sphb)
 {
     return false;
 }
-static inline int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb,
+static inline int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
                                                 unsigned int addr, int option)
 {
     return RTAS_OUT_HW_ERROR;
 }
-static inline int spapr_phb_vfio_eeh_get_state(sPAPRPHBState *sphb,
+static inline int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb,
                                                int *state)
 {
     return RTAS_OUT_HW_ERROR;
 }
-static inline int spapr_phb_vfio_eeh_reset(sPAPRPHBState *sphb, int option)
+static inline int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option)
 {
     return RTAS_OUT_HW_ERROR;
 }
-static inline int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb)
+static inline int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
 {
     return RTAS_OUT_HW_ERROR;
 }
@@ -163,9 +163,9 @@
 }
 #endif
 
-void spapr_phb_dma_reset(sPAPRPHBState *sphb);
+void spapr_phb_dma_reset(SpaprPhbState *sphb);
 
-static inline unsigned spapr_phb_windows_supported(sPAPRPHBState *sphb)
+static inline unsigned spapr_phb_windows_supported(SpaprPhbState *sphb)
 {
     return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
 }
diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
index 6b65397..e5b00d3 100644
--- a/include/hw/ppc/pnv.h
+++ b/include/hw/ppc/pnv.h
@@ -25,6 +25,8 @@
 #include "hw/ppc/pnv_lpc.h"
 #include "hw/ppc/pnv_psi.h"
 #include "hw/ppc/pnv_occ.h"
+#include "hw/ppc/pnv_xive.h"
+#include "hw/ppc/pnv_core.h"
 
 #define TYPE_PNV_CHIP "pnv-chip"
 #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
@@ -57,6 +59,8 @@
     MemoryRegion xscom_mmio;
     MemoryRegion xscom;
     AddressSpace xscom_as;
+
+    gchar        *dt_isa_nodename;
 } PnvChip;
 
 #define TYPE_PNV8_CHIP "pnv8-chip"
@@ -70,7 +74,7 @@
     MemoryRegion icp_mmio;
 
     PnvLpcController lpc;
-    PnvPsi       psi;
+    Pnv8Psi      psi;
     PnvOCC       occ;
 } Pnv8Chip;
 
@@ -82,6 +86,13 @@
     PnvChip      parent_obj;
 
     /*< public >*/
+    PnvXive      xive;
+    Pnv9Psi      psi;
+    PnvLpcController lpc;
+    PnvOCC       occ;
+
+    uint32_t     nr_quads;
+    PnvQuad      *quads;
 } Pnv9Chip;
 
 typedef struct PnvChipClass {
@@ -100,6 +111,8 @@
     uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
     void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
     ISABus *(*isa_create)(PnvChip *chip, Error **errp);
+    void (*dt_populate)(PnvChip *chip, void *fdt);
+    void (*pic_print_info)(PnvChip *chip, Monitor *mon);
 } PnvChipClass;
 
 #define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP
@@ -215,4 +228,31 @@
     (0x0003ffe000000000ull + (uint64_t)PNV_CHIP_INDEX(chip) * \
      PNV_PSIHB_FSP_SIZE)
 
+/*
+ * POWER9 MMIO base addresses
+ */
+#define PNV9_CHIP_BASE(chip, base)   \
+    ((base) + ((uint64_t) (chip)->chip_id << 42))
+
+#define PNV9_XIVE_VC_SIZE            0x0000008000000000ull
+#define PNV9_XIVE_VC_BASE(chip)      PNV9_CHIP_BASE(chip, 0x0006010000000000ull)
+
+#define PNV9_XIVE_PC_SIZE            0x0000001000000000ull
+#define PNV9_XIVE_PC_BASE(chip)      PNV9_CHIP_BASE(chip, 0x0006018000000000ull)
+
+#define PNV9_LPCM_SIZE               0x0000000100000000ull
+#define PNV9_LPCM_BASE(chip)         PNV9_CHIP_BASE(chip, 0x0006030000000000ull)
+
+#define PNV9_PSIHB_SIZE              0x0000000000100000ull
+#define PNV9_PSIHB_BASE(chip)        PNV9_CHIP_BASE(chip, 0x0006030203000000ull)
+
+#define PNV9_XIVE_IC_SIZE            0x0000000000080000ull
+#define PNV9_XIVE_IC_BASE(chip)      PNV9_CHIP_BASE(chip, 0x0006030203100000ull)
+
+#define PNV9_XIVE_TM_SIZE            0x0000000000040000ull
+#define PNV9_XIVE_TM_BASE(chip)      PNV9_CHIP_BASE(chip, 0x0006030203180000ull)
+
+#define PNV9_PSIHB_ESB_SIZE          0x0000000000010000ull
+#define PNV9_PSIHB_ESB_BASE(chip)    PNV9_CHIP_BASE(chip, 0x00060302031c0000ull)
+
 #endif /* _PPC_PNV_H */
diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h
index 9961ea3..50cdb2b 100644
--- a/include/hw/ppc/pnv_core.h
+++ b/include/hw/ppc/pnv_core.h
@@ -42,13 +42,15 @@
 
 typedef struct PnvCoreClass {
     DeviceClass parent_class;
+
+    const MemoryRegionOps *xscom_ops;
 } PnvCoreClass;
 
 #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE
 #define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX
 
 typedef struct PnvCPUState {
-    struct ICPState *icp;
+    Object *intc;
 } PnvCPUState;
 
 static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
@@ -56,4 +58,14 @@
     return (PnvCPUState *)cpu->machine_data;
 }
 
+#define TYPE_PNV_QUAD "powernv-cpu-quad"
+#define PNV_QUAD(obj) \
+    OBJECT_CHECK(PnvQuad, (obj), TYPE_PNV_QUAD)
+
+typedef struct PnvQuad {
+    DeviceState parent_obj;
+
+    uint32_t id;
+    MemoryRegion xscom_regs;
+} PnvQuad;
 #endif /* _PPC_PNV_CORE_H */
diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
index d657489..4135797 100644
--- a/include/hw/ppc/pnv_lpc.h
+++ b/include/hw/ppc/pnv_lpc.h
@@ -24,6 +24,11 @@
 #define TYPE_PNV_LPC "pnv-lpc"
 #define PNV_LPC(obj) \
      OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV_LPC)
+#define TYPE_PNV8_LPC TYPE_PNV_LPC "-POWER8"
+#define PNV8_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV8_LPC)
+
+#define TYPE_PNV9_LPC TYPE_PNV_LPC "-POWER9"
+#define PNV9_LPC(obj) OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV9_LPC)
 
 typedef struct PnvLpcController {
     DeviceState parent;
@@ -50,6 +55,8 @@
     MemoryRegion opb_master_regs;
 
     /* OPB Master LS registers */
+    uint32_t opb_irq_route0;
+    uint32_t opb_irq_route1;
     uint32_t opb_irq_stat;
     uint32_t opb_irq_mask;
     uint32_t opb_irq_pol;
@@ -70,6 +77,25 @@
     PnvPsi *psi;
 } PnvLpcController;
 
+#define PNV_LPC_CLASS(klass) \
+     OBJECT_CLASS_CHECK(PnvLpcClass, (klass), TYPE_PNV_LPC)
+#define PNV_LPC_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(PnvLpcClass, (obj), TYPE_PNV_LPC)
+
+typedef struct PnvLpcClass {
+    DeviceClass parent_class;
+
+    int psi_irq;
+
+    DeviceRealize parent_realize;
+} PnvLpcClass;
+
+/*
+ * Old compilers error on typdef forward declarations. Keep them happy.
+ */
+struct PnvChip;
+
 ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp);
+int pnv_dt_lpc(struct PnvChip *chip, void *fdt, int root_offset);
 
 #endif /* _PPC_PNV_LPC_H */
diff --git a/include/hw/ppc/pnv_occ.h b/include/hw/ppc/pnv_occ.h
index 82f299d..d22b65a 100644
--- a/include/hw/ppc/pnv_occ.h
+++ b/include/hw/ppc/pnv_occ.h
@@ -23,6 +23,10 @@
 
 #define TYPE_PNV_OCC "pnv-occ"
 #define PNV_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV_OCC)
+#define TYPE_PNV8_OCC TYPE_PNV_OCC "-POWER8"
+#define PNV8_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV8_OCC)
+#define TYPE_PNV9_OCC TYPE_PNV_OCC "-POWER9"
+#define PNV9_OCC(obj) OBJECT_CHECK(PnvOCC, (obj), TYPE_PNV9_OCC)
 
 typedef struct PnvOCC {
     DeviceState xd;
@@ -35,4 +39,17 @@
     MemoryRegion xscom_regs;
 } PnvOCC;
 
+#define PNV_OCC_CLASS(klass) \
+     OBJECT_CLASS_CHECK(PnvOCCClass, (klass), TYPE_PNV_OCC)
+#define PNV_OCC_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(PnvOCCClass, (obj), TYPE_PNV_OCC)
+
+typedef struct PnvOCCClass {
+    DeviceClass parent_class;
+
+    int xscom_size;
+    const MemoryRegionOps *xscom_ops;
+    int psi_irq;
+} PnvOCCClass;
+
 #endif /* _PPC_PNV_OCC_H */
diff --git a/include/hw/ppc/pnv_psi.h b/include/hw/ppc/pnv_psi.h
index 64ac735..2c1b27e 100644
--- a/include/hw/ppc/pnv_psi.h
+++ b/include/hw/ppc/pnv_psi.h
@@ -21,6 +21,7 @@
 
 #include "hw/sysbus.h"
 #include "hw/ppc/xics.h"
+#include "hw/ppc/xive.h"
 
 #define TYPE_PNV_PSI "pnv-psi"
 #define PNV_PSI(obj) \
@@ -39,7 +40,6 @@
     uint64_t fsp_bar;
 
     /* Interrupt generation */
-    ICSState ics;
     qemu_irq *qirqs;
 
     /* Registers */
@@ -48,6 +48,42 @@
     MemoryRegion xscom_regs;
 } PnvPsi;
 
+#define TYPE_PNV8_PSI TYPE_PNV_PSI "-POWER8"
+#define PNV8_PSI(obj) \
+    OBJECT_CHECK(Pnv8Psi, (obj), TYPE_PNV8_PSI)
+
+typedef struct Pnv8Psi {
+    PnvPsi   parent;
+
+    ICSState ics;
+} Pnv8Psi;
+
+#define TYPE_PNV9_PSI TYPE_PNV_PSI "-POWER9"
+#define PNV9_PSI(obj) \
+    OBJECT_CHECK(Pnv9Psi, (obj), TYPE_PNV9_PSI)
+
+typedef struct Pnv9Psi {
+    PnvPsi   parent;
+
+    XiveSource source;
+} Pnv9Psi;
+
+#define PNV_PSI_CLASS(klass) \
+     OBJECT_CLASS_CHECK(PnvPsiClass, (klass), TYPE_PNV_PSI)
+#define PNV_PSI_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(PnvPsiClass, (obj), TYPE_PNV_PSI)
+
+typedef struct PnvPsiClass {
+    SysBusDeviceClass parent_class;
+
+    int chip_type;
+    uint32_t xscom_pcba;
+    uint32_t xscom_size;
+    uint64_t bar_mask;
+
+    void (*irq_set)(PnvPsi *psi, int, bool state);
+} PnvPsiClass;
+
 /* The PSI and FSP interrupts are muxed on the same IRQ number */
 typedef enum PnvPsiIrq {
     PSIHB_IRQ_PSI, /* internal use only */
@@ -61,6 +97,25 @@
 
 #define PSI_NUM_INTERRUPTS 6
 
-extern void pnv_psi_irq_set(PnvPsi *psi, PnvPsiIrq irq, bool state);
+void pnv_psi_irq_set(PnvPsi *psi, int irq, bool state);
+
+/* P9 PSI Interrupts */
+#define PSIHB9_IRQ_PSI          0
+#define PSIHB9_IRQ_OCC          1
+#define PSIHB9_IRQ_FSI          2
+#define PSIHB9_IRQ_LPCHC        3
+#define PSIHB9_IRQ_LOCAL_ERR    4
+#define PSIHB9_IRQ_GLOBAL_ERR   5
+#define PSIHB9_IRQ_TPM          6
+#define PSIHB9_IRQ_LPC_SIRQ0    7
+#define PSIHB9_IRQ_LPC_SIRQ1    8
+#define PSIHB9_IRQ_LPC_SIRQ2    9
+#define PSIHB9_IRQ_LPC_SIRQ3    10
+#define PSIHB9_IRQ_SBE_I2C      11
+#define PSIHB9_IRQ_DIO          12
+#define PSIHB9_IRQ_PSU          13
+#define PSIHB9_NUM_IRQS         14
+
+void pnv_psi_pic_print_info(Pnv9Psi *psi, Monitor *mon);
 
 #endif /* _PPC_PNV_PSI_H */
diff --git a/include/hw/ppc/pnv_xive.h b/include/hw/ppc/pnv_xive.h
new file mode 100644
index 0000000..4fdaa92
--- /dev/null
+++ b/include/hw/ppc/pnv_xive.h
@@ -0,0 +1,93 @@
+/*
+ * QEMU PowerPC XIVE interrupt controller model
+ *
+ * Copyright (c) 2017-2019, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PPC_PNV_XIVE_H
+#define PPC_PNV_XIVE_H
+
+#include "hw/ppc/xive.h"
+
+struct PnvChip;
+
+#define TYPE_PNV_XIVE "pnv-xive"
+#define PNV_XIVE(obj) OBJECT_CHECK(PnvXive, (obj), TYPE_PNV_XIVE)
+
+#define XIVE_BLOCK_MAX      16
+
+#define XIVE_TABLE_BLK_MAX  16  /* Block Scope Table (0-15) */
+#define XIVE_TABLE_MIG_MAX  16  /* Migration Register Table (1-15) */
+#define XIVE_TABLE_VDT_MAX  16  /* VDT Domain Table (0-15) */
+#define XIVE_TABLE_EDT_MAX  64  /* EDT Domain Table (0-63) */
+
+typedef struct PnvXive {
+    XiveRouter    parent_obj;
+
+    /* Owning chip */
+    struct PnvChip *chip;
+
+    /* XSCOM addresses giving access to the controller registers */
+    MemoryRegion  xscom_regs;
+
+    /* Main MMIO regions that can be configured by FW */
+    MemoryRegion  ic_mmio;
+    MemoryRegion    ic_reg_mmio;
+    MemoryRegion    ic_notify_mmio;
+    MemoryRegion    ic_lsi_mmio;
+    MemoryRegion    tm_indirect_mmio;
+    MemoryRegion  vc_mmio;
+    MemoryRegion  pc_mmio;
+    MemoryRegion  tm_mmio;
+
+    /*
+     * IPI and END address spaces modeling the EDT segmentation in the
+     * VC region
+     */
+    AddressSpace  ipi_as;
+    MemoryRegion  ipi_mmio;
+    MemoryRegion    ipi_edt_mmio;
+
+    AddressSpace  end_as;
+    MemoryRegion  end_mmio;
+    MemoryRegion    end_edt_mmio;
+
+    /* Shortcut values for the Main MMIO regions */
+    hwaddr        ic_base;
+    uint32_t      ic_shift;
+    hwaddr        vc_base;
+    uint32_t      vc_shift;
+    hwaddr        pc_base;
+    uint32_t      pc_shift;
+    hwaddr        tm_base;
+    uint32_t      tm_shift;
+
+    /* Our XIVE source objects for IPIs and ENDs */
+    XiveSource    ipi_source;
+    XiveENDSource end_source;
+
+    /* Interrupt controller registers */
+    uint64_t      regs[0x300];
+
+    /* Can be configured by FW */
+    uint32_t      tctx_chipid;
+
+    /*
+     * Virtual Structure Descriptor tables : EAT, SBE, ENDT, NVTT, IRQ
+     * These are in a SRAM protected by ECC.
+     */
+    uint64_t      vsds[5][XIVE_BLOCK_MAX];
+
+    /* Translation tables */
+    uint64_t      blk[XIVE_TABLE_BLK_MAX];
+    uint64_t      mig[XIVE_TABLE_MIG_MAX];
+    uint64_t      vdt[XIVE_TABLE_VDT_MAX];
+    uint64_t      edt[XIVE_TABLE_EDT_MAX];
+} PnvXive;
+
+void pnv_xive_pic_print_info(PnvXive *xive, Monitor *mon);
+
+#endif /* PPC_PNV_XIVE_H */
diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h
index 255b26a..68dfae0 100644
--- a/include/hw/ppc/pnv_xscom.h
+++ b/include/hw/ppc/pnv_xscom.h
@@ -60,10 +60,6 @@
     (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24))
 #define PNV_XSCOM_EX_SIZE         0x100000
 
-#define PNV_XSCOM_P9_EC_BASE(core) \
-    ((uint64_t)(((core) & 0x1F) + 0x20) << 24)
-#define PNV_XSCOM_P9_EC_SIZE      0x100000
-
 #define PNV_XSCOM_LPC_BASE        0xb0020
 #define PNV_XSCOM_LPC_SIZE        0x4
 
@@ -73,6 +69,23 @@
 #define PNV_XSCOM_OCC_BASE        0x0066000
 #define PNV_XSCOM_OCC_SIZE        0x6000
 
+#define PNV9_XSCOM_EC_BASE(core) \
+    ((uint64_t)(((core) & 0x1F) + 0x20) << 24)
+#define PNV9_XSCOM_EC_SIZE        0x100000
+
+#define PNV9_XSCOM_EQ_BASE(core) \
+    ((uint64_t)(((core) & 0x1C) + 0x40) << 22)
+#define PNV9_XSCOM_EQ_SIZE        0x100000
+
+#define PNV9_XSCOM_OCC_BASE       PNV_XSCOM_OCC_BASE
+#define PNV9_XSCOM_OCC_SIZE       0x8000
+
+#define PNV9_XSCOM_PSIHB_BASE     0x5012900
+#define PNV9_XSCOM_PSIHB_SIZE     0x100
+
+#define PNV9_XSCOM_XIVE_BASE      0x5013000
+#define PNV9_XSCOM_XIVE_SIZE      0x300
+
 extern void pnv_xscom_realize(PnvChip *chip, Error **errp);
 extern int pnv_dt_xscom(PnvChip *chip, void *fdt, int offset);
 
diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h
index 746170f..4bdcb8b 100644
--- a/include/hw/ppc/ppc.h
+++ b/include/hw/ppc/ppc.h
@@ -4,6 +4,7 @@
 #include "target/ppc/cpu-qom.h"
 
 void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
+PowerPCCPU *ppc_get_vcpu_by_pir(int pir);
 
 /* PowerPC hardware exceptions management helpers */
 typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 59073a7..2b4c05a 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -8,16 +8,16 @@
 #include "hw/mem/pc-dimm.h"
 #include "hw/ppc/spapr_ovec.h"
 #include "hw/ppc/spapr_irq.h"
-#include "hw/ppc/spapr_xive.h"  /* For sPAPRXive */
+#include "hw/ppc/spapr_xive.h"  /* For SpaprXive */
 #include "hw/ppc/xics.h"        /* For ICSState */
 
-struct VIOsPAPRBus;
-struct sPAPRPHBState;
-struct sPAPRNVRAM;
+struct SpaprVioBus;
+struct SpaprPhbState;
+struct SpaprNvram;
 
-typedef struct sPAPREventLogEntry sPAPREventLogEntry;
-typedef struct sPAPREventSource sPAPREventSource;
-typedef struct sPAPRPendingHPT sPAPRPendingHPT;
+typedef struct SpaprEventLogEntry SpaprEventLogEntry;
+typedef struct SpaprEventSource SpaprEventSource;
+typedef struct SpaprPendingHpt SpaprPendingHpt;
 
 #define HPTE64_V_HPTE_DIRTY     0x0000000000000040ULL
 #define SPAPR_ENTRY_POINT       0x100
@@ -27,32 +27,32 @@
 #define TYPE_SPAPR_RTC "spapr-rtc"
 
 #define SPAPR_RTC(obj)                                  \
-    OBJECT_CHECK(sPAPRRTCState, (obj), TYPE_SPAPR_RTC)
+    OBJECT_CHECK(SpaprRtcState, (obj), TYPE_SPAPR_RTC)
 
-typedef struct sPAPRRTCState sPAPRRTCState;
-struct sPAPRRTCState {
+typedef struct SpaprRtcState SpaprRtcState;
+struct SpaprRtcState {
     /*< private >*/
     DeviceState parent_obj;
     int64_t ns_offset;
 };
 
-typedef struct sPAPRDIMMState sPAPRDIMMState;
-typedef struct sPAPRMachineClass sPAPRMachineClass;
+typedef struct SpaprDimmState SpaprDimmState;
+typedef struct SpaprMachineClass SpaprMachineClass;
 
 #define TYPE_SPAPR_MACHINE      "spapr-machine"
 #define SPAPR_MACHINE(obj) \
-    OBJECT_CHECK(sPAPRMachineState, (obj), TYPE_SPAPR_MACHINE)
+    OBJECT_CHECK(SpaprMachineState, (obj), TYPE_SPAPR_MACHINE)
 #define SPAPR_MACHINE_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(sPAPRMachineClass, obj, TYPE_SPAPR_MACHINE)
+    OBJECT_GET_CLASS(SpaprMachineClass, obj, TYPE_SPAPR_MACHINE)
 #define SPAPR_MACHINE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(sPAPRMachineClass, klass, TYPE_SPAPR_MACHINE)
+    OBJECT_CLASS_CHECK(SpaprMachineClass, klass, TYPE_SPAPR_MACHINE)
 
 typedef enum {
     SPAPR_RESIZE_HPT_DEFAULT = 0,
     SPAPR_RESIZE_HPT_DISABLED,
     SPAPR_RESIZE_HPT_ENABLED,
     SPAPR_RESIZE_HPT_REQUIRED,
-} sPAPRResizeHPT;
+} SpaprResizeHpt;
 
 /**
  * Capabilities
@@ -74,8 +74,12 @@
 #define SPAPR_CAP_HPT_MAXPAGESIZE       0x06
 /* Nested KVM-HV */
 #define SPAPR_CAP_NESTED_KVM_HV         0x07
+/* Large Decrementer */
+#define SPAPR_CAP_LARGE_DECREMENTER     0x08
+/* Count Cache Flush Assist HW Instruction */
+#define SPAPR_CAP_CCF_ASSIST            0x09
 /* Num Caps */
-#define SPAPR_CAP_NUM                   (SPAPR_CAP_NESTED_KVM_HV + 1)
+#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
 
 /*
  * Capability Values
@@ -83,22 +87,27 @@
 /* Bool Caps */
 #define SPAPR_CAP_OFF                   0x00
 #define SPAPR_CAP_ON                    0x01
+
 /* Custom Caps */
+
+/* Generic */
 #define SPAPR_CAP_BROKEN                0x00
 #define SPAPR_CAP_WORKAROUND            0x01
 #define SPAPR_CAP_FIXED                 0x02
+/* SPAPR_CAP_IBS (cap-ibs) */
 #define SPAPR_CAP_FIXED_IBS             0x02
 #define SPAPR_CAP_FIXED_CCD             0x03
+#define SPAPR_CAP_FIXED_NA              0x10 /* Lets leave a bit of a gap... */
 
-typedef struct sPAPRCapabilities sPAPRCapabilities;
-struct sPAPRCapabilities {
+typedef struct SpaprCapabilities SpaprCapabilities;
+struct SpaprCapabilities {
     uint8_t caps[SPAPR_CAP_NUM];
 };
 
 /**
- * sPAPRMachineClass:
+ * SpaprMachineClass:
  */
-struct sPAPRMachineClass {
+struct SpaprMachineClass {
     /*< private >*/
     MachineClass parent_class;
 
@@ -110,33 +119,33 @@
     bool pre_2_10_has_unused_icps;
     bool legacy_irq_allocation;
 
-    void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index,
+    void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
                           uint64_t *buid, hwaddr *pio, 
                           hwaddr *mmio32, hwaddr *mmio64,
                           unsigned n_dma, uint32_t *liobns, Error **errp);
-    sPAPRResizeHPT resize_hpt_default;
-    sPAPRCapabilities default_caps;
-    sPAPRIrq *irq;
+    SpaprResizeHpt resize_hpt_default;
+    SpaprCapabilities default_caps;
+    SpaprIrq *irq;
 };
 
 /**
- * sPAPRMachineState:
+ * SpaprMachineState:
  */
-struct sPAPRMachineState {
+struct SpaprMachineState {
     /*< private >*/
     MachineState parent_obj;
 
-    struct VIOsPAPRBus *vio_bus;
-    QLIST_HEAD(, sPAPRPHBState) phbs;
-    struct sPAPRNVRAM *nvram;
+    struct SpaprVioBus *vio_bus;
+    QLIST_HEAD(, SpaprPhbState) phbs;
+    struct SpaprNvram *nvram;
     ICSState *ics;
-    sPAPRRTCState rtc;
+    SpaprRtcState rtc;
 
-    sPAPRResizeHPT resize_hpt;
+    SpaprResizeHpt resize_hpt;
     void *htab;
     uint32_t htab_shift;
     uint64_t patb_entry; /* Process tbl registed in H_REGISTER_PROCESS_TABLE */
-    sPAPRPendingHPT *pending_hpt; /* in-progress resize */
+    SpaprPendingHpt *pending_hpt; /* in-progress resize */
 
     hwaddr rma_size;
     int vrma_adjust;
@@ -155,15 +164,15 @@
     uint32_t vsmt;       /* Virtual SMT mode (KVM's "core stride") */
 
     Notifier epow_notifier;
-    QTAILQ_HEAD(, sPAPREventLogEntry) pending_events;
+    QTAILQ_HEAD(, SpaprEventLogEntry) pending_events;
     bool use_hotplug_event_source;
-    sPAPREventSource *event_sources;
+    SpaprEventSource *event_sources;
 
     /* ibm,client-architecture-support option negotiation */
     bool cas_reboot;
     bool cas_legacy_guest_workaround;
-    sPAPROptionVector *ov5;         /* QEMU-supported option vectors */
-    sPAPROptionVector *ov5_cas;     /* negotiated (via CAS) option vectors */
+    SpaprOptionVector *ov5;         /* QEMU-supported option vectors */
+    SpaprOptionVector *ov5_cas;     /* negotiated (via CAS) option vectors */
     uint32_t max_compat_pvr;
 
     /* Migration state */
@@ -174,7 +183,7 @@
     /* Pending DIMM unplug cache. It is populated when a LMB
      * unplug starts. It can be regenerated if a migration
      * occurs during the unplug process. */
-    QTAILQ_HEAD(, sPAPRDIMMState) pending_dimm_unplugs;
+    QTAILQ_HEAD(, SpaprDimmState) pending_dimm_unplugs;
 
     /*< public >*/
     char *kvm_type;
@@ -183,12 +192,12 @@
 
     int32_t irq_map_nr;
     unsigned long *irq_map;
-    sPAPRXive  *xive;
-    sPAPRIrq *irq;
+    SpaprXive  *xive;
+    SpaprIrq *irq;
     qemu_irq *qirqs;
 
     bool cmd_line_caps[SPAPR_CAP_NUM];
-    sPAPRCapabilities def, eff, mig;
+    SpaprCapabilities def, eff, mig;
 };
 
 #define H_SUCCESS         0
@@ -337,9 +346,11 @@
 #define H_CPU_CHAR_HON_BRANCH_HINTS             PPC_BIT(5)
 #define H_CPU_CHAR_THR_RECONF_TRIG              PPC_BIT(6)
 #define H_CPU_CHAR_CACHE_COUNT_DIS              PPC_BIT(7)
+#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST           PPC_BIT(9)
 #define H_CPU_BEHAV_FAVOUR_SECURITY             PPC_BIT(0)
 #define H_CPU_BEHAV_L1D_FLUSH_PR                PPC_BIT(1)
 #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR           PPC_BIT(2)
+#define H_CPU_BEHAV_FLUSH_COUNT_CACHE           PPC_BIT(5)
 
 /* Each control block has to be on a 4K boundary */
 #define H_CB_ALIGNMENT     4096
@@ -492,16 +503,16 @@
 #define KVMPPC_H_UPDATE_DT      (KVMPPC_HCALL_BASE + 0x3)
 #define KVMPPC_HCALL_MAX        KVMPPC_H_UPDATE_DT
 
-typedef struct sPAPRDeviceTreeUpdateHeader {
+typedef struct SpaprDeviceTreeUpdateHeader {
     uint32_t version_id;
-} sPAPRDeviceTreeUpdateHeader;
+} SpaprDeviceTreeUpdateHeader;
 
 #define hcall_dprintf(fmt, ...) \
     do { \
         qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt, __func__, ## __VA_ARGS__); \
     } while (0)
 
-typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm,
+typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
                                        target_ulong opcode,
                                        target_ulong *args);
 
@@ -655,16 +666,16 @@
     stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val);
 }
 
-typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm,
+typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
                               uint32_t token,
                               uint32_t nargs, target_ulong args,
                               uint32_t nret, target_ulong rets);
 void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn);
-target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *sm,
+target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *sm,
                              uint32_t token, uint32_t nargs, target_ulong args,
                              uint32_t nret, target_ulong rets);
 void spapr_dt_rtas_tokens(void *fdt, int rtas);
-void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr);
+void spapr_load_rtas(SpaprMachineState *spapr, void *fdt, hwaddr addr);
 
 #define SPAPR_TCE_PAGE_SHIFT   12
 #define SPAPR_TCE_PAGE_SIZE    (1ULL << SPAPR_TCE_PAGE_SHIFT)
@@ -691,17 +702,17 @@
     intspec[1] = is_lsi ? cpu_to_be32(1) : 0;
 }
 
-typedef struct sPAPRTCETable sPAPRTCETable;
+typedef struct SpaprTceTable SpaprTceTable;
 
 #define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
 #define SPAPR_TCE_TABLE(obj) \
-    OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)
+    OBJECT_CHECK(SpaprTceTable, (obj), TYPE_SPAPR_TCE_TABLE)
 
 #define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region"
 #define SPAPR_IOMMU_MEMORY_REGION(obj) \
         OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION)
 
-struct sPAPRTCETable {
+struct SpaprTceTable {
     DeviceState parent;
     uint32_t liobn;
     uint32_t nb_table;
@@ -712,76 +723,77 @@
     uint64_t *mig_table;
     bool bypass;
     bool need_vfio;
+    bool skipping_replay;
     int fd;
     MemoryRegion root;
     IOMMUMemoryRegion iommu;
-    struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */
-    QLIST_ENTRY(sPAPRTCETable) list;
+    struct SpaprVioDevice *vdev; /* for @bypass migration compatibility only */
+    QLIST_ENTRY(SpaprTceTable) list;
 };
 
-sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn);
+SpaprTceTable *spapr_tce_find_by_liobn(target_ulong liobn);
 
-struct sPAPREventLogEntry {
+struct SpaprEventLogEntry {
     uint32_t summary;
     uint32_t extended_length;
     void *extended_log;
-    QTAILQ_ENTRY(sPAPREventLogEntry) next;
+    QTAILQ_ENTRY(SpaprEventLogEntry) next;
 };
 
-void spapr_events_init(sPAPRMachineState *sm);
-void spapr_dt_events(sPAPRMachineState *sm, void *fdt);
-int spapr_h_cas_compose_response(sPAPRMachineState *sm,
+void spapr_events_init(SpaprMachineState *sm);
+void spapr_dt_events(SpaprMachineState *sm, void *fdt);
+int spapr_h_cas_compose_response(SpaprMachineState *sm,
                                  target_ulong addr, target_ulong size,
-                                 sPAPROptionVector *ov5_updates);
-void close_htab_fd(sPAPRMachineState *spapr);
-void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr);
-void spapr_free_hpt(sPAPRMachineState *spapr);
-sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn);
-void spapr_tce_table_enable(sPAPRTCETable *tcet,
+                                 SpaprOptionVector *ov5_updates);
+void close_htab_fd(SpaprMachineState *spapr);
+void spapr_setup_hpt_and_vrma(SpaprMachineState *spapr);
+void spapr_free_hpt(SpaprMachineState *spapr);
+SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn);
+void spapr_tce_table_enable(SpaprTceTable *tcet,
                             uint32_t page_shift, uint64_t bus_offset,
                             uint32_t nb_table);
-void spapr_tce_table_disable(sPAPRTCETable *tcet);
-void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio);
+void spapr_tce_table_disable(SpaprTceTable *tcet);
+void spapr_tce_set_need_vfio(SpaprTceTable *tcet, bool need_vfio);
 
-MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
+MemoryRegion *spapr_tce_get_iommu(SpaprTceTable *tcet);
 int spapr_dma_dt(void *fdt, int node_off, const char *propname,
                  uint32_t liobn, uint64_t window, uint32_t size);
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
-                      sPAPRTCETable *tcet);
+                      SpaprTceTable *tcet);
 void spapr_pci_switch_vga(bool big_endian);
-void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc);
-void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc);
-void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_add_by_index(SpaprDrc *drc);
+void spapr_hotplug_req_remove_by_index(SpaprDrc *drc);
+void spapr_hotplug_req_add_by_count(SpaprDrcType drc_type,
                                        uint32_t count);
-void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_remove_by_count(SpaprDrcType drc_type,
                                           uint32_t count);
-void spapr_hotplug_req_add_by_count_indexed(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_add_by_count_indexed(SpaprDrcType drc_type,
                                             uint32_t count, uint32_t index);
-void spapr_hotplug_req_remove_by_count_indexed(sPAPRDRConnectorType drc_type,
+void spapr_hotplug_req_remove_by_count_indexed(SpaprDrcType drc_type,
                                                uint32_t count, uint32_t index);
 int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
-void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
+void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift,
                           Error **errp);
-void spapr_clear_pending_events(sPAPRMachineState *spapr);
-int spapr_max_server_number(sPAPRMachineState *spapr);
+void spapr_clear_pending_events(SpaprMachineState *spapr);
+int spapr_max_server_number(SpaprMachineState *spapr);
 
 /* DRC callbacks. */
 void spapr_core_release(DeviceState *dev);
-int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                            void *fdt, int *fdt_start_offset, Error **errp);
 void spapr_lmb_release(DeviceState *dev);
-int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp);
 void spapr_phb_release(DeviceState *dev);
-int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp);
 
-void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns);
-int spapr_rtc_import_offset(sPAPRRTCState *rtc, int64_t legacy_offset);
+void spapr_rtc_read(SpaprRtcState *rtc, struct tm *tm, uint32_t *ns);
+int spapr_rtc_import_offset(SpaprRtcState *rtc, int64_t legacy_offset);
 
 #define TYPE_SPAPR_RNG "spapr-rng"
 
-#define SPAPR_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */
+#define SPAPR_MEMORY_BLOCK_SIZE ((hwaddr)1 << 28) /* 256MB */
 
 /*
  * This defines the maximum number of DIMM slots we can have for sPAPR
@@ -828,19 +840,21 @@
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
 extern const VMStateDescription vmstate_spapr_cap_ibs;
 extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
+extern const VMStateDescription vmstate_spapr_cap_large_decr;
+extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
 
-static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
+static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap)
 {
     return spapr->eff.caps[cap];
 }
 
-void spapr_caps_init(sPAPRMachineState *spapr);
-void spapr_caps_apply(sPAPRMachineState *spapr);
-void spapr_caps_cpu_apply(sPAPRMachineState *spapr, PowerPCCPU *cpu);
-void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp);
-int spapr_caps_post_migration(sPAPRMachineState *spapr);
+void spapr_caps_init(SpaprMachineState *spapr);
+void spapr_caps_apply(SpaprMachineState *spapr);
+void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu);
+void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp);
+int spapr_caps_post_migration(SpaprMachineState *spapr);
 
-void spapr_check_pagesize(sPAPRMachineState *spapr, hwaddr pagesize,
+void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
                           Error **errp);
 /*
  * XIVE definitions
diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
index d64f86b..f9645a7 100644
--- a/include/hw/ppc/spapr_cpu_core.h
+++ b/include/hw/ppc/spapr_cpu_core.h
@@ -16,43 +16,43 @@
 
 #define TYPE_SPAPR_CPU_CORE "spapr-cpu-core"
 #define SPAPR_CPU_CORE(obj) \
-    OBJECT_CHECK(sPAPRCPUCore, (obj), TYPE_SPAPR_CPU_CORE)
+    OBJECT_CHECK(SpaprCpuCore, (obj), TYPE_SPAPR_CPU_CORE)
 #define SPAPR_CPU_CORE_CLASS(klass) \
-    OBJECT_CLASS_CHECK(sPAPRCPUCoreClass, (klass), TYPE_SPAPR_CPU_CORE)
+    OBJECT_CLASS_CHECK(SpaprCpuCoreClass, (klass), TYPE_SPAPR_CPU_CORE)
 #define SPAPR_CPU_CORE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(sPAPRCPUCoreClass, (obj), TYPE_SPAPR_CPU_CORE)
+     OBJECT_GET_CLASS(SpaprCpuCoreClass, (obj), TYPE_SPAPR_CPU_CORE)
 
 #define SPAPR_CPU_CORE_TYPE_NAME(model) model "-" TYPE_SPAPR_CPU_CORE
 
-typedef struct sPAPRCPUCore {
+typedef struct SpaprCpuCore {
     /*< private >*/
     CPUCore parent_obj;
 
     /*< public >*/
     PowerPCCPU **threads;
     int node_id;
-    bool pre_3_0_migration; /* older machine don't know about sPAPRCPUState */
-} sPAPRCPUCore;
+    bool pre_3_0_migration; /* older machine don't know about SpaprCpuState */
+} SpaprCpuCore;
 
-typedef struct sPAPRCPUCoreClass {
+typedef struct SpaprCpuCoreClass {
     DeviceClass parent_class;
     const char *cpu_type;
-} sPAPRCPUCoreClass;
+} SpaprCpuCoreClass;
 
 const char *spapr_get_cpu_core_type(const char *cpu_type);
 void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3);
 
-typedef struct sPAPRCPUState {
+typedef struct SpaprCpuState {
     uint64_t vpa_addr;
     uint64_t slb_shadow_addr, slb_shadow_size;
     uint64_t dtl_addr, dtl_size;
     struct ICPState *icp;
     struct XiveTCTX *tctx;
-} sPAPRCPUState;
+} SpaprCpuState;
 
-static inline sPAPRCPUState *spapr_cpu_state(PowerPCCPU *cpu)
+static inline SpaprCpuState *spapr_cpu_state(PowerPCCPU *cpu)
 {
-    return (sPAPRCPUState *)cpu->machine_data;
+    return (SpaprCpuState *)cpu->machine_data;
 }
 
 #endif
diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
index 46b0f62..fad0a88 100644
--- a/include/hw/ppc/spapr_drc.h
+++ b/include/hw/ppc/spapr_drc.h
@@ -22,65 +22,65 @@
 
 #define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector"
 #define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DR_CONNECTOR)
+        OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DR_CONNECTOR)
 #define SPAPR_DR_CONNECTOR_CLASS(klass) \
-        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \
+        OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \
                            TYPE_SPAPR_DR_CONNECTOR)
-#define SPAPR_DR_CONNECTOR(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+#define SPAPR_DR_CONNECTOR(obj) OBJECT_CHECK(SpaprDrc, (obj), \
                                              TYPE_SPAPR_DR_CONNECTOR)
 
 #define TYPE_SPAPR_DRC_PHYSICAL "spapr-drc-physical"
 #define SPAPR_DRC_PHYSICAL_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PHYSICAL)
+        OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PHYSICAL)
 #define SPAPR_DRC_PHYSICAL_CLASS(klass) \
-        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \
+        OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \
                            TYPE_SPAPR_DRC_PHYSICAL)
-#define SPAPR_DRC_PHYSICAL(obj) OBJECT_CHECK(sPAPRDRCPhysical, (obj), \
+#define SPAPR_DRC_PHYSICAL(obj) OBJECT_CHECK(SpaprDrcPhysical, (obj), \
                                              TYPE_SPAPR_DRC_PHYSICAL)
 
 #define TYPE_SPAPR_DRC_LOGICAL "spapr-drc-logical"
 #define SPAPR_DRC_LOGICAL_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_LOGICAL)
+        OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_LOGICAL)
 #define SPAPR_DRC_LOGICAL_CLASS(klass) \
-        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \
+        OBJECT_CLASS_CHECK(SpaprDrcClass, klass, \
                            TYPE_SPAPR_DRC_LOGICAL)
-#define SPAPR_DRC_LOGICAL(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+#define SPAPR_DRC_LOGICAL(obj) OBJECT_CHECK(SpaprDrc, (obj), \
                                              TYPE_SPAPR_DRC_LOGICAL)
 
 #define TYPE_SPAPR_DRC_CPU "spapr-drc-cpu"
 #define SPAPR_DRC_CPU_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_CPU)
+        OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_CPU)
 #define SPAPR_DRC_CPU_CLASS(klass) \
-        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_CPU)
-#define SPAPR_DRC_CPU(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+        OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_CPU)
+#define SPAPR_DRC_CPU(obj) OBJECT_CHECK(SpaprDrc, (obj), \
                                         TYPE_SPAPR_DRC_CPU)
 
 #define TYPE_SPAPR_DRC_PCI "spapr-drc-pci"
 #define SPAPR_DRC_PCI_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PCI)
+        OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PCI)
 #define SPAPR_DRC_PCI_CLASS(klass) \
-        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_PCI)
-#define SPAPR_DRC_PCI(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+        OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PCI)
+#define SPAPR_DRC_PCI(obj) OBJECT_CHECK(SpaprDrc, (obj), \
                                         TYPE_SPAPR_DRC_PCI)
 
 #define TYPE_SPAPR_DRC_LMB "spapr-drc-lmb"
 #define SPAPR_DRC_LMB_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_LMB)
+        OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_LMB)
 #define SPAPR_DRC_LMB_CLASS(klass) \
-        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_LMB)
-#define SPAPR_DRC_LMB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+        OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_LMB)
+#define SPAPR_DRC_LMB(obj) OBJECT_CHECK(SpaprDrc, (obj), \
                                         TYPE_SPAPR_DRC_LMB)
 
 #define TYPE_SPAPR_DRC_PHB "spapr-drc-phb"
 #define SPAPR_DRC_PHB_GET_CLASS(obj) \
-        OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PHB)
+        OBJECT_GET_CLASS(SpaprDrcClass, obj, TYPE_SPAPR_DRC_PHB)
 #define SPAPR_DRC_PHB_CLASS(klass) \
-        OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_PHB)
-#define SPAPR_DRC_PHB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
+        OBJECT_CLASS_CHECK(SpaprDrcClass, klass, TYPE_SPAPR_DRC_PHB)
+#define SPAPR_DRC_PHB(obj) OBJECT_CHECK(SpaprDrc, (obj), \
                                         TYPE_SPAPR_DRC_PHB)
 
 /*
- * Various hotplug types managed by sPAPRDRConnector
+ * Various hotplug types managed by SpaprDrc
  *
  * these are somewhat arbitrary, but to make things easier
  * when generating DRC indexes later we've aligned the bit
@@ -96,7 +96,7 @@
     SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO = 3,
     SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI = 4,
     SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB = 8,
-} sPAPRDRConnectorTypeShift;
+} SpaprDrcTypeShift;
 
 typedef enum {
     SPAPR_DR_CONNECTOR_TYPE_ANY = ~0,
@@ -105,7 +105,7 @@
     SPAPR_DR_CONNECTOR_TYPE_VIO = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO,
     SPAPR_DR_CONNECTOR_TYPE_PCI = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI,
     SPAPR_DR_CONNECTOR_TYPE_LMB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB,
-} sPAPRDRConnectorType;
+} SpaprDrcType;
 
 /*
  * set via set-indicator RTAS calls
@@ -117,7 +117,7 @@
 typedef enum {
     SPAPR_DR_ISOLATION_STATE_ISOLATED   = 0,
     SPAPR_DR_ISOLATION_STATE_UNISOLATED = 1
-} sPAPRDRIsolationState;
+} SpaprDRIsolationState;
 
 /*
  * set via set-indicator RTAS calls
@@ -133,7 +133,7 @@
     SPAPR_DR_ALLOCATION_STATE_USABLE    = 1,
     SPAPR_DR_ALLOCATION_STATE_EXCHANGE  = 2,
     SPAPR_DR_ALLOCATION_STATE_RECOVER   = 3
-} sPAPRDRAllocationState;
+} SpaprDRAllocationState;
 
 /*
  * DR-indicator (LED/visual indicator)
@@ -152,7 +152,7 @@
     SPAPR_DR_INDICATOR_ACTIVE     = 1,
     SPAPR_DR_INDICATOR_IDENTIFY   = 2,
     SPAPR_DR_INDICATOR_ACTION     = 3,
-} sPAPRDRIndicatorState;
+} SpaprDRIndicatorState;
 
 /*
  * returned via get-sensor-state RTAS calls
@@ -170,7 +170,7 @@
     SPAPR_DR_ENTITY_SENSE_UNUSABLE  = 2,
     SPAPR_DR_ENTITY_SENSE_EXCHANGE  = 3,
     SPAPR_DR_ENTITY_SENSE_RECOVER   = 4,
-} sPAPRDREntitySense;
+} SpaprDREntitySense;
 
 typedef enum {
     SPAPR_DR_CC_RESPONSE_NEXT_SIB         = 1, /* currently unused */
@@ -181,7 +181,7 @@
     SPAPR_DR_CC_RESPONSE_ERROR            = -1,
     SPAPR_DR_CC_RESPONSE_CONTINUE         = -2,
     SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE = -9003,
-} sPAPRDRCCResponse;
+} SpaprDRCCResponse;
 
 typedef enum {
     /*
@@ -199,9 +199,9 @@
     SPAPR_DRC_STATE_PHYSICAL_POWERON    = 6,
     SPAPR_DRC_STATE_PHYSICAL_UNISOLATE  = 7,
     SPAPR_DRC_STATE_PHYSICAL_CONFIGURED = 8,
-} sPAPRDRCState;
+} SpaprDrcState;
 
-typedef struct sPAPRDRConnector {
+typedef struct SpaprDrc {
     /*< private >*/
     DeviceState parent;
 
@@ -220,60 +220,60 @@
     bool unplug_requested;
     void *fdt;
     int fdt_start_offset;
-} sPAPRDRConnector;
+} SpaprDrc;
 
-struct sPAPRMachineState;
+struct SpaprMachineState;
 
-typedef struct sPAPRDRConnectorClass {
+typedef struct SpaprDrcClass {
     /*< private >*/
     DeviceClass parent;
-    sPAPRDRCState empty_state;
-    sPAPRDRCState ready_state;
+    SpaprDrcState empty_state;
+    SpaprDrcState ready_state;
 
     /*< public >*/
-    sPAPRDRConnectorTypeShift typeshift;
+    SpaprDrcTypeShift typeshift;
     const char *typename; /* used in device tree, PAPR 13.5.2.6 & C.6.1 */
     const char *drc_name_prefix; /* used other places in device tree */
 
-    sPAPRDREntitySense (*dr_entity_sense)(sPAPRDRConnector *drc);
-    uint32_t (*isolate)(sPAPRDRConnector *drc);
-    uint32_t (*unisolate)(sPAPRDRConnector *drc);
+    SpaprDREntitySense (*dr_entity_sense)(SpaprDrc *drc);
+    uint32_t (*isolate)(SpaprDrc *drc);
+    uint32_t (*unisolate)(SpaprDrc *drc);
     void (*release)(DeviceState *dev);
 
-    int (*dt_populate)(sPAPRDRConnector *drc, struct sPAPRMachineState *spapr,
+    int (*dt_populate)(SpaprDrc *drc, struct SpaprMachineState *spapr,
                        void *fdt, int *fdt_start_offset, Error **errp);
-} sPAPRDRConnectorClass;
+} SpaprDrcClass;
 
-typedef struct sPAPRDRCPhysical {
+typedef struct SpaprDrcPhysical {
     /*< private >*/
-    sPAPRDRConnector parent;
+    SpaprDrc parent;
 
     /* DR-indicator */
     uint32_t dr_indicator;
-} sPAPRDRCPhysical;
+} SpaprDrcPhysical;
 
 static inline bool spapr_drc_hotplugged(DeviceState *dev)
 {
     return dev->hotplugged && !runstate_check(RUN_STATE_INMIGRATE);
 }
 
-void spapr_drc_reset(sPAPRDRConnector *drc);
+void spapr_drc_reset(SpaprDrc *drc);
 
-uint32_t spapr_drc_index(sPAPRDRConnector *drc);
-sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc);
+uint32_t spapr_drc_index(SpaprDrc *drc);
+SpaprDrcType spapr_drc_type(SpaprDrc *drc);
 
-sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
+SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
                                          uint32_t id);
-sPAPRDRConnector *spapr_drc_by_index(uint32_t index);
-sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id);
+SpaprDrc *spapr_drc_by_index(uint32_t index);
+SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id);
 int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
                           uint32_t drc_type_mask);
 
-void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, Error **errp);
-void spapr_drc_detach(sPAPRDRConnector *drc);
+void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp);
+void spapr_drc_detach(SpaprDrc *drc);
 bool spapr_drc_needed(void *opaque);
 
-static inline bool spapr_drc_unplug_requested(sPAPRDRConnector *drc)
+static inline bool spapr_drc_unplug_requested(SpaprDrc *drc)
 {
     return drc->unplug_requested;
 }
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
index ec1ee64..b855f74 100644
--- a/include/hw/ppc/spapr_irq.h
+++ b/include/hw/ppc/spapr_irq.h
@@ -22,51 +22,51 @@
 #define SPAPR_IRQ_MSI        0x1300  /* Offset of the dynamic range covered
                                       * by the bitmap allocator */
 
-typedef struct sPAPRMachineState sPAPRMachineState;
+typedef struct SpaprMachineState SpaprMachineState;
 
-void spapr_irq_msi_init(sPAPRMachineState *spapr, uint32_t nr_msis);
-int spapr_irq_msi_alloc(sPAPRMachineState *spapr, uint32_t num, bool align,
+void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis);
+int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align,
                         Error **errp);
-void spapr_irq_msi_free(sPAPRMachineState *spapr, int irq, uint32_t num);
-void spapr_irq_msi_reset(sPAPRMachineState *spapr);
+void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num);
+void spapr_irq_msi_reset(SpaprMachineState *spapr);
 
-typedef struct sPAPRIrq {
+typedef struct SpaprIrq {
     uint32_t    nr_irqs;
     uint32_t    nr_msis;
     uint8_t     ov5;
 
-    void (*init)(sPAPRMachineState *spapr, int nr_irqs, Error **errp);
-    int (*claim)(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
-    void (*free)(sPAPRMachineState *spapr, int irq, int num);
-    qemu_irq (*qirq)(sPAPRMachineState *spapr, int irq);
-    void (*print_info)(sPAPRMachineState *spapr, Monitor *mon);
-    void (*dt_populate)(sPAPRMachineState *spapr, uint32_t nr_servers,
+    void (*init)(SpaprMachineState *spapr, int nr_irqs, Error **errp);
+    int (*claim)(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
+    void (*free)(SpaprMachineState *spapr, int irq, int num);
+    qemu_irq (*qirq)(SpaprMachineState *spapr, int irq);
+    void (*print_info)(SpaprMachineState *spapr, Monitor *mon);
+    void (*dt_populate)(SpaprMachineState *spapr, uint32_t nr_servers,
                         void *fdt, uint32_t phandle);
-    void (*cpu_intc_create)(sPAPRMachineState *spapr, PowerPCCPU *cpu,
+    void (*cpu_intc_create)(SpaprMachineState *spapr, PowerPCCPU *cpu,
                             Error **errp);
-    int (*post_load)(sPAPRMachineState *spapr, int version_id);
-    void (*reset)(sPAPRMachineState *spapr, Error **errp);
+    int (*post_load)(SpaprMachineState *spapr, int version_id);
+    void (*reset)(SpaprMachineState *spapr, Error **errp);
     void (*set_irq)(void *opaque, int srcno, int val);
-    const char *(*get_nodename)(sPAPRMachineState *spapr);
-} sPAPRIrq;
+    const char *(*get_nodename)(SpaprMachineState *spapr);
+} SpaprIrq;
 
-extern sPAPRIrq spapr_irq_xics;
-extern sPAPRIrq spapr_irq_xics_legacy;
-extern sPAPRIrq spapr_irq_xive;
-extern sPAPRIrq spapr_irq_dual;
+extern SpaprIrq spapr_irq_xics;
+extern SpaprIrq spapr_irq_xics_legacy;
+extern SpaprIrq spapr_irq_xive;
+extern SpaprIrq spapr_irq_dual;
 
-void spapr_irq_init(sPAPRMachineState *spapr, Error **errp);
-int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
-void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num);
-qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq);
-int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id);
-void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp);
-int spapr_irq_get_phandle(sPAPRMachineState *spapr, void *fdt, Error **errp);
+void spapr_irq_init(SpaprMachineState *spapr, Error **errp);
+int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp);
+void spapr_irq_free(SpaprMachineState *spapr, int irq, int num);
+qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq);
+int spapr_irq_post_load(SpaprMachineState *spapr, int version_id);
+void spapr_irq_reset(SpaprMachineState *spapr, Error **errp);
+int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp);
 
 /*
  * XICS legacy routines
  */
-int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp);
+int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp);
 #define spapr_irq_findone(spapr, errp) spapr_irq_find(spapr, 1, false, errp)
 
 #endif
diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h
index 0f2d8d7..188a936 100644
--- a/include/hw/ppc/spapr_ovec.h
+++ b/include/hw/ppc/spapr_ovec.h
@@ -39,7 +39,7 @@
 #include "cpu.h"
 #include "migration/vmstate.h"
 
-typedef struct sPAPROptionVector sPAPROptionVector;
+typedef struct SpaprOptionVector SpaprOptionVector;
 
 #define OV_BIT(byte, bit) ((byte - 1) * BITS_PER_BYTE + bit)
 
@@ -61,21 +61,21 @@
 #define OV5_MMU_RADIX_GTSE      OV_BIT(26, 1) /* Radix GTSE */
 
 /* interfaces */
-sPAPROptionVector *spapr_ovec_new(void);
-sPAPROptionVector *spapr_ovec_clone(sPAPROptionVector *ov_orig);
-void spapr_ovec_intersect(sPAPROptionVector *ov,
-                          sPAPROptionVector *ov1,
-                          sPAPROptionVector *ov2);
-bool spapr_ovec_diff(sPAPROptionVector *ov,
-                     sPAPROptionVector *ov_old,
-                     sPAPROptionVector *ov_new);
-void spapr_ovec_cleanup(sPAPROptionVector *ov);
-void spapr_ovec_set(sPAPROptionVector *ov, long bitnr);
-void spapr_ovec_clear(sPAPROptionVector *ov, long bitnr);
-bool spapr_ovec_test(sPAPROptionVector *ov, long bitnr);
-sPAPROptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
+SpaprOptionVector *spapr_ovec_new(void);
+SpaprOptionVector *spapr_ovec_clone(SpaprOptionVector *ov_orig);
+void spapr_ovec_intersect(SpaprOptionVector *ov,
+                          SpaprOptionVector *ov1,
+                          SpaprOptionVector *ov2);
+bool spapr_ovec_diff(SpaprOptionVector *ov,
+                     SpaprOptionVector *ov_old,
+                     SpaprOptionVector *ov_new);
+void spapr_ovec_cleanup(SpaprOptionVector *ov);
+void spapr_ovec_set(SpaprOptionVector *ov, long bitnr);
+void spapr_ovec_clear(SpaprOptionVector *ov, long bitnr);
+bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr);
+SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
 int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
-                           sPAPROptionVector *ov, const char *name);
+                           SpaprOptionVector *ov, const char *name);
 
 /* migration */
 extern const VMStateDescription vmstate_spapr_ovec;
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index e8b006d..04609f2 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -26,91 +26,91 @@
 
 #define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
 #define VIO_SPAPR_DEVICE(obj) \
-     OBJECT_CHECK(VIOsPAPRDevice, (obj), TYPE_VIO_SPAPR_DEVICE)
+     OBJECT_CHECK(SpaprVioDevice, (obj), TYPE_VIO_SPAPR_DEVICE)
 #define VIO_SPAPR_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(VIOsPAPRDeviceClass, (klass), TYPE_VIO_SPAPR_DEVICE)
+     OBJECT_CLASS_CHECK(SpaprVioDeviceClass, (klass), TYPE_VIO_SPAPR_DEVICE)
 #define VIO_SPAPR_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(VIOsPAPRDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE)
+     OBJECT_GET_CLASS(SpaprVioDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE)
 
 #define TYPE_SPAPR_VIO_BUS "spapr-vio-bus"
-#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(VIOsPAPRBus, (obj), TYPE_SPAPR_VIO_BUS)
+#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(SpaprVioBus, (obj), TYPE_SPAPR_VIO_BUS)
 
 #define TYPE_SPAPR_VIO_BRIDGE "spapr-vio-bridge"
 
-typedef struct VIOsPAPR_CRQ {
+typedef struct SpaprVioCrq {
     uint64_t qladdr;
     uint32_t qsize;
     uint32_t qnext;
-    int(*SendFunc)(struct VIOsPAPRDevice *vdev, uint8_t *crq);
-} VIOsPAPR_CRQ;
+    int(*SendFunc)(struct SpaprVioDevice *vdev, uint8_t *crq);
+} SpaprVioCrq;
 
-typedef struct VIOsPAPRDevice VIOsPAPRDevice;
-typedef struct VIOsPAPRBus VIOsPAPRBus;
+typedef struct SpaprVioDevice SpaprVioDevice;
+typedef struct SpaprVioBus SpaprVioBus;
 
-typedef struct VIOsPAPRDeviceClass {
+typedef struct SpaprVioDeviceClass {
     DeviceClass parent_class;
 
     const char *dt_name, *dt_type, *dt_compatible;
     target_ulong signal_mask;
     uint32_t rtce_window_size;
-    void (*realize)(VIOsPAPRDevice *dev, Error **errp);
-    void (*reset)(VIOsPAPRDevice *dev);
-    int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
-} VIOsPAPRDeviceClass;
+    void (*realize)(SpaprVioDevice *dev, Error **errp);
+    void (*reset)(SpaprVioDevice *dev);
+    int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off);
+} SpaprVioDeviceClass;
 
-struct VIOsPAPRDevice {
+struct SpaprVioDevice {
     DeviceState qdev;
     uint32_t reg;
     uint32_t irq;
     uint64_t signal_state;
-    VIOsPAPR_CRQ crq;
+    SpaprVioCrq crq;
     AddressSpace as;
     MemoryRegion mrroot;
     MemoryRegion mrbypass;
-    sPAPRTCETable *tcet;
+    SpaprTceTable *tcet;
 };
 
 #define DEFINE_SPAPR_PROPERTIES(type, field)           \
         DEFINE_PROP_UINT32("reg", type, field.reg, -1)
 
-struct VIOsPAPRBus {
+struct SpaprVioBus {
     BusState bus;
     uint32_t next_reg;
 };
 
-extern VIOsPAPRBus *spapr_vio_bus_init(void);
-extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
-void spapr_dt_vdevice(VIOsPAPRBus *bus, void *fdt);
-extern gchar *spapr_vio_stdout_path(VIOsPAPRBus *bus);
+extern SpaprVioBus *spapr_vio_bus_init(void);
+extern SpaprVioDevice *spapr_vio_find_by_reg(SpaprVioBus *bus, uint32_t reg);
+void spapr_dt_vdevice(SpaprVioBus *bus, void *fdt);
+extern gchar *spapr_vio_stdout_path(SpaprVioBus *bus);
 
-static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev)
+static inline qemu_irq spapr_vio_qirq(SpaprVioDevice *dev)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
 
     return spapr_qirq(spapr, dev->irq);
 }
 
-static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr,
+static inline bool spapr_vio_dma_valid(SpaprVioDevice *dev, uint64_t taddr,
                                        uint32_t size, DMADirection dir)
 {
     return dma_memory_valid(&dev->as, taddr, size, dir);
 }
 
-static inline int spapr_vio_dma_read(VIOsPAPRDevice *dev, uint64_t taddr,
+static inline int spapr_vio_dma_read(SpaprVioDevice *dev, uint64_t taddr,
                                      void *buf, uint32_t size)
 {
     return (dma_memory_read(&dev->as, taddr, buf, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
-static inline int spapr_vio_dma_write(VIOsPAPRDevice *dev, uint64_t taddr,
+static inline int spapr_vio_dma_write(SpaprVioDevice *dev, uint64_t taddr,
                                       const void *buf, uint32_t size)
 {
     return (dma_memory_write(&dev->as, taddr, buf, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
-static inline int spapr_vio_dma_set(VIOsPAPRDevice *dev, uint64_t taddr,
+static inline int spapr_vio_dma_set(SpaprVioDevice *dev, uint64_t taddr,
                                     uint8_t c, uint32_t size)
 {
     return (dma_memory_set(&dev->as, taddr, c, size) != 0) ?
@@ -123,21 +123,21 @@
 #define vio_stq(_dev, _addr, _val) (stq_be_dma(&(_dev)->as, (_addr), (_val)))
 #define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->as, (_addr)))
 
-int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
+int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq);
 
-VIOsPAPRDevice *vty_lookup(sPAPRMachineState *spapr, target_ulong reg);
-void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
-void spapr_vty_create(VIOsPAPRBus *bus, Chardev *chardev);
-void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd);
-void spapr_vscsi_create(VIOsPAPRBus *bus);
+SpaprVioDevice *vty_lookup(SpaprMachineState *spapr, target_ulong reg);
+void vty_putchars(SpaprVioDevice *sdev, uint8_t *buf, int len);
+void spapr_vty_create(SpaprVioBus *bus, Chardev *chardev);
+void spapr_vlan_create(SpaprVioBus *bus, NICInfo *nd);
+void spapr_vscsi_create(SpaprVioBus *bus);
 
-VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
+SpaprVioDevice *spapr_vty_get_default(SpaprVioBus *bus);
 
 extern const VMStateDescription vmstate_spapr_vio;
 
 #define VMSTATE_SPAPR_VIO(_f, _s) \
-    VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, VIOsPAPRDevice)
+    VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, SpaprVioDevice)
 
-void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass);
+void spapr_vio_set_bypass(SpaprVioDevice *dev, bool bypass);
 
 #endif /* HW_SPAPR_VIO_H */
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 2d31f24..fc3e965 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -13,9 +13,9 @@
 #include "hw/ppc/xive.h"
 
 #define TYPE_SPAPR_XIVE "spapr-xive"
-#define SPAPR_XIVE(obj) OBJECT_CHECK(sPAPRXive, (obj), TYPE_SPAPR_XIVE)
+#define SPAPR_XIVE(obj) OBJECT_CHECK(SpaprXive, (obj), TYPE_SPAPR_XIVE)
 
-typedef struct sPAPRXive {
+typedef struct SpaprXive {
     XiveRouter    parent;
 
     /* Internal interrupt source for IPIs and virtual devices */
@@ -38,16 +38,16 @@
     /* TIMA mapping address */
     hwaddr        tm_base;
     MemoryRegion  tm_mmio;
-} sPAPRXive;
+} SpaprXive;
 
-bool spapr_xive_irq_claim(sPAPRXive *xive, uint32_t lisn, bool lsi);
-bool spapr_xive_irq_free(sPAPRXive *xive, uint32_t lisn);
-void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon);
+bool spapr_xive_irq_claim(SpaprXive *xive, uint32_t lisn, bool lsi);
+bool spapr_xive_irq_free(SpaprXive *xive, uint32_t lisn);
+void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon);
 
-void spapr_xive_hcall_init(sPAPRMachineState *spapr);
-void spapr_dt_xive(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt,
+void spapr_xive_hcall_init(SpaprMachineState *spapr);
+void spapr_dt_xive(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
                    uint32_t phandle);
 void spapr_xive_set_tctx_os_cam(XiveTCTX *tctx);
-void spapr_xive_mmio_set_enabled(sPAPRXive *xive, bool enable);
+void spapr_xive_mmio_set_enabled(SpaprXive *xive, bool enable);
 
 #endif /* PPC_SPAPR_XIVE_H */
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
index b8d924b..15a8dcf 100644
--- a/include/hw/ppc/xics_spapr.h
+++ b/include/hw/ppc/xics_spapr.h
@@ -31,9 +31,9 @@
 
 #define XICS_NODENAME "interrupt-controller"
 
-void spapr_dt_xics(sPAPRMachineState *spapr, uint32_t nr_servers, void *fdt,
+void spapr_dt_xics(SpaprMachineState *spapr, uint32_t nr_servers, void *fdt,
                    uint32_t phandle);
-int xics_kvm_init(sPAPRMachineState *spapr, Error **errp);
-void xics_spapr_init(sPAPRMachineState *spapr);
+int xics_kvm_init(SpaprMachineState *spapr, Error **errp);
+void xics_spapr_init(SpaprMachineState *spapr);
 
 #endif /* XICS_SPAPR_H */
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 13a4875..c4f2774 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -364,6 +364,7 @@
 int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
                           XiveNVT *nvt, uint8_t word_number);
 XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs);
+void xive_router_notify(XiveNotifier *xn, uint32_t lisn);
 
 /*
  * XIVE END ESBs
@@ -410,6 +411,9 @@
 #define XIVE_TM_USER_PAGE       0x3
 
 extern const MemoryRegionOps xive_tm_ops;
+void xive_tctx_tm_write(XiveTCTX *tctx, hwaddr offset, uint64_t value,
+                        unsigned size);
+uint64_t xive_tctx_tm_read(XiveTCTX *tctx, hwaddr offset, unsigned size);
 
 void xive_tctx_pic_print_info(XiveTCTX *tctx, Monitor *mon);
 Object *xive_tctx_create(Object *cpu, XiveRouter *xrtr, Error **errp);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 17f09aa..33ed3b8 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -431,8 +431,6 @@
 
 Object *qdev_get_machine(void);
 
-void object_apply_compat_props(Object *obj);
-
 /* FIXME: make this a link<> */
 void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
 
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index b65a2f0..1155b79 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -193,6 +193,8 @@
 int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
                              uint32_t subtype, struct vfio_region_info **info);
 bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type);
+struct vfio_info_cap_header *
+vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id);
 #endif
 extern const MemoryListener vfio_prereg_listener;
 
diff --git a/include/qom/object.h b/include/qom/object.h
index e026296..288cddd 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -677,6 +677,9 @@
 
 void object_apply_global_props(Object *obj, const GPtrArray *props,
                                Error **errp);
+void object_set_machine_compat_props(GPtrArray *compat_props);
+void object_set_accelerator_compat_props(GPtrArray *compat_props);
+void object_apply_compat_props(Object *obj);
 
 /**
  * object_set_props:
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 89604a8..6065d9e 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -110,7 +110,6 @@
 extern int boot_menu;
 extern bool boot_strict;
 extern uint8_t *boot_splash_filedata;
-extern size_t boot_splash_filedata_size;
 extern bool enable_mlock;
 extern bool enable_cpu_pm;
 extern QEMUClockType rtc_clock;
diff --git a/memory.c b/memory.c
index 61d66e4..e49369d 100644
--- a/memory.c
+++ b/memory.c
@@ -932,9 +932,7 @@
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both and unchanged (except logging may have changed) */
 
-            if (!adding) {
-                flat_range_coalesced_io_del(frold, as);
-            } else {
+            if (adding) {
                 MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_nop);
                 if (frnew->dirty_log_mask & ~frold->dirty_log_mask) {
                     MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, log_start,
@@ -946,7 +944,6 @@
                                                   frold->dirty_log_mask,
                                                   frnew->dirty_log_mask);
                 }
-                flat_range_coalesced_io_add(frnew, as);
             }
 
             ++iold;
diff --git a/pc-bios/u-boot.e500 b/pc-bios/u-boot.e500
index 25537f8..732660f 100644
--- a/pc-bios/u-boot.e500
+++ b/pc-bios/u-boot.e500
Binary files differ
diff --git a/qapi/char.json b/qapi/char.json
index 77ed847..a6e81ac 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -248,6 +248,11 @@
 # @addr: socket address to listen on (server=true)
 #        or connect to (server=false)
 # @tls-creds: the ID of the TLS credentials object (since 2.6)
+# @tls-authz: the ID of the QAuthZ authorization object against which
+#             the client's x509 distinguished name will be validated. This
+#             object is only resolved at time of use, so can be deleted
+#             and recreated on the fly while the chardev server is active.
+#             If missing, it will default to denying access (since 4.0)
 # @server: create server socket (default: true)
 # @wait: wait for incoming connection on server
 #        sockets (default: false).
@@ -268,6 +273,7 @@
 { 'struct': 'ChardevSocket',
   'data': { 'addr': 'SocketAddressLegacy',
             '*tls-creds': 'str',
+            '*tls-authz'  : 'str',
             '*server': 'bool',
             '*wait': 'bool',
             '*nodelay': 'bool',
diff --git a/qemu-options.hx b/qemu-options.hx
index c74f99b..7118d90 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2428,7 +2428,7 @@
     "-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
     "-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4][,ipv6][,nodelay][,reconnect=seconds]\n"
     "         [,server][,nowait][,telnet][,websocket][,reconnect=seconds][,mux=on|off]\n"
-    "         [,logfile=PATH][,logappend=on|off][,tls-creds=ID] (tcp)\n"
+    "         [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n"
     "-chardev socket,id=id,path=path[,server][,nowait][,telnet][,websocket][,reconnect=seconds]\n"
     "         [,mux=on|off][,logfile=PATH][,logappend=on|off] (unix)\n"
     "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n"
@@ -2557,7 +2557,7 @@
 A void device. This device will not emit any data, and will drop any data it
 receives. The null backend does not take any options.
 
-@item -chardev socket,id=@var{id}[,@var{TCP options} or @var{unix options}][,server][,nowait][,telnet][,websocket][,reconnect=@var{seconds}][,tls-creds=@var{id}]
+@item -chardev socket,id=@var{id}[,@var{TCP options} or @var{unix options}][,server][,nowait][,telnet][,websocket][,reconnect=@var{seconds}][,tls-creds=@var{id}][,tls-authz=@var{id}]
 
 Create a two-way stream socket, which can be either a TCP or a unix socket. A
 unix socket will be created if @option{path} is specified. Behaviour is
@@ -2583,6 +2583,12 @@
 credentials must be previously created with the @option{-object tls-creds}
 argument.
 
+@option{tls-auth} provides the ID of the QAuthZ authorization object against
+which the client's x509 distinguished name will be validated. This object is
+only resolved at time of use, so can be deleted and recreated on the fly
+while the chardev server is active. If missing, it will default to denying
+access.
+
 TCP and unix socket options are given below:
 
 @table @option
diff --git a/qom/cpu.c b/qom/cpu.c
index f5579b1..a8d2958 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -380,6 +380,9 @@
 
 static void cpu_common_finalize(Object *obj)
 {
+    CPUState *cpu = CPU(obj);
+
+    qemu_mutex_destroy(&cpu->work_mutex);
 }
 
 static int64_t cpu_common_get_arch_id(CPUState *cpu)
diff --git a/qom/object.c b/qom/object.c
index 05a8567..e3206d6 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -408,6 +408,45 @@
     }
 }
 
+/*
+ * Global property defaults
+ * Slot 0: accelerator's global property defaults
+ * Slot 1: machine's global property defaults
+ * Each is a GPtrArray of of GlobalProperty.
+ * Applied in order, later entries override earlier ones.
+ */
+static GPtrArray *object_compat_props[2];
+
+/*
+ * Set machine's global property defaults to @compat_props.
+ * May be called at most once.
+ */
+void object_set_machine_compat_props(GPtrArray *compat_props)
+{
+    assert(!object_compat_props[1]);
+    object_compat_props[1] = compat_props;
+}
+
+/*
+ * Set accelerator's global property defaults to @compat_props.
+ * May be called at most once.
+ */
+void object_set_accelerator_compat_props(GPtrArray *compat_props)
+{
+    assert(!object_compat_props[0]);
+    object_compat_props[0] = compat_props;
+}
+
+void object_apply_compat_props(Object *obj)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
+        object_apply_global_props(obj, object_compat_props[i],
+                                  &error_abort);
+    }
+}
+
 static void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
 {
     Object *obj = data;
diff --git a/roms/u-boot b/roms/u-boot
index d85ca02..d368926 160000
--- a/roms/u-boot
+++ b/roms/u-boot
@@ -1 +1 @@
-Subproject commit d85ca029f257b53a96da6c2fb421e78a003a9943
+Subproject commit d3689267f92c5956e09cc7d1baa4700141662bff
diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py
index 690827e..f2a305c 100644
--- a/scripts/qemu-gdb.py
+++ b/scripts/qemu-gdb.py
@@ -7,11 +7,8 @@
 # Authors:
 #  Avi Kivity <avi@redhat.com>
 #
-# This work is licensed under the terms of the GNU GPL, version 2.  See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
 
 # Usage:
 # At the (gdb) prompt, type "source scripts/qemu-gdb.py".
diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index 81f811a..41e079d 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -7,11 +7,8 @@
 # Authors:
 #  Avi Kivity <avi@redhat.com>
 #
-# This work is licensed under the terms of the GNU GPL, version 2.  See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# This work is licensed under the terms of the GNU GPL, version 2
+# or later.  See the COPYING file in the top-level directory.
 
 import gdb
 
diff --git a/scripts/qemugdb/mtree.py b/scripts/qemugdb/mtree.py
index e6791b7..3030a60 100644
--- a/scripts/qemugdb/mtree.py
+++ b/scripts/qemugdb/mtree.py
@@ -7,11 +7,8 @@
 # Authors:
 #  Avi Kivity <avi@redhat.com>
 #
-# This work is licensed under the terms of the GNU GPL, version 2.  See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
 
 # 'qemu mtree' -- display the memory hierarchy
 
diff --git a/scripts/qemugdb/tcg.py b/scripts/qemugdb/tcg.py
index 8c7f1d7..18880fc 100644
--- a/scripts/qemugdb/tcg.py
+++ b/scripts/qemugdb/tcg.py
@@ -8,11 +8,8 @@
 # Authors:
 #  Alex Bennée <alex.bennee@linaro.org>
 #
-# This work is licensed under the terms of the GNU GPL, version 2.  See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
 
 # 'qemu tcg-lock-status' -- display the TCG lock status across threads
 
diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs
index cb9c265..48e0c28 100644
--- a/target/i386/Makefile.objs
+++ b/target/i386/Makefile.objs
@@ -3,10 +3,10 @@
 obj-$(CONFIG_TCG) += bpt_helper.o cc_helper.o excp_helper.o fpu_helper.o
 obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o mpx_helper.o
 obj-$(CONFIG_TCG) += seg_helper.o smm_helper.o svm_helper.o
+obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
 ifeq ($(CONFIG_SOFTMMU),y)
 obj-y += machine.o arch_memory_mapping.o arch_dump.o monitor.o
 obj-$(CONFIG_KVM) += kvm.o
-obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
 obj-$(CONFIG_HYPERV) += hyperv.o
 obj-$(call lnot,$(CONFIG_HYPERV)) += hyperv-stub.o
 ifeq ($(CONFIG_WIN32),y)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index d3aa6a8..d90c01a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5031,6 +5031,13 @@
         x86_cpu_adjust_feat_level(cpu, FEAT_C000_0001_EDX);
         x86_cpu_adjust_feat_level(cpu, FEAT_SVM);
         x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE);
+
+        /* Intel Processor Trace requires CPUID[0x14] */
+        if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) &&
+             kvm_enabled() && cpu->intel_pt_auto_level) {
+            x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14);
+        }
+
         /* SVM requires CPUID[0x8000000A] */
         if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
             x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
@@ -5824,6 +5831,8 @@
     DEFINE_PROP_INT32("x-hv-max-vps", X86CPU, hv_max_vps, -1),
     DEFINE_PROP_BOOL("x-hv-synic-kvm-only", X86CPU, hyperv_synic_kvm_only,
                      false),
+    DEFINE_PROP_BOOL("x-intel-pt-auto-level", X86CPU, intel_pt_auto_level,
+                     true),
     DEFINE_PROP_END_OF_LIST()
 };
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 95112b9..83fb522 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1454,6 +1454,9 @@
     /* Enable auto level-increase for all CPUID leaves */
     bool full_cpuid_auto_level;
 
+    /* Enable auto level-increase for Intel Processor Trace leave */
+    bool intel_pt_auto_level;
+
     /* if true fill the top bits of the MTRR_PHYSMASKn variable range */
     bool fill_mtrr_mask;
 
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index ae51fe7..be9b4c3 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -190,6 +190,7 @@
 #endif
     const PPCHash64Options *hash64_opts;
     struct ppc_radix_page_info *radix_page_info;
+    uint32_t lrg_decr_bits;
     void (*init_proc)(CPUPPCState *env);
     int  (*check_pow)(CPUPPCState *env);
     int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 26604dd..fc12b468 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1321,10 +1321,10 @@
 void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value);
 void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value);
 bool ppc_decr_clear_on_delivery(CPUPPCState *env);
-uint32_t cpu_ppc_load_decr (CPUPPCState *env);
-void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value);
-uint32_t cpu_ppc_load_hdecr (CPUPPCState *env);
-void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value);
+target_ulong cpu_ppc_load_decr(CPUPPCState *env);
+void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value);
+target_ulong cpu_ppc_load_hdecr(CPUPPCState *env);
+void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value);
 uint64_t cpu_ppc_load_purr (CPUPPCState *env);
 uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env);
 uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env);
@@ -2563,19 +2563,64 @@
 }
 
 /* Accessors for FP, VMX and VSX registers */
+#if defined(HOST_WORDS_BIGENDIAN)
+#define VsrB(i) u8[i]
+#define VsrSB(i) s8[i]
+#define VsrH(i) u16[i]
+#define VsrSH(i) s16[i]
+#define VsrW(i) u32[i]
+#define VsrSW(i) s32[i]
+#define VsrD(i) u64[i]
+#define VsrSD(i) s64[i]
+#else
+#define VsrB(i) u8[15 - (i)]
+#define VsrSB(i) s8[15 - (i)]
+#define VsrH(i) u16[7 - (i)]
+#define VsrSH(i) s16[7 - (i)]
+#define VsrW(i) u32[3 - (i)]
+#define VsrSW(i) s32[3 - (i)]
+#define VsrD(i) u64[1 - (i)]
+#define VsrSD(i) s64[1 - (i)]
+#endif
+
+static inline int vsr64_offset(int i, bool high)
+{
+    return offsetof(CPUPPCState, vsr[i].VsrD(high ? 0 : 1));
+}
+
+static inline int vsr_full_offset(int i)
+{
+    return offsetof(CPUPPCState, vsr[i].u64[0]);
+}
+
+static inline int fpr_offset(int i)
+{
+    return vsr64_offset(i, true);
+}
+
 static inline uint64_t *cpu_fpr_ptr(CPUPPCState *env, int i)
 {
-    return &env->vsr[i].u64[0];
+    return (uint64_t *)((uintptr_t)env + fpr_offset(i));
 }
 
 static inline uint64_t *cpu_vsrl_ptr(CPUPPCState *env, int i)
 {
-    return &env->vsr[i].u64[1];
+    return (uint64_t *)((uintptr_t)env + vsr64_offset(i, false));
+}
+
+static inline long avr64_offset(int i, bool high)
+{
+    return vsr64_offset(i + 32, high);
+}
+
+static inline int avr_full_offset(int i)
+{
+    return vsr_full_offset(i + 32);
 }
 
 static inline ppc_avr_t *cpu_avr_ptr(CPUPPCState *env, int i)
 {
-    return &env->vsr[32 + i];
+    return (ppc_avr_t *)((uintptr_t)env + avr_full_offset(i));
 }
 
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 39bedbb..beafcf1 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -107,6 +107,24 @@
     return POWERPC_EXCP_RESET;
 }
 
+static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail)
+{
+    uint64_t offset = 0;
+
+    switch (ail) {
+    case AIL_0001_8000:
+        offset = 0x18000;
+        break;
+    case AIL_C000_0000_0000_4000:
+        offset = 0xc000000000004000ull;
+        break;
+    default:
+        cpu_abort(cs, "Invalid AIL combination %d\n", ail);
+        break;
+    }
+
+    return offset;
+}
 
 /* Note that this function should be greatly optimized
  * when called with a constant excp, from ppc_hw_interrupt
@@ -708,17 +726,7 @@
     /* Handle AIL */
     if (ail) {
         new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
-        switch(ail) {
-        case AIL_0001_8000:
-            vector |= 0x18000;
-            break;
-        case AIL_C000_0000_0000_4000:
-            vector |= 0xc000000000004000ull;
-            break;
-        default:
-            cpu_abort(cs, "Invalid AIL combination %d\n", ail);
-            break;
-        }
+        vector |= ppc_excp_vector_offset(cs, ail);
     }
 
 #if defined(TARGET_PPC64)
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index f26a71f..fb6f64e 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -204,35 +204,16 @@
 EXTRACT_HELPER(DCMX, 16, 7);
 EXTRACT_HELPER_SPLIT_3(DCMX_XV, 5, 16, 0, 1, 2, 5, 1, 6, 6);
 
-#if defined(HOST_WORDS_BIGENDIAN)
-#define VsrB(i) u8[i]
-#define VsrSB(i) s8[i]
-#define VsrH(i) u16[i]
-#define VsrSH(i) s16[i]
-#define VsrW(i) u32[i]
-#define VsrSW(i) s32[i]
-#define VsrD(i) u64[i]
-#define VsrSD(i) s64[i]
-#else
-#define VsrB(i) u8[15 - (i)]
-#define VsrSB(i) s8[15 - (i)]
-#define VsrH(i) u16[7 - (i)]
-#define VsrSH(i) s16[7 - (i)]
-#define VsrW(i) u32[3 - (i)]
-#define VsrSW(i) s32[3 - (i)]
-#define VsrD(i) u64[1 - (i)]
-#define VsrSD(i) s64[1 - (i)]
-#endif
 static inline void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
 {
-    vsr->VsrD(0) = env->vsr[n].u64[0];
-    vsr->VsrD(1) = env->vsr[n].u64[1];
+    vsr->VsrD(0) = env->vsr[n].VsrD(0);
+    vsr->VsrD(1) = env->vsr[n].VsrD(1);
 }
 
 static inline void putVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
 {
-    env->vsr[n].u64[0] = vsr->VsrD(0);
-    env->vsr[n].u64[1] = vsr->VsrD(1);
+    env->vsr[n].VsrD(0) = vsr->VsrD(0);
+    env->vsr[n].VsrD(1) = vsr->VsrD(1);
 }
 
 void helper_compute_fprf_float16(CPUPPCState *env, float16 arg);
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index d01852f..2427c8e 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -90,7 +90,9 @@
 static int cap_ppc_safe_cache;
 static int cap_ppc_safe_bounds_check;
 static int cap_ppc_safe_indirect_branch;
+static int cap_ppc_count_cache_flush_assist;
 static int cap_ppc_nested_kvm_hv;
+static int cap_large_decr;
 
 static uint32_t debug_inst_opcode;
 
@@ -124,6 +126,7 @@
 
 static int kvm_ppc_register_host_cpu_type(MachineState *ms);
 static void kvmppc_get_cpu_characteristics(KVMState *s);
+static int kvmppc_get_dec_bits(void);
 
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
@@ -151,6 +154,7 @@
     cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
     kvmppc_get_cpu_characteristics(s);
     cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
+    cap_large_decr = kvmppc_get_dec_bits();
     /*
      * Note: setting it to false because there is not such capability
      * in KVM at this moment.
@@ -752,7 +756,7 @@
 static int kvm_get_vpa(CPUState *cs)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
     struct kvm_one_reg reg;
     int ret;
 
@@ -792,7 +796,7 @@
 static int kvm_put_vpa(CPUState *cs)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
-    sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
+    SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
     struct kvm_one_reg reg;
     int ret;
 
@@ -1593,70 +1597,93 @@
     }
 }
 
+static int kvm_handle_hw_breakpoint(CPUState *cs,
+                                    struct kvm_debug_exit_arch *arch_info)
+{
+    int handle = 0;
+    int n;
+    int flag = 0;
+
+    if (nb_hw_breakpoint + nb_hw_watchpoint > 0) {
+        if (arch_info->status & KVMPPC_DEBUG_BREAKPOINT) {
+            n = find_hw_breakpoint(arch_info->address, GDB_BREAKPOINT_HW);
+            if (n >= 0) {
+                handle = 1;
+            }
+        } else if (arch_info->status & (KVMPPC_DEBUG_WATCH_READ |
+                                        KVMPPC_DEBUG_WATCH_WRITE)) {
+            n = find_hw_watchpoint(arch_info->address,  &flag);
+            if (n >= 0) {
+                handle = 1;
+                cs->watchpoint_hit = &hw_watchpoint;
+                hw_watchpoint.vaddr = hw_debug_points[n].addr;
+                hw_watchpoint.flags = flag;
+            }
+        }
+    }
+    return handle;
+}
+
+static int kvm_handle_singlestep(void)
+{
+    return 1;
+}
+
+static int kvm_handle_sw_breakpoint(void)
+{
+    return 1;
+}
+
 static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run)
 {
     CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     struct kvm_debug_exit_arch *arch_info = &run->debug.arch;
-    int handle = 0;
-    int n;
-    int flag = 0;
 
     if (cs->singlestep_enabled) {
-        handle = 1;
-    } else if (arch_info->status) {
-        if (nb_hw_breakpoint + nb_hw_watchpoint > 0) {
-            if (arch_info->status & KVMPPC_DEBUG_BREAKPOINT) {
-                n = find_hw_breakpoint(arch_info->address, GDB_BREAKPOINT_HW);
-                if (n >= 0) {
-                    handle = 1;
-                }
-            } else if (arch_info->status & (KVMPPC_DEBUG_WATCH_READ |
-                                            KVMPPC_DEBUG_WATCH_WRITE)) {
-                n = find_hw_watchpoint(arch_info->address,  &flag);
-                if (n >= 0) {
-                    handle = 1;
-                    cs->watchpoint_hit = &hw_watchpoint;
-                    hw_watchpoint.vaddr = hw_debug_points[n].addr;
-                    hw_watchpoint.flags = flag;
-                }
-            }
-        }
-    } else if (kvm_find_sw_breakpoint(cs, arch_info->address)) {
-        handle = 1;
-    } else {
-        /* QEMU is not able to handle debug exception, so inject
-         * program exception to guest;
-         * Yes program exception NOT debug exception !!
-         * When QEMU is using debug resources then debug exception must
-         * be always set. To achieve this we set MSR_DE and also set
-         * MSRP_DEP so guest cannot change MSR_DE.
-         * When emulating debug resource for guest we want guest
-         * to control MSR_DE (enable/disable debug interrupt on need).
-         * Supporting both configurations are NOT possible.
-         * So the result is that we cannot share debug resources
-         * between QEMU and Guest on BOOKE architecture.
-         * In the current design QEMU gets the priority over guest,
-         * this means that if QEMU is using debug resources then guest
-         * cannot use them;
-         * For software breakpoint QEMU uses a privileged instruction;
-         * So there cannot be any reason that we are here for guest
-         * set debug exception, only possibility is guest executed a
-         * privileged / illegal instruction and that's why we are
-         * injecting a program interrupt.
-         */
-
-        cpu_synchronize_state(cs);
-        /* env->nip is PC, so increment this by 4 to use
-         * ppc_cpu_do_interrupt(), which set srr0 = env->nip - 4.
-         */
-        env->nip += 4;
-        cs->exception_index = POWERPC_EXCP_PROGRAM;
-        env->error_code = POWERPC_EXCP_INVAL;
-        ppc_cpu_do_interrupt(cs);
+        return kvm_handle_singlestep();
     }
 
-    return handle;
+    if (arch_info->status) {
+        return kvm_handle_hw_breakpoint(cs, arch_info);
+    }
+
+    if (kvm_find_sw_breakpoint(cs, arch_info->address)) {
+        return kvm_handle_sw_breakpoint();
+    }
+
+    /*
+     * QEMU is not able to handle debug exception, so inject
+     * program exception to guest;
+     * Yes program exception NOT debug exception !!
+     * When QEMU is using debug resources then debug exception must
+     * be always set. To achieve this we set MSR_DE and also set
+     * MSRP_DEP so guest cannot change MSR_DE.
+     * When emulating debug resource for guest we want guest
+     * to control MSR_DE (enable/disable debug interrupt on need).
+     * Supporting both configurations are NOT possible.
+     * So the result is that we cannot share debug resources
+     * between QEMU and Guest on BOOKE architecture.
+     * In the current design QEMU gets the priority over guest,
+     * this means that if QEMU is using debug resources then guest
+     * cannot use them;
+     * For software breakpoint QEMU uses a privileged instruction;
+     * So there cannot be any reason that we are here for guest
+     * set debug exception, only possibility is guest executed a
+     * privileged / illegal instruction and that's why we are
+     * injecting a program interrupt.
+     */
+    cpu_synchronize_state(cs);
+    /*
+     * env->nip is PC, so increment this by 4 to use
+     * ppc_cpu_do_interrupt(), which set srr0 = env->nip - 4.
+     */
+    env->nip += 4;
+    cs->exception_index = POWERPC_EXCP_PROGRAM;
+    env->error_code = POWERPC_EXCP_INVAL;
+    ppc_cpu_do_interrupt(cs);
+
+    return 0;
 }
 
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
@@ -1927,6 +1954,16 @@
     return kvmppc_read_int_cpu_dt("clock-frequency");
 }
 
+static int kvmppc_get_dec_bits(void)
+{
+    int nr_bits = kvmppc_read_int_cpu_dt("ibm,dec-bits");
+
+    if (nr_bits > 0) {
+        return nr_bits;
+    }
+    return 0;
+}
+
 static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
  {
      PowerPCCPU *cpu = ppc_env_get_cpu(env);
@@ -2007,6 +2044,11 @@
     kvmppc_enable_hcall(kvm_state, H_CLEAR_MOD);
 }
 
+void kvmppc_enable_h_page_init(void)
+{
+    kvmppc_enable_hcall(kvm_state, H_PAGE_INIT);
+}
+
 void kvmppc_set_papr(PowerPCCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
@@ -2379,7 +2421,13 @@
 
 static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c)
 {
-    if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
+    if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) &&
+        (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) &&
+        (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) {
+        return SPAPR_CAP_FIXED_NA;
+    } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) {
+        return SPAPR_CAP_WORKAROUND;
+    } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
         return  SPAPR_CAP_FIXED_CCD;
     } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) {
         return SPAPR_CAP_FIXED_IBS;
@@ -2388,6 +2436,14 @@
     return 0;
 }
 
+static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c)
+{
+    if (c.character & c.character_mask & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) {
+        return 1;
+    }
+    return 0;
+}
+
 static void kvmppc_get_cpu_characteristics(KVMState *s)
 {
     struct kvm_ppc_cpu_char c;
@@ -2410,6 +2466,8 @@
     cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c);
     cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c);
     cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c);
+    cap_ppc_count_cache_flush_assist =
+        parse_cap_ppc_count_cache_flush_assist(c);
 }
 
 int kvmppc_get_cap_safe_cache(void)
@@ -2427,6 +2485,11 @@
     return cap_ppc_safe_indirect_branch;
 }
 
+int kvmppc_get_cap_count_cache_flush_assist(void)
+{
+    return cap_ppc_count_cache_flush_assist;
+}
+
 bool kvmppc_has_cap_nested_kvm_hv(void)
 {
     return !!cap_ppc_nested_kvm_hv;
@@ -2442,6 +2505,35 @@
     return cap_spapr_vfio;
 }
 
+int kvmppc_get_cap_large_decr(void)
+{
+    return cap_large_decr;
+}
+
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable)
+{
+    CPUState *cs = CPU(cpu);
+    uint64_t lpcr;
+
+    kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr);
+    /* Do we need to modify the LPCR? */
+    if (!!(lpcr & LPCR_LD) != !!enable) {
+        if (enable) {
+            lpcr |= LPCR_LD;
+        } else {
+            lpcr &= ~LPCR_LD;
+        }
+        kvm_set_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr);
+        kvm_get_one_reg(cs, KVM_REG_PPC_LPCR_64, &lpcr);
+
+        if (!!(lpcr & LPCR_LD) != !!enable) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
 {
     uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index bdfaa4e..2c2ea30 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -23,6 +23,7 @@
 void kvmppc_enable_logical_ci_hcalls(void);
 void kvmppc_enable_set_mode_hcall(void);
 void kvmppc_enable_clear_ref_mod_hcalls(void);
+void kvmppc_enable_h_page_init(void);
 void kvmppc_set_papr(PowerPCCPU *cpu);
 int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
 void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
@@ -62,8 +63,11 @@
 int kvmppc_get_cap_safe_cache(void);
 int kvmppc_get_cap_safe_bounds_check(void);
 int kvmppc_get_cap_safe_indirect_branch(void);
+int kvmppc_get_cap_count_cache_flush_assist(void);
 bool kvmppc_has_cap_nested_kvm_hv(void);
 int kvmppc_set_cap_nested_kvm_hv(int enable);
+int kvmppc_get_cap_large_decr(void);
+int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable);
 int kvmppc_enable_hwrng(void);
 int kvmppc_put_books_sregs(PowerPCCPU *cpu);
 PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
@@ -135,6 +139,10 @@
 {
 }
 
+static inline void kvmppc_enable_h_page_init(void)
+{
+}
+
 static inline void kvmppc_set_papr(PowerPCCPU *cpu)
 {
 }
@@ -322,6 +330,11 @@
     return 0;
 }
 
+static inline int kvmppc_get_cap_count_cache_flush_assist(void)
+{
+    return 0;
+}
+
 static inline bool kvmppc_has_cap_nested_kvm_hv(void)
 {
     return false;
@@ -332,6 +345,16 @@
     return -1;
 }
 
+static inline int kvmppc_get_cap_large_decr(void)
+{
+    return 0;
+}
+
+static inline int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable)
+{
+    return -1;
+}
+
 static inline int kvmppc_enable_hwrng(void)
 {
     return -1;
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index 756b6d2..a92d0ad 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -150,7 +150,7 @@
 {
     ppc_vsr_t *v = pv;
 
-    v->u64[0] = qemu_get_be64(f);
+    v->VsrD(0) = qemu_get_be64(f);
 
     return 0;
 }
@@ -160,7 +160,7 @@
 {
     ppc_vsr_t *v = pv;
 
-    qemu_put_be64(f, v->u64[0]);
+    qemu_put_be64(f, v->VsrD(0));
     return 0;
 }
 
@@ -181,7 +181,7 @@
 {
     ppc_vsr_t *v = pv;
 
-    v->u64[1] = qemu_get_be64(f);
+    v->VsrD(1) = qemu_get_be64(f);
 
     return 0;
 }
@@ -191,7 +191,7 @@
 {
     ppc_vsr_t *v = pv;
 
-    qemu_put_be64(f, v->u64[1]);
+    qemu_put_be64(f, v->VsrD(1));
     return 0;
 }
 
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index c431303..a2b1ec5 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -1109,7 +1109,7 @@
     case POWERPC_MMU_3_00: /* P9 */
         lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
                       (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
-                      LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR |
+                      LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD |
                       (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
                       LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC |
                       LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 819221f..98b37ce 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6677,34 +6677,22 @@
 
 static inline void get_fpr(TCGv_i64 dst, int regno)
 {
-    tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState, vsr[regno].u64[0]));
+    tcg_gen_ld_i64(dst, cpu_env, fpr_offset(regno));
 }
 
 static inline void set_fpr(int regno, TCGv_i64 src)
 {
-    tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, vsr[regno].u64[0]));
+    tcg_gen_st_i64(src, cpu_env, fpr_offset(regno));
 }
 
 static inline void get_avr64(TCGv_i64 dst, int regno, bool high)
 {
-#ifdef HOST_WORDS_BIGENDIAN
-    tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState,
-                                          vsr[32 + regno].u64[(high ? 0 : 1)]));
-#else
-    tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState,
-                                          vsr[32 + regno].u64[(high ? 1 : 0)]));
-#endif
+    tcg_gen_ld_i64(dst, cpu_env, avr64_offset(regno, high));
 }
 
 static inline void set_avr64(int regno, TCGv_i64 src, bool high)
 {
-#ifdef HOST_WORDS_BIGENDIAN
-    tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState,
-                                          vsr[32 + regno].u64[(high ? 0 : 1)]));
-#else
-    tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState,
-                                          vsr[32 + regno].u64[(high ? 1 : 0)]));
-#endif
+    tcg_gen_st_i64(src, cpu_env, avr64_offset(regno, high));
 }
 
 #include "translate/fp-impl.inc.c"
@@ -7417,7 +7405,7 @@
 #if !defined(NO_TIMER_DUMP)
     cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
 #if !defined(CONFIG_USER_ONLY)
-                " DECR %08" PRIu32
+                " DECR " TARGET_FMT_lu
 #endif
                 "\n",
                 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c
index f1b15ae..eb10c53 100644
--- a/target/ppc/translate/vmx-impl.inc.c
+++ b/target/ppc/translate/vmx-impl.inc.c
@@ -10,15 +10,10 @@
 static inline TCGv_ptr gen_avr_ptr(int reg)
 {
     TCGv_ptr r = tcg_temp_new_ptr();
-    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, vsr[32 + reg].u64[0]));
+    tcg_gen_addi_ptr(r, cpu_env, avr_full_offset(reg));
     return r;
 }
 
-static inline long avr64_offset(int reg, bool high)
-{
-    return offsetof(CPUPPCState, vsr[32 + reg].u64[(high ? 0 : 1)]);
-}
-
 #define GEN_VR_LDX(name, opc2, opc3)                                          \
 static void glue(gen_, name)(DisasContext *ctx)                                       \
 {                                                                             \
@@ -205,7 +200,7 @@
     }
 
     val = tcg_temp_new_i32();
-    bofs = avr64_offset(rB(ctx->opcode), true);
+    bofs = avr_full_offset(rB(ctx->opcode));
 #ifdef HOST_WORDS_BIGENDIAN
     bofs += 3 * 4;
 #endif
@@ -284,9 +279,9 @@
     }                                                                   \
                                                                         \
     tcg_op(vece,                                                        \
-           avr64_offset(rD(ctx->opcode), true),                         \
-           avr64_offset(rA(ctx->opcode), true),                         \
-           avr64_offset(rB(ctx->opcode), true),                         \
+           avr_full_offset(rD(ctx->opcode)),                            \
+           avr_full_offset(rA(ctx->opcode)),                            \
+           avr_full_offset(rB(ctx->opcode)),                            \
            16, 16);                                                     \
 }
 
@@ -578,10 +573,10 @@
         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
         return;                                                         \
     }                                                                   \
-    tcg_gen_gvec_4(avr64_offset(rD(ctx->opcode), true),                 \
+    tcg_gen_gvec_4(avr_full_offset(rD(ctx->opcode)),                    \
                    offsetof(CPUPPCState, vscr_sat),                     \
-                   avr64_offset(rA(ctx->opcode), true),                 \
-                   avr64_offset(rB(ctx->opcode), true),                 \
+                   avr_full_offset(rA(ctx->opcode)),                    \
+                   avr_full_offset(rB(ctx->opcode)),                    \
                    16, 16, &g);                                         \
 }
 
@@ -755,7 +750,7 @@
             return;                                                     \
         }                                                               \
         simm = SIMM5(ctx->opcode);                                      \
-        tcg_op(avr64_offset(rD(ctx->opcode), true), 16, 16, simm);      \
+        tcg_op(avr_full_offset(rD(ctx->opcode)), 16, 16, simm);         \
     }
 
 GEN_VXFORM_DUPI(vspltisb, tcg_gen_gvec_dup8i, 6, 12);
@@ -850,8 +845,8 @@
     }
 
     uimm = UIMM5(ctx->opcode);
-    bofs = avr64_offset(rB(ctx->opcode), true);
-    dofs = avr64_offset(rD(ctx->opcode), true);
+    bofs = avr_full_offset(rB(ctx->opcode));
+    dofs = avr_full_offset(rD(ctx->opcode));
 
     /* Experimental testing shows that hardware masks the immediate.  */
     bofs += (uimm << vece) & 15;
diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c
index e73197e..508e919 100644
--- a/target/ppc/translate/vsx-impl.inc.c
+++ b/target/ppc/translate/vsx-impl.inc.c
@@ -1,54 +1,23 @@
 /***                           VSX extension                               ***/
 
-static inline void get_vsr(TCGv_i64 dst, int n)
-{
-    tcg_gen_ld_i64(dst, cpu_env, offsetof(CPUPPCState, vsr[n].u64[1]));
-}
-
-static inline void set_vsr(int n, TCGv_i64 src)
-{
-    tcg_gen_st_i64(src, cpu_env, offsetof(CPUPPCState, vsr[n].u64[1]));
-}
-
-static inline int vsr_full_offset(int n)
-{
-    return offsetof(CPUPPCState, vsr[n].u64[0]);
-}
-
 static inline void get_cpu_vsrh(TCGv_i64 dst, int n)
 {
-    if (n < 32) {
-        get_fpr(dst, n);
-    } else {
-        get_avr64(dst, n - 32, true);
-    }
+    tcg_gen_ld_i64(dst, cpu_env, vsr64_offset(n, true));
 }
 
 static inline void get_cpu_vsrl(TCGv_i64 dst, int n)
 {
-    if (n < 32) {
-        get_vsr(dst, n);
-    } else {
-        get_avr64(dst, n - 32, false);
-    }
+    tcg_gen_ld_i64(dst, cpu_env, vsr64_offset(n, false));
 }
 
 static inline void set_cpu_vsrh(int n, TCGv_i64 src)
 {
-    if (n < 32) {
-        set_fpr(n, src);
-    } else {
-        set_avr64(n - 32, src, true);
-    }
+    tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, true));
 }
 
 static inline void set_cpu_vsrl(int n, TCGv_i64 src)
 {
-    if (n < 32) {
-        set_vsr(n, src);
-    } else {
-        set_avr64(n - 32, src, false);
-    }
+    tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, false));
 }
 
 #define VSX_LOAD_SCALAR(name, operation)                      \
@@ -1618,8 +1587,7 @@
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
     get_cpu_vsrh(t1, xB(ctx->opcode));
-    tcg_gen_andi_i64(rt, t1, 0x000FFFFFFFFFFFFF);
-    tcg_gen_or_i64(rt, rt, t0);
+    tcg_gen_deposit_i64(rt, t0, t1, 0, 52);
 
     tcg_temp_free_i64(t0);
     tcg_temp_free_i64(t1);
@@ -1655,8 +1623,7 @@
     tcg_gen_movi_i64(t0, 0x0001000000000000);
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
-    tcg_gen_andi_i64(xth, xbh, 0x0000FFFFFFFFFFFF);
-    tcg_gen_or_i64(xth, xth, t0);
+    tcg_gen_deposit_i64(xth, t0, xbh, 0, 48);
     set_cpu_vsrh(rD(ctx->opcode) + 32, xth);
     tcg_gen_mov_i64(xtl, xbl);
     set_cpu_vsrl(rD(ctx->opcode) + 32, xtl);
@@ -1726,7 +1693,6 @@
     TCGv_i64 xal;
     TCGv_i64 xbh;
     TCGv_i64 xbl;
-    TCGv_i64 t0;
 
     if (unlikely(!ctx->vsx_enabled)) {
         gen_exception(ctx, POWERPC_EXCP_VSXU);
@@ -1742,20 +1708,13 @@
     get_cpu_vsrl(xal, xA(ctx->opcode));
     get_cpu_vsrh(xbh, xB(ctx->opcode));
     get_cpu_vsrl(xbl, xB(ctx->opcode));
-    t0 = tcg_temp_new_i64();
 
-    tcg_gen_andi_i64(xth, xah, 0x800FFFFFFFFFFFFF);
-    tcg_gen_andi_i64(t0, xbh, 0x7FF);
-    tcg_gen_shli_i64(t0, t0, 52);
-    tcg_gen_or_i64(xth, xth, t0);
+    tcg_gen_deposit_i64(xth, xah, xbh, 52, 11);
     set_cpu_vsrh(xT(ctx->opcode), xth);
-    tcg_gen_andi_i64(xtl, xal, 0x800FFFFFFFFFFFFF);
-    tcg_gen_andi_i64(t0, xbl, 0x7FF);
-    tcg_gen_shli_i64(t0, t0, 52);
-    tcg_gen_or_i64(xtl, xtl, t0);
+
+    tcg_gen_deposit_i64(xtl, xal, xbl, 52, 11);
     set_cpu_vsrl(xT(ctx->opcode), xtl);
 
-    tcg_temp_free_i64(t0);
     tcg_temp_free_i64(xth);
     tcg_temp_free_i64(xtl);
     tcg_temp_free_i64(xah);
@@ -1853,16 +1812,14 @@
     tcg_gen_movi_i64(t0, 0x0010000000000000);
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
-    tcg_gen_andi_i64(xth, xbh, 0x000FFFFFFFFFFFFF);
-    tcg_gen_or_i64(xth, xth, t0);
+    tcg_gen_deposit_i64(xth, t0, xbh, 0, 52);
     set_cpu_vsrh(xT(ctx->opcode), xth);
 
     tcg_gen_extract_i64(exp, xbl, 52, 11);
     tcg_gen_movi_i64(t0, 0x0010000000000000);
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
-    tcg_gen_andi_i64(xtl, xbl, 0x000FFFFFFFFFFFFF);
-    tcg_gen_or_i64(xtl, xtl, t0);
+    tcg_gen_deposit_i64(xth, t0, xbl, 0, 52);
     set_cpu_vsrl(xT(ctx->opcode), xtl);
 
     tcg_temp_free_i64(t0);
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 58542c0..0bd555e 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8376,6 +8376,7 @@
 #if defined(CONFIG_SOFTMMU)
     pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
     pcc->hash64_opts = &ppc_hash64_opts_basic;
+    pcc->lrg_decr_bits = 32;
 #endif
     pcc->excp_model = POWERPC_EXCP_970;
     pcc->bus_model = PPC_FLAGS_INPUT_970;
@@ -8550,6 +8551,7 @@
 #if defined(CONFIG_SOFTMMU)
     pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
     pcc->hash64_opts = &ppc_hash64_opts_POWER7;
+    pcc->lrg_decr_bits = 32;
 #endif
     pcc->excp_model = POWERPC_EXCP_POWER7;
     pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
@@ -8718,6 +8720,7 @@
 #if defined(CONFIG_SOFTMMU)
     pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
     pcc->hash64_opts = &ppc_hash64_opts_POWER7;
+    pcc->lrg_decr_bits = 32;
 #endif
     pcc->excp_model = POWERPC_EXCP_POWER8;
     pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
@@ -8892,7 +8895,7 @@
                        PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
                        PPC_MEM_SYNC | PPC_MEM_EIEIO |
                        PPC_MEM_TLBSYNC |
-                       PPC_64B | PPC_64BX | PPC_ALTIVEC |
+                       PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC |
                        PPC_SEGMENT_64B | PPC_SLBI |
                        PPC_POPCNTB | PPC_POPCNTWD |
                        PPC_CILDST;
@@ -8904,6 +8907,7 @@
                         PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
                         PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
     pcc->msr_mask = (1ull << MSR_SF) |
+                    (1ull << MSR_SHV) |
                     (1ull << MSR_TM) |
                     (1ull << MSR_VR) |
                     (1ull << MSR_VSX) |
@@ -8926,6 +8930,7 @@
     /* segment page size remain the same */
     pcc->hash64_opts = &ppc_hash64_opts_POWER7;
     pcc->radix_page_info = &POWER9_radix_page_info;
+    pcc->lrg_decr_bits = 56;
 #endif
     pcc->excp_model = POWERPC_EXCP_POWER9;
     pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs
index 22a9a99..68eeee3 100644
--- a/target/s390x/Makefile.objs
+++ b/target/s390x/Makefile.objs
@@ -1,6 +1,7 @@
 obj-y += cpu.o cpu_models.o cpu_features.o gdbstub.o interrupt.o helper.o
 obj-$(CONFIG_TCG) += translate.o cc_helper.o excp_helper.o fpu_helper.o
 obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o crypto_helper.o
+obj-$(CONFIG_TCG) += vec_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o
 obj-$(CONFIG_SOFTMMU) += sigp.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index b71ac51..cb6d770 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -257,6 +257,7 @@
 /* PSW defines */
 #undef PSW_MASK_PER
 #undef PSW_MASK_UNUSED_2
+#undef PSW_MASK_UNUSED_3
 #undef PSW_MASK_DAT
 #undef PSW_MASK_IO
 #undef PSW_MASK_EXT
@@ -276,6 +277,7 @@
 
 #define PSW_MASK_PER            0x4000000000000000ULL
 #define PSW_MASK_UNUSED_2       0x2000000000000000ULL
+#define PSW_MASK_UNUSED_3       0x1000000000000000ULL
 #define PSW_MASK_DAT            0x0400000000000000ULL
 #define PSW_MASK_IO             0x0200000000000000ULL
 #define PSW_MASK_EXT            0x0100000000000000ULL
@@ -323,12 +325,14 @@
 
 /* we'll use some unused PSW positions to store CR flags in tb flags */
 #define FLAG_MASK_AFP           (PSW_MASK_UNUSED_2 >> FLAG_MASK_PSW_SHIFT)
+#define FLAG_MASK_VECTOR        (PSW_MASK_UNUSED_3 >> FLAG_MASK_PSW_SHIFT)
 
 /* Control register 0 bits */
 #define CR0_LOWPROT             0x0000000010000000ULL
 #define CR0_SECONDARY           0x0000000004000000ULL
 #define CR0_EDAT                0x0000000000800000ULL
 #define CR0_AFP                 0x0000000000040000ULL
+#define CR0_VECTOR              0x0000000000020000ULL
 #define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
 #define CR0_EXTERNAL_CALL_SC    0x0000000000002000ULL
 #define CR0_CKC_SC              0x0000000000000800ULL
@@ -373,6 +377,9 @@
     if (env->cregs[0] & CR0_AFP) {
         *flags |= FLAG_MASK_AFP;
     }
+    if (env->cregs[0] & CR0_VECTOR) {
+        *flags |= FLAG_MASK_VECTOR;
+    }
 }
 
 /* PER bits from control register 9 */
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index bb65925..0b494a2 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -123,6 +123,27 @@
 DEF_HELPER_5(msa, i32, env, i32, i32, i32, i32)
 DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
+DEF_HELPER_FLAGS_3(probe_write_access, TCG_CALL_NO_WG, void, env, i64, i64)
+
+/* === Vector Support Instructions === */
+DEF_HELPER_FLAGS_4(vll, TCG_CALL_NO_WG, void, env, ptr, i64, i64)
+DEF_HELPER_FLAGS_4(gvec_vpk16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vpk32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vpk64, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vpks16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vpks32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vpks64, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_5(gvec_vpks_cc16, void, ptr, cptr, cptr, env, i32)
+DEF_HELPER_5(gvec_vpks_cc32, void, ptr, cptr, cptr, env, i32)
+DEF_HELPER_5(gvec_vpks_cc64, void, ptr, cptr, cptr, env, i32)
+DEF_HELPER_FLAGS_4(gvec_vpkls16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vpkls32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vpkls64, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32)
+DEF_HELPER_5(gvec_vpkls_cc16, void, ptr, cptr, cptr, env, i32)
+DEF_HELPER_5(gvec_vpkls_cc32, void, ptr, cptr, cptr, env, i32)
+DEF_HELPER_5(gvec_vpkls_cc64, void, ptr, cptr, cptr, env, i32)
+DEF_HELPER_FLAGS_5(gvec_vperm, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32)
+DEF_HELPER_FLAGS_4(vstl, TCG_CALL_NO_WG, void, env, cptr, i64, i64)
 
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_3(servc, i32, env, i64, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 61b750a..71fa9b8 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -972,6 +972,88 @@
     D(0xb93e, KIMD,    RRE,   MSA,  0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KIMD)
     D(0xb93f, KLMD,    RRE,   MSA,  0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KLMD)
 
+/* === Vector Support Instructions === */
+
+/* VECTOR GATHER ELEMENT */
+    E(0xe713, VGEF,    VRV,   V,   la2, 0, 0, 0, vge, 0, ES_32, IF_VEC)
+    E(0xe712, VGEG,    VRV,   V,   la2, 0, 0, 0, vge, 0, ES_64, IF_VEC)
+/* VECTOR GENERATE BYTE MASK */
+    F(0xe744, VGBM,    VRI_a, V,   0, 0, 0, 0, vgbm, 0, IF_VEC)
+/* VECTOR GENERATE MASK */
+    F(0xe746, VGM,     VRI_b, V,   0, 0, 0, 0, vgm, 0, IF_VEC)
+/* VECTOR LOAD */
+    F(0xe706, VL,      VRX,   V,   la2, 0, 0, 0, vl, 0, IF_VEC)
+    F(0xe756, VLR,     VRR_a, V,   0, 0, 0, 0, vlr, 0, IF_VEC)
+/* VECTOR LOAD AND REPLICATE */
+    F(0xe705, VLREP,   VRX,   V,   la2, 0, 0, 0, vlrep, 0, IF_VEC)
+/* VECTOR LOAD ELEMENT */
+    E(0xe700, VLEB,    VRX,   V,   la2, 0, 0, 0, vle, 0, ES_8, IF_VEC)
+    E(0xe701, VLEH,    VRX,   V,   la2, 0, 0, 0, vle, 0, ES_16, IF_VEC)
+    E(0xe703, VLEF,    VRX,   V,   la2, 0, 0, 0, vle, 0, ES_32, IF_VEC)
+    E(0xe702, VLEG,    VRX,   V,   la2, 0, 0, 0, vle, 0, ES_64, IF_VEC)
+/* VECTOR LOAD ELEMENT IMMEDIATE */
+    E(0xe740, VLEIB,   VRI_a, V,   0, 0, 0, 0, vlei, 0, ES_8, IF_VEC)
+    E(0xe741, VLEIH,   VRI_a, V,   0, 0, 0, 0, vlei, 0, ES_16, IF_VEC)
+    E(0xe743, VLEIF,   VRI_a, V,   0, 0, 0, 0, vlei, 0, ES_32, IF_VEC)
+    E(0xe742, VLEIG,   VRI_a, V,   0, 0, 0, 0, vlei, 0, ES_64, IF_VEC)
+/* VECTOR LOAD GR FROM VR ELEMENT */
+    F(0xe721, VLGV,    VRS_c, V,   la2, 0, r1, 0, vlgv, 0, IF_VEC)
+/* VECTOR LOAD LOGICAL ELEMENT AND ZERO */
+    F(0xe704, VLLEZ,   VRX,   V,   la2, 0, 0, 0, vllez, 0, IF_VEC)
+/* VECTOR LOAD MULTIPLE */
+    F(0xe736, VLM,     VRS_a, V,   la2, 0, 0, 0, vlm, 0, IF_VEC)
+/* VECTOR LOAD TO BLOCK BOUNDARY */
+    F(0xe707, VLBB,    VRX,   V,   la2, 0, 0, 0, vlbb, 0, IF_VEC)
+/* VECTOR LOAD VR ELEMENT FROM GR */
+    F(0xe722, VLVG,    VRS_b, V,   la2, r3, 0, 0, vlvg, 0, IF_VEC)
+/* VECTOR LOAD VR FROM GRS DISJOINT */
+    F(0xe762, VLVGP,   VRR_f, V,   r2, r3, 0, 0, vlvgp, 0, IF_VEC)
+/* VECTOR LOAD WITH LENGTH */
+    F(0xe737, VLL,     VRS_b, V,   la2, r3_32u, 0, 0, vll, 0, IF_VEC)
+/* VECTOR MERGE HIGH */
+    F(0xe761, VMRH,    VRR_c, V,   0, 0, 0, 0, vmr, 0, IF_VEC)
+/* VECTOR MERGE LOW */
+    F(0xe760, VMRL,    VRR_c, V,   0, 0, 0, 0, vmr, 0, IF_VEC)
+/* VECTOR PACK */
+    F(0xe794, VPK,     VRR_c, V,   0, 0, 0, 0, vpk, 0, IF_VEC)
+/* VECTOR PACK SATURATE */
+    F(0xe797, VPKS,    VRR_b, V,   0, 0, 0, 0, vpk, 0, IF_VEC)
+/* VECTOR PACK LOGICAL SATURATE */
+    F(0xe795, VPKLS,   VRR_b, V,   0, 0, 0, 0, vpk, 0, IF_VEC)
+    F(0xe78c, VPERM,   VRR_e, V,   0, 0, 0, 0, vperm, 0, IF_VEC)
+/* VECTOR PERMUTE DOUBLEWORD IMMEDIATE */
+    F(0xe784, VPDI,    VRR_c, V,   0, 0, 0, 0, vpdi, 0, IF_VEC)
+/* VECTOR REPLICATE */
+    F(0xe74d, VREP,    VRI_c, V,   0, 0, 0, 0, vrep, 0, IF_VEC)
+/* VECTOR REPLICATE IMMEDIATE */
+    F(0xe745, VREPI,   VRI_a, V,   0, 0, 0, 0, vrepi, 0, IF_VEC)
+/* VECTOR SCATTER ELEMENT */
+    E(0xe71b, VSCEF,   VRV,   V,   la2, 0, 0, 0, vsce, 0, ES_32, IF_VEC)
+    E(0xe71a, VSCEG,   VRV,   V,   la2, 0, 0, 0, vsce, 0, ES_64, IF_VEC)
+/* VECTOR SELECT */
+    F(0xe78d, VSEL,    VRR_e, V,   0, 0, 0, 0, vsel, 0, IF_VEC)
+/* VECTOR SIGN EXTEND TO DOUBLEWORD */
+    F(0xe75f, VSEG,    VRR_a, V,   0, 0, 0, 0, vseg, 0, IF_VEC)
+/* VECTOR STORE */
+    F(0xe70e, VST,     VRX,   V,   la2, 0, 0, 0, vst, 0, IF_VEC)
+/* VECTOR STORE ELEMENT */
+    E(0xe708, VSTEB,   VRX,   V,   la2, 0, 0, 0, vste, 0, ES_8, IF_VEC)
+    E(0xe709, VSTEH,   VRX,   V,   la2, 0, 0, 0, vste, 0, ES_16, IF_VEC)
+    E(0xe70b, VSTEF,   VRX,   V,   la2, 0, 0, 0, vste, 0, ES_32, IF_VEC)
+    E(0xe70a, VSTEG,   VRX,   V,   la2, 0, 0, 0, vste, 0, ES_64, IF_VEC)
+/* VECTOR STORE MULTIPLE */
+    F(0xe73e, VSTM,    VRS_a, V,   la2, 0, 0, 0, vstm, 0, IF_VEC)
+/* VECTOR STORE WITH LENGTH */
+    F(0xe73f, VSTL,    VRS_b, V,   la2, r3_32u, 0, 0, vstl, 0, IF_VEC)
+/* VECTOR UNPACK HIGH */
+    F(0xe7d7, VUPH,    VRR_a, V,   0, 0, 0, 0, vup, 0, IF_VEC)
+/* VECTOR UNPACK LOGICAL HIGH */
+    F(0xe7d5, VUPLH,   VRR_a, V,   0, 0, 0, 0, vup, 0, IF_VEC)
+/* VECTOR UNPACK LOW */
+    F(0xe7d6, VUPL,    VRR_a, V,   0, 0, 0, 0, vup, 0, IF_VEC)
+/* VECTOR UNPACK LOGICAL LOW */
+    F(0xe7d4, VUPLL,   VRR_a, V,   0, 0, 0, 0, vup, 0, IF_VEC)
+
 #ifndef CONFIG_USER_ONLY
 /* COMPARE AND SWAP AND PURGE */
     E(0xb250, CSP,     RRE,   Z,   r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL, IF_PRIV)
diff --git a/target/s390x/insn-format.def b/target/s390x/insn-format.def
index 4297ff4..6253edb 100644
--- a/target/s390x/insn-format.def
+++ b/target/s390x/insn-format.def
@@ -54,3 +54,28 @@
 F3(SS_f,  BD(1,16,20), L(2,8,8),    BD(2,32,36))
 F2(SSE,   BD(1,16,20), BD(2,32,36))
 F3(SSF,   BD(1,16,20), BD(2,32,36), R(3,8))
+F3(VRI_a, V(1,8),      I(2,16,16),  M(3,32))
+F4(VRI_b, V(1,8),      I(2,16,8),   I(3,24,8),   M(4,32))
+F4(VRI_c, V(1,8),      V(3,12),     I(2,16,16),  M(4,32))
+F5(VRI_d, V(1,8),      V(2,12),     V(3,16),     I(4,24,8),   M(5,32))
+F5(VRI_e, V(1,8),      V(2,12),     I(3,16,12),  M(5,28),     M(4,32))
+F5(VRI_f, V(1,8),      V(2,12),     V(3,16),     M(5,24),     I(4,28,8))
+F5(VRI_g, V(1,8),      V(2,12),     I(4,16,8),   M(5,24),     I(3,28,8))
+F3(VRI_h, V(1,8),      I(2,16,16),  I(3,32,4))
+F4(VRI_i, V(1,8),      R(2,12),     M(4,24),     I(3,28,8))
+F5(VRR_a, V(1,8),      V(2,12),     M(5,24),     M(4,28),     M(3,32))
+F5(VRR_b, V(1,8),      V(2,12),     V(3,16),     M(5,24),     M(4,32))
+F6(VRR_c, V(1,8),      V(2,12),     V(3,16),     M(6,24),     M(5,28),  M(4,32))
+F6(VRR_d, V(1,8),      V(2,12),     V(3,16),     M(5,20),     M(6,24),  V(4,32))
+F6(VRR_e, V(1,8),      V(2,12),     V(3,16),     M(6,20),     M(5,28),  V(4,32))
+F3(VRR_f, V(1,8),      R(2,12),     R(3,16))
+F1(VRR_g, V(1,12))
+F3(VRR_h, V(1,12),     V(2,16),     M(3,24))
+F3(VRR_i, R(1,8),      V(2,12),     M(3,24))
+F4(VRS_a, V(1,8),      V(3,12),     BD(2,16,20), M(4,32))
+F4(VRS_b, V(1,8),      R(3,12),     BD(2,16,20), M(4,32))
+F4(VRS_c, R(1,8),      V(3,12),     BD(2,16,20), M(4,32))
+F3(VRS_d, R(3,12),     BD(2,16,20), V(1,32))
+F4(VRV,   V(1,8),      V(2,12),     BD(2,16,20), M(3,32))
+F3(VRX,   V(1,8),      BXD(2),      M(3,32))
+F3(VSI,   I(3,8,8),    BD(2,16,20), V(1,32))
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index 7baf0e2..3b4855c 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -63,45 +63,7 @@
     PSW             program_new_psw;          /* 0x1d0 */
     PSW             mcck_new_psw;             /* 0x1e0 */
     PSW             io_new_psw;               /* 0x1f0 */
-    PSW             return_psw;               /* 0x200 */
-    uint8_t         irb[64];                  /* 0x210 */
-    uint64_t        sync_enter_timer;         /* 0x250 */
-    uint64_t        async_enter_timer;        /* 0x258 */
-    uint64_t        exit_timer;               /* 0x260 */
-    uint64_t        last_update_timer;        /* 0x268 */
-    uint64_t        user_timer;               /* 0x270 */
-    uint64_t        system_timer;             /* 0x278 */
-    uint64_t        last_update_clock;        /* 0x280 */
-    uint64_t        steal_clock;              /* 0x288 */
-    PSW             return_mcck_psw;          /* 0x290 */
-    uint8_t         pad9[0xc00 - 0x2a0];      /* 0x2a0 */
-    /* System info area */
-    uint64_t        save_area[16];            /* 0xc00 */
-    uint8_t         pad10[0xd40 - 0xc80];     /* 0xc80 */
-    uint64_t        kernel_stack;             /* 0xd40 */
-    uint64_t        thread_info;              /* 0xd48 */
-    uint64_t        async_stack;              /* 0xd50 */
-    uint64_t        kernel_asce;              /* 0xd58 */
-    uint64_t        user_asce;                /* 0xd60 */
-    uint64_t        panic_stack;              /* 0xd68 */
-    uint64_t        user_exec_asce;           /* 0xd70 */
-    uint8_t         pad11[0xdc0 - 0xd78];     /* 0xd78 */
-
-    /* SMP info area: defined by DJB */
-    uint64_t        clock_comparator;         /* 0xdc0 */
-    uint64_t        ext_call_fast;            /* 0xdc8 */
-    uint64_t        percpu_offset;            /* 0xdd0 */
-    uint64_t        current_task;             /* 0xdd8 */
-    uint32_t        softirq_pending;          /* 0xde0 */
-    uint32_t        pad_0x0de4;               /* 0xde4 */
-    uint64_t        int_clock;                /* 0xde8 */
-    uint8_t         pad12[0xe00 - 0xdf0];     /* 0xdf0 */
-
-    /* 0xe00 is used as indicator for dump tools */
-    /* whether the kernel died with panic() or not */
-    uint32_t        panic_magic;              /* 0xe00 */
-
-    uint8_t         pad13[0x11b0 - 0xe04];    /* 0xe04 */
+    uint8_t         pad13[0x11b0 - 0x200];    /* 0x200 */
 
     uint64_t        mcesad;                    /* 0x11B0 */
 
@@ -130,6 +92,7 @@
 
     uint8_t         pad18[0x2000 - 0x1400];    /* 0x1400 */
 } QEMU_PACKED LowCore;
+QEMU_BUILD_BUG_ON(sizeof(LowCore) != 8192);
 #endif /* CONFIG_USER_ONLY */
 
 #define MAX_ILEN 6
@@ -386,6 +349,8 @@
 
 /* mem_helper.c */
 target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
+void probe_write_access(CPUS390XState *env, uint64_t addr, uint64_t len,
+                        uintptr_t ra);
 
 
 /* mmu_helper.c */
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index a506d9e..3f76a8a 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -2623,3 +2623,29 @@
     return convert_unicode(env, r1, r2, m3, GETPC(),
                            decode_utf32, encode_utf16);
 }
+
+void probe_write_access(CPUS390XState *env, uint64_t addr, uint64_t len,
+                        uintptr_t ra)
+{
+#ifdef CONFIG_USER_ONLY
+    if (!h2g_valid(addr) || !h2g_valid(addr + len - 1) ||
+        page_check_range(addr, len, PAGE_WRITE) < 0) {
+        s390_program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO, ra);
+    }
+#else
+    /* test the actual access, not just any access to the page due to LAP */
+    while (len) {
+        const uint64_t pagelen = -(addr | -TARGET_PAGE_MASK);
+        const uint64_t curlen = MIN(pagelen, len);
+
+        probe_write(env, addr, curlen, cpu_mmu_index(env, false), ra);
+        addr = wrap_address(env, addr + curlen);
+        len -= curlen;
+    }
+#endif
+}
+
+void HELPER(probe_write_access)(CPUS390XState *env, uint64_t addr, uint64_t len)
+{
+    probe_write_access(env, addr, len, GETPC());
+}
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 41fb466..0afa8f7 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -34,6 +34,7 @@
 #include "disas/disas.h"
 #include "exec/exec-all.h"
 #include "tcg-op.h"
+#include "tcg-op-gvec.h"
 #include "qemu/log.h"
 #include "qemu/host-utils.h"
 #include "exec/cpu_ldst.h"
@@ -985,6 +986,7 @@
 #define F3(N, X1, X2, X3)             F0(N)
 #define F4(N, X1, X2, X3, X4)         F0(N)
 #define F5(N, X1, X2, X3, X4, X5)     F0(N)
+#define F6(N, X1, X2, X3, X4, X5, X6) F0(N)
 
 typedef enum {
 #include "insn-format.def"
@@ -996,6 +998,7 @@
 #undef F3
 #undef F4
 #undef F5
+#undef F6
 
 /* Define a structure to hold the decoded fields.  We'll store each inside
    an array indexed by an enum.  In order to conserve memory, we'll arrange
@@ -1010,6 +1013,8 @@
     FLD_O_m1,
     FLD_O_m3,
     FLD_O_m4,
+    FLD_O_m5,
+    FLD_O_m6,
     FLD_O_b1,
     FLD_O_b2,
     FLD_O_b4,
@@ -1023,7 +1028,11 @@
     FLD_O_i2,
     FLD_O_i3,
     FLD_O_i4,
-    FLD_O_i5
+    FLD_O_i5,
+    FLD_O_v1,
+    FLD_O_v2,
+    FLD_O_v3,
+    FLD_O_v4,
 };
 
 enum DisasFieldIndexC {
@@ -1031,6 +1040,7 @@
     FLD_C_m1 = 0,
     FLD_C_b1 = 0,
     FLD_C_i1 = 0,
+    FLD_C_v1 = 0,
 
     FLD_C_r2 = 1,
     FLD_C_b2 = 1,
@@ -1039,20 +1049,25 @@
     FLD_C_r3 = 2,
     FLD_C_m3 = 2,
     FLD_C_i3 = 2,
+    FLD_C_v3 = 2,
 
     FLD_C_m4 = 3,
     FLD_C_b4 = 3,
     FLD_C_i4 = 3,
     FLD_C_l1 = 3,
+    FLD_C_v4 = 3,
 
     FLD_C_i5 = 4,
     FLD_C_d1 = 4,
+    FLD_C_m5 = 4,
 
     FLD_C_d2 = 5,
+    FLD_C_m6 = 5,
 
     FLD_C_d4 = 6,
     FLD_C_x2 = 6,
     FLD_C_l2 = 6,
+    FLD_C_v2 = 6,
 
     NUM_C_FIELD = 7
 };
@@ -1097,6 +1112,7 @@
 
 #define R(N, B)       {  B,  4, 0, FLD_C_r##N, FLD_O_r##N }
 #define M(N, B)       {  B,  4, 0, FLD_C_m##N, FLD_O_m##N }
+#define V(N, B)       {  B,  4, 3, FLD_C_v##N, FLD_O_v##N }
 #define BD(N, BB, BD) { BB,  4, 0, FLD_C_b##N, FLD_O_b##N }, \
                       { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
 #define BXD(N)        { 16,  4, 0, FLD_C_b##N, FLD_O_b##N }, \
@@ -1116,6 +1132,7 @@
 #define F3(N, X1, X2, X3)         { { X1, X2, X3 } },
 #define F4(N, X1, X2, X3, X4)     { { X1, X2, X3, X4 } },
 #define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
+#define F6(N, X1, X2, X3, X4, X5, X6)       { { X1, X2, X3, X4, X5, X6 } },
 
 static const DisasFormatInfo format_info[] = {
 #include "insn-format.def"
@@ -1127,8 +1144,10 @@
 #undef F3
 #undef F4
 #undef F5
+#undef F6
 #undef R
 #undef M
+#undef V
 #undef BD
 #undef BXD
 #undef BDL
@@ -1185,6 +1204,7 @@
 #define IF_BFP      0x0008      /* binary floating point instruction */
 #define IF_DFP      0x0010      /* decimal floating point instruction */
 #define IF_PRIV     0x0020      /* privileged instruction */
+#define IF_VEC      0x0040      /* vector instruction */
 
 struct DisasInsn {
     unsigned opc:16;
@@ -5101,6 +5121,8 @@
 }
 #endif
 
+#include "translate_vx.inc.c"
+
 /* ====================================================================== */
 /* The "Cc OUTput" generators.  Given the generated output (and in some cases
    the original inputs), update the various cc data structures in order to
@@ -5772,6 +5794,13 @@
 }
 #define SPEC_in2_r3_sr32 0
 
+static void in2_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r3)]);
+}
+#define SPEC_in2_r3_32u 0
+
 static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
@@ -6119,6 +6148,25 @@
     case 2: /* dl+dh split, signed 20 bit. */
         r = ((int8_t)r << 12) | (r >> 8);
         break;
+    case 3: /* MSB stored in RXB */
+        g_assert(f->size == 4);
+        switch (f->beg) {
+        case 8:
+            r |= extract64(insn, 63 - 36, 1) << 4;
+            break;
+        case 12:
+            r |= extract64(insn, 63 - 37, 1) << 4;
+            break;
+        case 16:
+            r |= extract64(insn, 63 - 38, 1) << 4;
+            break;
+        case 32:
+            r |= extract64(insn, 63 - 39, 1) << 4;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        break;
     default:
         abort();
     }
@@ -6300,11 +6348,22 @@
             if (insn->flags & IF_DFP) {
                 dxc = 3;
             }
+            if (insn->flags & IF_VEC) {
+                dxc = 0xfe;
+            }
             if (dxc) {
                 gen_data_exception(dxc);
                 return DISAS_NORETURN;
             }
         }
+
+        /* if vector instructions not enabled, executing them is forbidden */
+        if (insn->flags & IF_VEC) {
+            if (!((s->base.tb->flags & FLAG_MASK_VECTOR))) {
+                gen_data_exception(0xfe);
+                return DISAS_NORETURN;
+            }
+        }
     }
 
     /* Check for insn specification exceptions.  */
diff --git a/target/s390x/translate_vx.inc.c b/target/s390x/translate_vx.inc.c
new file mode 100644
index 0000000..76f9a5d
--- /dev/null
+++ b/target/s390x/translate_vx.inc.c
@@ -0,0 +1,935 @@
+/*
+ * QEMU TCG support -- s390x vector instruction translation functions
+ *
+ * Copyright (C) 2019 Red Hat Inc
+ *
+ * Authors:
+ *   David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * For most instructions that use the same element size for reads and
+ * writes, we can use real gvec vector expansion, which potantially uses
+ * real host vector instructions. As they only work up to 64 bit elements,
+ * 128 bit elements (vector is a single element) have to be handled
+ * differently. Operations that are too complicated to encode via TCG ops
+ * are handled via gvec ool (out-of-line) handlers.
+ *
+ * As soon as instructions use different element sizes for reads and writes
+ * or access elements "out of their element scope" we expand them manually
+ * in fancy loops, as gvec expansion does not deal with actual element
+ * numbers and does also not support access to other elements.
+ *
+ * 128 bit elements:
+ *  As we only have i32/i64, such elements have to be loaded into two
+ *  i64 values and can then be processed e.g. by tcg_gen_add2_i64.
+ *
+ * Sizes:
+ *  On s390x, the operand size (oprsz) and the maximum size (maxsz) are
+ *  always 16 (128 bit). What gvec code calls "vece", s390x calls "es",
+ *  a.k.a. "element size". These values nicely map to MO_8 ... MO_64. Only
+ *  128 bit element size has to be treated in a special way (MO_64 + 1).
+ *  We will use ES_* instead of MO_* for this reason in this file.
+ *
+ * CC handling:
+ *  As gvec ool-helpers can currently not return values (besides via
+ *  pointers like vectors or cpu_env), whenever we have to set the CC and
+ *  can't conclude the value from the result vector, we will directly
+ *  set it in "env->cc_op" and mark it as static via set_cc_static()".
+ *  Whenever this is done, the helper writes globals (cc_op).
+ */
+
+#define NUM_VEC_ELEMENT_BYTES(es) (1 << (es))
+#define NUM_VEC_ELEMENTS(es) (16 / NUM_VEC_ELEMENT_BYTES(es))
+#define NUM_VEC_ELEMENT_BITS(es) (NUM_VEC_ELEMENT_BYTES(es) * BITS_PER_BYTE)
+
+#define ES_8    MO_8
+#define ES_16   MO_16
+#define ES_32   MO_32
+#define ES_64   MO_64
+#define ES_128  4
+
+static inline bool valid_vec_element(uint8_t enr, TCGMemOp es)
+{
+    return !(enr & ~(NUM_VEC_ELEMENTS(es) - 1));
+}
+
+static void read_vec_element_i64(TCGv_i64 dst, uint8_t reg, uint8_t enr,
+                                 TCGMemOp memop)
+{
+    const int offs = vec_reg_offset(reg, enr, memop & MO_SIZE);
+
+    switch (memop) {
+    case ES_8:
+        tcg_gen_ld8u_i64(dst, cpu_env, offs);
+        break;
+    case ES_16:
+        tcg_gen_ld16u_i64(dst, cpu_env, offs);
+        break;
+    case ES_32:
+        tcg_gen_ld32u_i64(dst, cpu_env, offs);
+        break;
+    case ES_8 | MO_SIGN:
+        tcg_gen_ld8s_i64(dst, cpu_env, offs);
+        break;
+    case ES_16 | MO_SIGN:
+        tcg_gen_ld16s_i64(dst, cpu_env, offs);
+        break;
+    case ES_32 | MO_SIGN:
+        tcg_gen_ld32s_i64(dst, cpu_env, offs);
+        break;
+    case ES_64:
+    case ES_64 | MO_SIGN:
+        tcg_gen_ld_i64(dst, cpu_env, offs);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static void write_vec_element_i64(TCGv_i64 src, int reg, uint8_t enr,
+                                  TCGMemOp memop)
+{
+    const int offs = vec_reg_offset(reg, enr, memop & MO_SIZE);
+
+    switch (memop) {
+    case ES_8:
+        tcg_gen_st8_i64(src, cpu_env, offs);
+        break;
+    case ES_16:
+        tcg_gen_st16_i64(src, cpu_env, offs);
+        break;
+    case ES_32:
+        tcg_gen_st32_i64(src, cpu_env, offs);
+        break;
+    case ES_64:
+        tcg_gen_st_i64(src, cpu_env, offs);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+
+static void get_vec_element_ptr_i64(TCGv_ptr ptr, uint8_t reg, TCGv_i64 enr,
+                                    uint8_t es)
+{
+    TCGv_i64 tmp = tcg_temp_new_i64();
+
+    /* mask off invalid parts from the element nr */
+    tcg_gen_andi_i64(tmp, enr, NUM_VEC_ELEMENTS(es) - 1);
+
+    /* convert it to an element offset relative to cpu_env (vec_reg_offset() */
+    tcg_gen_shli_i64(tmp, tmp, es);
+#ifndef HOST_WORDS_BIGENDIAN
+    tcg_gen_xori_i64(tmp, tmp, 8 - NUM_VEC_ELEMENT_BYTES(es));
+#endif
+    tcg_gen_addi_i64(tmp, tmp, vec_full_reg_offset(reg));
+
+    /* generate the final ptr by adding cpu_env */
+    tcg_gen_trunc_i64_ptr(ptr, tmp);
+    tcg_gen_add_ptr(ptr, ptr, cpu_env);
+
+    tcg_temp_free_i64(tmp);
+}
+
+#define gen_gvec_3_ool(v1, v2, v3, data, fn) \
+    tcg_gen_gvec_3_ool(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \
+                       vec_full_reg_offset(v3), 16, 16, data, fn)
+#define gen_gvec_3_ptr(v1, v2, v3, ptr, data, fn) \
+    tcg_gen_gvec_3_ptr(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \
+                       vec_full_reg_offset(v3), ptr, 16, 16, data, fn)
+#define gen_gvec_4(v1, v2, v3, v4, gen) \
+    tcg_gen_gvec_4(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \
+                   vec_full_reg_offset(v3), vec_full_reg_offset(v4), \
+                   16, 16, gen)
+#define gen_gvec_4_ool(v1, v2, v3, v4, data, fn) \
+    tcg_gen_gvec_4_ool(vec_full_reg_offset(v1), vec_full_reg_offset(v2), \
+                       vec_full_reg_offset(v3), vec_full_reg_offset(v4), \
+                       16, 16, data, fn)
+#define gen_gvec_dup_i64(es, v1, c) \
+    tcg_gen_gvec_dup_i64(es, vec_full_reg_offset(v1), 16, 16, c)
+#define gen_gvec_mov(v1, v2) \
+    tcg_gen_gvec_mov(0, vec_full_reg_offset(v1), vec_full_reg_offset(v2), 16, \
+                     16)
+#define gen_gvec_dup64i(v1, c) \
+    tcg_gen_gvec_dup64i(vec_full_reg_offset(v1), 16, 16, c)
+
+static void gen_gvec_dupi(uint8_t es, uint8_t reg, uint64_t c)
+{
+    switch (es) {
+    case ES_8:
+        tcg_gen_gvec_dup8i(vec_full_reg_offset(reg), 16, 16, c);
+        break;
+    case ES_16:
+        tcg_gen_gvec_dup16i(vec_full_reg_offset(reg), 16, 16, c);
+        break;
+    case ES_32:
+        tcg_gen_gvec_dup32i(vec_full_reg_offset(reg), 16, 16, c);
+        break;
+    case ES_64:
+        gen_gvec_dup64i(reg, c);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static void zero_vec(uint8_t reg)
+{
+    tcg_gen_gvec_dup8i(vec_full_reg_offset(reg), 16, 16, 0);
+}
+
+static DisasJumpType op_vge(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = s->insn->data;
+    const uint8_t enr = get_field(s->fields, m3);
+    TCGv_i64 tmp;
+
+    if (!valid_vec_element(enr, es)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    read_vec_element_i64(tmp, get_field(s->fields, v2), enr, es);
+    tcg_gen_add_i64(o->addr1, o->addr1, tmp);
+    gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 0);
+
+    tcg_gen_qemu_ld_i64(tmp, o->addr1, get_mem_index(s), MO_TE | es);
+    write_vec_element_i64(tmp, get_field(s->fields, v1), enr, es);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static uint64_t generate_byte_mask(uint8_t mask)
+{
+    uint64_t r = 0;
+    int i;
+
+    for (i = 0; i < 8; i++) {
+        if ((mask >> i) & 1) {
+            r |= 0xffull << (i * 8);
+        }
+    }
+    return r;
+}
+
+static DisasJumpType op_vgbm(DisasContext *s, DisasOps *o)
+{
+    const uint16_t i2 = get_field(s->fields, i2);
+
+    if (i2 == (i2 & 0xff) * 0x0101) {
+        /*
+         * Masks for both 64 bit elements of the vector are the same.
+         * Trust tcg to produce a good constant loading.
+         */
+        gen_gvec_dup64i(get_field(s->fields, v1),
+                        generate_byte_mask(i2 & 0xff));
+    } else {
+        TCGv_i64 t = tcg_temp_new_i64();
+
+        tcg_gen_movi_i64(t, generate_byte_mask(i2 >> 8));
+        write_vec_element_i64(t, get_field(s->fields, v1), 0, ES_64);
+        tcg_gen_movi_i64(t, generate_byte_mask(i2));
+        write_vec_element_i64(t, get_field(s->fields, v1), 1, ES_64);
+        tcg_temp_free_i64(t);
+    }
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vgm(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = get_field(s->fields, m4);
+    const uint8_t bits = NUM_VEC_ELEMENT_BITS(es);
+    const uint8_t i2 = get_field(s->fields, i2) & (bits - 1);
+    const uint8_t i3 = get_field(s->fields, i3) & (bits - 1);
+    uint64_t mask = 0;
+    int i;
+
+    if (es > ES_64) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    /* generate the mask - take care of wrapping */
+    for (i = i2; ; i = (i + 1) % bits) {
+        mask |= 1ull << (bits - i - 1);
+        if (i == i3) {
+            break;
+        }
+    }
+
+    gen_gvec_dupi(es, get_field(s->fields, v1), mask);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vl(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    TCGv_i64 t1 = tcg_temp_new_i64();
+
+    tcg_gen_qemu_ld_i64(t0, o->addr1, get_mem_index(s), MO_TEQ);
+    gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
+    tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ);
+    write_vec_element_i64(t0, get_field(s->fields, v1), 0, ES_64);
+    write_vec_element_i64(t1, get_field(s->fields, v1), 1, ES_64);
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlr(DisasContext *s, DisasOps *o)
+{
+    gen_gvec_mov(get_field(s->fields, v1), get_field(s->fields, v2));
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlrep(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = get_field(s->fields, m3);
+    TCGv_i64 tmp;
+
+    if (es > ES_64) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    tcg_gen_qemu_ld_i64(tmp, o->addr1, get_mem_index(s), MO_TE | es);
+    gen_gvec_dup_i64(es, get_field(s->fields, v1), tmp);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vle(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = s->insn->data;
+    const uint8_t enr = get_field(s->fields, m3);
+    TCGv_i64 tmp;
+
+    if (!valid_vec_element(enr, es)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    tcg_gen_qemu_ld_i64(tmp, o->addr1, get_mem_index(s), MO_TE | es);
+    write_vec_element_i64(tmp, get_field(s->fields, v1), enr, es);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlei(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = s->insn->data;
+    const uint8_t enr = get_field(s->fields, m3);
+    TCGv_i64 tmp;
+
+    if (!valid_vec_element(enr, es)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_const_i64((int16_t)get_field(s->fields, i2));
+    write_vec_element_i64(tmp, get_field(s->fields, v1), enr, es);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlgv(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = get_field(s->fields, m4);
+    TCGv_ptr ptr;
+
+    if (es > ES_64) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    /* fast path if we don't need the register content */
+    if (!get_field(s->fields, b2)) {
+        uint8_t enr = get_field(s->fields, d2) & (NUM_VEC_ELEMENTS(es) - 1);
+
+        read_vec_element_i64(o->out, get_field(s->fields, v3), enr, es);
+        return DISAS_NEXT;
+    }
+
+    ptr = tcg_temp_new_ptr();
+    get_vec_element_ptr_i64(ptr, get_field(s->fields, v3), o->addr1, es);
+    switch (es) {
+    case ES_8:
+        tcg_gen_ld8u_i64(o->out, ptr, 0);
+        break;
+    case ES_16:
+        tcg_gen_ld16u_i64(o->out, ptr, 0);
+        break;
+    case ES_32:
+        tcg_gen_ld32u_i64(o->out, ptr, 0);
+        break;
+    case ES_64:
+        tcg_gen_ld_i64(o->out, ptr, 0);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    tcg_temp_free_ptr(ptr);
+
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vllez(DisasContext *s, DisasOps *o)
+{
+    uint8_t es = get_field(s->fields, m3);
+    uint8_t enr;
+    TCGv_i64 t;
+
+    switch (es) {
+    /* rightmost sub-element of leftmost doubleword */
+    case ES_8:
+        enr = 7;
+        break;
+    case ES_16:
+        enr = 3;
+        break;
+    case ES_32:
+        enr = 1;
+        break;
+    case ES_64:
+        enr = 0;
+        break;
+    /* leftmost sub-element of leftmost doubleword */
+    case 6:
+        if (s390_has_feat(S390_FEAT_VECTOR_ENH)) {
+            es = ES_32;
+            enr = 0;
+            break;
+        }
+    default:
+        /* fallthrough */
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    t = tcg_temp_new_i64();
+    tcg_gen_qemu_ld_i64(t, o->addr1, get_mem_index(s), MO_TE | es);
+    zero_vec(get_field(s->fields, v1));
+    write_vec_element_i64(t, get_field(s->fields, v1), enr, es);
+    tcg_temp_free_i64(t);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlm(DisasContext *s, DisasOps *o)
+{
+    const uint8_t v3 = get_field(s->fields, v3);
+    uint8_t v1 = get_field(s->fields, v1);
+    TCGv_i64 t0, t1;
+
+    if (v3 < v1 || (v3 - v1 + 1) > 16) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    /*
+     * Check for possible access exceptions by trying to load the last
+     * element. The first element will be checked first next.
+     */
+    t0 = tcg_temp_new_i64();
+    t1 = tcg_temp_new_i64();
+    gen_addi_and_wrap_i64(s, t0, o->addr1, (v3 - v1) * 16 + 8);
+    tcg_gen_qemu_ld_i64(t0, t0, get_mem_index(s), MO_TEQ);
+
+    for (;; v1++) {
+        tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ);
+        write_vec_element_i64(t1, v1, 0, ES_64);
+        if (v1 == v3) {
+            break;
+        }
+        gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
+        tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ);
+        write_vec_element_i64(t1, v1, 1, ES_64);
+        gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
+    }
+
+    /* Store the last element, loaded first */
+    write_vec_element_i64(t0, v1, 1, ES_64);
+
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlbb(DisasContext *s, DisasOps *o)
+{
+    const int64_t block_size = (1ull << (get_field(s->fields, m3) + 6));
+    const int v1_offs = vec_full_reg_offset(get_field(s->fields, v1));
+    TCGv_ptr a0;
+    TCGv_i64 bytes;
+
+    if (get_field(s->fields, m3) > 6) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    bytes = tcg_temp_new_i64();
+    a0 = tcg_temp_new_ptr();
+    /* calculate the number of bytes until the next block boundary */
+    tcg_gen_ori_i64(bytes, o->addr1, -block_size);
+    tcg_gen_neg_i64(bytes, bytes);
+
+    tcg_gen_addi_ptr(a0, cpu_env, v1_offs);
+    gen_helper_vll(cpu_env, a0, o->addr1, bytes);
+    tcg_temp_free_i64(bytes);
+    tcg_temp_free_ptr(a0);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlvg(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = get_field(s->fields, m4);
+    TCGv_ptr ptr;
+
+    if (es > ES_64) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    /* fast path if we don't need the register content */
+    if (!get_field(s->fields, b2)) {
+        uint8_t enr = get_field(s->fields, d2) & (NUM_VEC_ELEMENTS(es) - 1);
+
+        write_vec_element_i64(o->in2, get_field(s->fields, v1), enr, es);
+        return DISAS_NEXT;
+    }
+
+    ptr = tcg_temp_new_ptr();
+    get_vec_element_ptr_i64(ptr, get_field(s->fields, v1), o->addr1, es);
+    switch (es) {
+    case ES_8:
+        tcg_gen_st8_i64(o->in2, ptr, 0);
+        break;
+    case ES_16:
+        tcg_gen_st16_i64(o->in2, ptr, 0);
+        break;
+    case ES_32:
+        tcg_gen_st32_i64(o->in2, ptr, 0);
+        break;
+    case ES_64:
+        tcg_gen_st_i64(o->in2, ptr, 0);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    tcg_temp_free_ptr(ptr);
+
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vlvgp(DisasContext *s, DisasOps *o)
+{
+    write_vec_element_i64(o->in1, get_field(s->fields, v1), 0, ES_64);
+    write_vec_element_i64(o->in2, get_field(s->fields, v1), 1, ES_64);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vll(DisasContext *s, DisasOps *o)
+{
+    const int v1_offs = vec_full_reg_offset(get_field(s->fields, v1));
+    TCGv_ptr a0 = tcg_temp_new_ptr();
+
+    /* convert highest index into an actual length */
+    tcg_gen_addi_i64(o->in2, o->in2, 1);
+    tcg_gen_addi_ptr(a0, cpu_env, v1_offs);
+    gen_helper_vll(cpu_env, a0, o->addr1, o->in2);
+    tcg_temp_free_ptr(a0);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vmr(DisasContext *s, DisasOps *o)
+{
+    const uint8_t v1 = get_field(s->fields, v1);
+    const uint8_t v2 = get_field(s->fields, v2);
+    const uint8_t v3 = get_field(s->fields, v3);
+    const uint8_t es = get_field(s->fields, m4);
+    int dst_idx, src_idx;
+    TCGv_i64 tmp;
+
+    if (es > ES_64) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    if (s->fields->op2 == 0x61) {
+        /* iterate backwards to avoid overwriting data we might need later */
+        for (dst_idx = NUM_VEC_ELEMENTS(es) - 1; dst_idx >= 0; dst_idx--) {
+            src_idx = dst_idx / 2;
+            if (dst_idx % 2 == 0) {
+                read_vec_element_i64(tmp, v2, src_idx, es);
+            } else {
+                read_vec_element_i64(tmp, v3, src_idx, es);
+            }
+            write_vec_element_i64(tmp, v1, dst_idx, es);
+        }
+    } else {
+        /* iterate forward to avoid overwriting data we might need later */
+        for (dst_idx = 0; dst_idx < NUM_VEC_ELEMENTS(es); dst_idx++) {
+            src_idx = (dst_idx + NUM_VEC_ELEMENTS(es)) / 2;
+            if (dst_idx % 2 == 0) {
+                read_vec_element_i64(tmp, v2, src_idx, es);
+            } else {
+                read_vec_element_i64(tmp, v3, src_idx, es);
+            }
+            write_vec_element_i64(tmp, v1, dst_idx, es);
+        }
+    }
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vpk(DisasContext *s, DisasOps *o)
+{
+    const uint8_t v1 = get_field(s->fields, v1);
+    const uint8_t v2 = get_field(s->fields, v2);
+    const uint8_t v3 = get_field(s->fields, v3);
+    const uint8_t es = get_field(s->fields, m4);
+    static gen_helper_gvec_3 * const vpk[3] = {
+        gen_helper_gvec_vpk16,
+        gen_helper_gvec_vpk32,
+        gen_helper_gvec_vpk64,
+    };
+     static gen_helper_gvec_3 * const vpks[3] = {
+        gen_helper_gvec_vpks16,
+        gen_helper_gvec_vpks32,
+        gen_helper_gvec_vpks64,
+    };
+    static gen_helper_gvec_3_ptr * const vpks_cc[3] = {
+        gen_helper_gvec_vpks_cc16,
+        gen_helper_gvec_vpks_cc32,
+        gen_helper_gvec_vpks_cc64,
+    };
+    static gen_helper_gvec_3 * const vpkls[3] = {
+        gen_helper_gvec_vpkls16,
+        gen_helper_gvec_vpkls32,
+        gen_helper_gvec_vpkls64,
+    };
+    static gen_helper_gvec_3_ptr * const vpkls_cc[3] = {
+        gen_helper_gvec_vpkls_cc16,
+        gen_helper_gvec_vpkls_cc32,
+        gen_helper_gvec_vpkls_cc64,
+    };
+
+    if (es == ES_8 || es > ES_64) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    switch (s->fields->op2) {
+    case 0x97:
+        if (get_field(s->fields, m5) & 0x1) {
+            gen_gvec_3_ptr(v1, v2, v3, cpu_env, 0, vpks_cc[es - 1]);
+            set_cc_static(s);
+        } else {
+            gen_gvec_3_ool(v1, v2, v3, 0, vpks[es - 1]);
+        }
+        break;
+    case 0x95:
+        if (get_field(s->fields, m5) & 0x1) {
+            gen_gvec_3_ptr(v1, v2, v3, cpu_env, 0, vpkls_cc[es - 1]);
+            set_cc_static(s);
+        } else {
+            gen_gvec_3_ool(v1, v2, v3, 0, vpkls[es - 1]);
+        }
+        break;
+    case 0x94:
+        /* If sources and destination dont't overlap -> fast path */
+        if (v1 != v2 && v1 != v3) {
+            const uint8_t src_es = get_field(s->fields, m4);
+            const uint8_t dst_es = src_es - 1;
+            TCGv_i64 tmp = tcg_temp_new_i64();
+            int dst_idx, src_idx;
+
+            for (dst_idx = 0; dst_idx < NUM_VEC_ELEMENTS(dst_es); dst_idx++) {
+                src_idx = dst_idx;
+                if (src_idx < NUM_VEC_ELEMENTS(src_es)) {
+                    read_vec_element_i64(tmp, v2, src_idx, src_es);
+                } else {
+                    src_idx -= NUM_VEC_ELEMENTS(src_es);
+                    read_vec_element_i64(tmp, v3, src_idx, src_es);
+                }
+                write_vec_element_i64(tmp, v1, dst_idx, dst_es);
+            }
+            tcg_temp_free_i64(tmp);
+        } else {
+            gen_gvec_3_ool(v1, v2, v3, 0, vpk[es - 1]);
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vperm(DisasContext *s, DisasOps *o)
+{
+    gen_gvec_4_ool(get_field(s->fields, v1), get_field(s->fields, v2),
+                   get_field(s->fields, v3), get_field(s->fields, v4),
+                   0, gen_helper_gvec_vperm);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vpdi(DisasContext *s, DisasOps *o)
+{
+    const uint8_t i2 = extract32(get_field(s->fields, m4), 2, 1);
+    const uint8_t i3 = extract32(get_field(s->fields, m4), 0, 1);
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    TCGv_i64 t1 = tcg_temp_new_i64();
+
+    read_vec_element_i64(t0, get_field(s->fields, v2), i2, ES_64);
+    read_vec_element_i64(t1, get_field(s->fields, v3), i3, ES_64);
+    write_vec_element_i64(t0, get_field(s->fields, v1), 0, ES_64);
+    write_vec_element_i64(t1, get_field(s->fields, v1), 1, ES_64);
+    tcg_temp_free_i64(t0);
+    tcg_temp_free_i64(t1);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vrep(DisasContext *s, DisasOps *o)
+{
+    const uint8_t enr = get_field(s->fields, i2);
+    const uint8_t es = get_field(s->fields, m4);
+
+    if (es > ES_64 || !valid_vec_element(enr, es)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tcg_gen_gvec_dup_mem(es, vec_full_reg_offset(get_field(s->fields, v1)),
+                         vec_reg_offset(get_field(s->fields, v3), enr, es),
+                         16, 16);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vrepi(DisasContext *s, DisasOps *o)
+{
+    const int64_t data = (int16_t)get_field(s->fields, i2);
+    const uint8_t es = get_field(s->fields, m3);
+
+    if (es > ES_64) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    gen_gvec_dupi(es, get_field(s->fields, v1), data);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vsce(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = s->insn->data;
+    const uint8_t enr = get_field(s->fields, m3);
+    TCGv_i64 tmp;
+
+    if (!valid_vec_element(enr, es)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    read_vec_element_i64(tmp, get_field(s->fields, v2), enr, es);
+    tcg_gen_add_i64(o->addr1, o->addr1, tmp);
+    gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 0);
+
+    read_vec_element_i64(tmp, get_field(s->fields, v1), enr, es);
+    tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TE | es);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static void gen_sel_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c)
+{
+    TCGv_i64 t = tcg_temp_new_i64();
+
+    /* bit in c not set -> copy bit from b */
+    tcg_gen_andc_i64(t, b, c);
+    /* bit in c set -> copy bit from a */
+    tcg_gen_and_i64(d, a, c);
+    /* merge the results */
+    tcg_gen_or_i64(d, d, t);
+    tcg_temp_free_i64(t);
+}
+
+static void gen_sel_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b,
+                        TCGv_vec c)
+{
+    TCGv_vec t = tcg_temp_new_vec_matching(d);
+
+    tcg_gen_andc_vec(vece, t, b, c);
+    tcg_gen_and_vec(vece, d, a, c);
+    tcg_gen_or_vec(vece, d, d, t);
+    tcg_temp_free_vec(t);
+}
+
+static DisasJumpType op_vsel(DisasContext *s, DisasOps *o)
+{
+    static const GVecGen4 gvec_op = {
+        .fni8 = gen_sel_i64,
+        .fniv = gen_sel_vec,
+        .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+    };
+
+    gen_gvec_4(get_field(s->fields, v1), get_field(s->fields, v2),
+               get_field(s->fields, v3), get_field(s->fields, v4), &gvec_op);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vseg(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = get_field(s->fields, m3);
+    int idx1, idx2;
+    TCGv_i64 tmp;
+
+    switch (es) {
+    case ES_8:
+        idx1 = 7;
+        idx2 = 15;
+        break;
+    case ES_16:
+        idx1 = 3;
+        idx2 = 7;
+        break;
+    case ES_32:
+        idx1 = 1;
+        idx2 = 3;
+        break;
+    default:
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    read_vec_element_i64(tmp, get_field(s->fields, v2), idx1, es | MO_SIGN);
+    write_vec_element_i64(tmp, get_field(s->fields, v1), 0, ES_64);
+    read_vec_element_i64(tmp, get_field(s->fields, v2), idx2, es | MO_SIGN);
+    write_vec_element_i64(tmp, get_field(s->fields, v1), 1, ES_64);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vst(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 tmp = tcg_const_i64(16);
+
+    /* Probe write access before actually modifying memory */
+    gen_helper_probe_write_access(cpu_env, o->addr1, tmp);
+
+    read_vec_element_i64(tmp,  get_field(s->fields, v1), 0, ES_64);
+    tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
+    gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
+    read_vec_element_i64(tmp,  get_field(s->fields, v1), 1, ES_64);
+    tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vste(DisasContext *s, DisasOps *o)
+{
+    const uint8_t es = s->insn->data;
+    const uint8_t enr = get_field(s->fields, m3);
+    TCGv_i64 tmp;
+
+    if (!valid_vec_element(enr, es)) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    read_vec_element_i64(tmp, get_field(s->fields, v1), enr, es);
+    tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TE | es);
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vstm(DisasContext *s, DisasOps *o)
+{
+    const uint8_t v3 = get_field(s->fields, v3);
+    uint8_t v1 = get_field(s->fields, v1);
+    TCGv_i64 tmp;
+
+    while (v3 < v1 || (v3 - v1 + 1) > 16) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    /* Probe write access before actually modifying memory */
+    tmp = tcg_const_i64((v3 - v1 + 1) * 16);
+    gen_helper_probe_write_access(cpu_env, o->addr1, tmp);
+
+    for (;; v1++) {
+        read_vec_element_i64(tmp, v1, 0, ES_64);
+        tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
+        gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
+        read_vec_element_i64(tmp, v1, 1, ES_64);
+        tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
+        if (v1 == v3) {
+            break;
+        }
+        gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
+    }
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vstl(DisasContext *s, DisasOps *o)
+{
+    const int v1_offs = vec_full_reg_offset(get_field(s->fields, v1));
+    TCGv_ptr a0 = tcg_temp_new_ptr();
+
+    /* convert highest index into an actual length */
+    tcg_gen_addi_i64(o->in2, o->in2, 1);
+    tcg_gen_addi_ptr(a0, cpu_env, v1_offs);
+    gen_helper_vstl(cpu_env, a0, o->addr1, o->in2);
+    tcg_temp_free_ptr(a0);
+    return DISAS_NEXT;
+}
+
+static DisasJumpType op_vup(DisasContext *s, DisasOps *o)
+{
+    const bool logical = s->fields->op2 == 0xd4 || s->fields->op2 == 0xd5;
+    const uint8_t v1 = get_field(s->fields, v1);
+    const uint8_t v2 = get_field(s->fields, v2);
+    const uint8_t src_es = get_field(s->fields, m3);
+    const uint8_t dst_es = src_es + 1;
+    int dst_idx, src_idx;
+    TCGv_i64 tmp;
+
+    if (src_es > ES_32) {
+        gen_program_exception(s, PGM_SPECIFICATION);
+        return DISAS_NORETURN;
+    }
+
+    tmp = tcg_temp_new_i64();
+    if (s->fields->op2 == 0xd7 || s->fields->op2 == 0xd5) {
+        /* iterate backwards to avoid overwriting data we might need later */
+        for (dst_idx = NUM_VEC_ELEMENTS(dst_es) - 1; dst_idx >= 0; dst_idx--) {
+            src_idx = dst_idx;
+            read_vec_element_i64(tmp, v2, src_idx,
+                                 src_es | (logical ? 0 : MO_SIGN));
+            write_vec_element_i64(tmp, v1, dst_idx, dst_es);
+        }
+
+    } else {
+        /* iterate forward to avoid overwriting data we might need later */
+        for (dst_idx = 0; dst_idx < NUM_VEC_ELEMENTS(dst_es); dst_idx++) {
+            src_idx = dst_idx + NUM_VEC_ELEMENTS(src_es) / 2;
+            read_vec_element_i64(tmp, v2, src_idx,
+                                 src_es | (logical ? 0 : MO_SIGN));
+            write_vec_element_i64(tmp, v1, dst_idx, dst_es);
+        }
+    }
+    tcg_temp_free_i64(tmp);
+    return DISAS_NEXT;
+}
diff --git a/target/s390x/vec.h b/target/s390x/vec.h
new file mode 100644
index 0000000..3313fb4
--- /dev/null
+++ b/target/s390x/vec.h
@@ -0,0 +1,101 @@
+/*
+ * QEMU TCG support -- s390x vector utilitites
+ *
+ * Copyright (C) 2019 Red Hat Inc
+ *
+ * Authors:
+ *   David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef S390X_VEC_H
+#define S390X_VEC_H
+
+typedef union S390Vector {
+    uint64_t doubleword[2];
+    uint32_t word[4];
+    uint16_t halfword[8];
+    uint8_t byte[16];
+} S390Vector;
+
+/*
+ * Each vector is stored as two 64bit host values. So when talking about
+ * byte/halfword/word numbers, we have to take care of proper translation
+ * between element numbers.
+ *
+ * Big Endian (target/possible host)
+ * B:  [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15]
+ * HW: [     0][     1][     2][     3] - [     4][     5][     6][     7]
+ * W:  [             0][             1] - [             2][             3]
+ * DW: [                             0] - [                             1]
+ *
+ * Little Endian (possible host)
+ * B:  [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8]
+ * HW: [     3][     2][     1][     0] - [     7][     6][     5][     4]
+ * W:  [             1][             0] - [             3][             2]
+ * DW: [                             0] - [                             1]
+ */
+#ifndef HOST_WORDS_BIGENDIAN
+#define H1(x)  ((x) ^ 7)
+#define H2(x)  ((x) ^ 3)
+#define H4(x)  ((x) ^ 1)
+#else
+#define H1(x)  (x)
+#define H2(x)  (x)
+#define H4(x)  (x)
+#endif
+
+static inline uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 16);
+    return v->byte[H1(enr)];
+}
+
+static inline uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 8);
+    return v->halfword[H2(enr)];
+}
+
+static inline uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 4);
+    return v->word[H4(enr)];
+}
+
+static inline uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr)
+{
+    g_assert(enr < 2);
+    return v->doubleword[enr];
+}
+
+static inline void s390_vec_write_element8(S390Vector *v, uint8_t enr,
+                                           uint8_t data)
+{
+    g_assert(enr < 16);
+    v->byte[H1(enr)] = data;
+}
+
+static inline void s390_vec_write_element16(S390Vector *v, uint8_t enr,
+                                            uint16_t data)
+{
+    g_assert(enr < 8);
+    v->halfword[H2(enr)] = data;
+}
+
+static inline void s390_vec_write_element32(S390Vector *v, uint8_t enr,
+                                            uint32_t data)
+{
+    g_assert(enr < 4);
+    v->word[H4(enr)] = data;
+}
+
+static inline void s390_vec_write_element64(S390Vector *v, uint8_t enr,
+                                            uint64_t data)
+{
+    g_assert(enr < 2);
+    v->doubleword[enr] = data;
+}
+
+#endif /* S390X_VEC_H */
diff --git a/target/s390x/vec_helper.c b/target/s390x/vec_helper.c
new file mode 100644
index 0000000..bb4c930
--- /dev/null
+++ b/target/s390x/vec_helper.c
@@ -0,0 +1,193 @@
+/*
+ * QEMU TCG support -- s390x vector support instructions
+ *
+ * Copyright (C) 2019 Red Hat Inc
+ *
+ * Authors:
+ *   David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "internal.h"
+#include "vec.h"
+#include "tcg/tcg.h"
+#include "tcg/tcg-gvec-desc.h"
+#include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
+#include "exec/exec-all.h"
+
+void HELPER(vll)(CPUS390XState *env, void *v1, uint64_t addr, uint64_t bytes)
+{
+    if (likely(bytes >= 16)) {
+        uint64_t t0, t1;
+
+        t0 = cpu_ldq_data_ra(env, addr, GETPC());
+        addr = wrap_address(env, addr + 8);
+        t1 = cpu_ldq_data_ra(env, addr, GETPC());
+        s390_vec_write_element64(v1, 0, t0);
+        s390_vec_write_element64(v1, 1, t1);
+    } else {
+        S390Vector tmp = {};
+        int i;
+
+        for (i = 0; i < bytes; i++) {
+            uint8_t byte = cpu_ldub_data_ra(env, addr, GETPC());
+
+            s390_vec_write_element8(&tmp, i, byte);
+            addr = wrap_address(env, addr + 1);
+        }
+        *(S390Vector *)v1 = tmp;
+    }
+}
+
+#define DEF_VPK_HFN(BITS, TBITS)                                               \
+typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *);              \
+static int vpk##BITS##_hfn(S390Vector *v1, const S390Vector *v2,               \
+                           const S390Vector *v3, vpk##BITS##_fn fn)            \
+{                                                                              \
+    int i, saturated = 0;                                                      \
+    S390Vector tmp;                                                            \
+                                                                               \
+    for (i = 0; i < (128 / TBITS); i++) {                                      \
+        uint##BITS##_t src;                                                    \
+                                                                               \
+        if (i < (128 / BITS)) {                                                \
+            src = s390_vec_read_element##BITS(v2, i);                          \
+        } else {                                                               \
+            src = s390_vec_read_element##BITS(v3, i - (128 / BITS));           \
+        }                                                                      \
+        s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated));           \
+    }                                                                          \
+    *v1 = tmp;                                                                 \
+    return saturated;                                                          \
+}
+DEF_VPK_HFN(64, 32)
+DEF_VPK_HFN(32, 16)
+DEF_VPK_HFN(16, 8)
+
+#define DEF_VPK(BITS, TBITS)                                                   \
+static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated)        \
+{                                                                              \
+    return src;                                                                \
+}                                                                              \
+void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3,          \
+                            uint32_t desc)                                     \
+{                                                                              \
+    vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e);                                 \
+}
+DEF_VPK(64, 32)
+DEF_VPK(32, 16)
+DEF_VPK(16, 8)
+
+#define DEF_VPKS(BITS, TBITS)                                                  \
+static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated)       \
+{                                                                              \
+    if ((int##BITS##_t)src > INT##TBITS##_MAX) {                               \
+        (*saturated)++;                                                        \
+        return INT##TBITS##_MAX;                                               \
+    } else if ((int##BITS##_t)src < INT##TBITS##_MIN) {                        \
+        (*saturated)++;                                                        \
+        return INT##TBITS##_MIN;                                               \
+    }                                                                          \
+    return src;                                                                \
+}                                                                              \
+void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3,         \
+                             uint32_t desc)                                    \
+{                                                                              \
+    vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e);                                \
+}                                                                              \
+void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3,      \
+                                CPUS390XState *env, uint32_t desc)             \
+{                                                                              \
+    int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e);                \
+                                                                               \
+    if (saturated == (128 / TBITS)) {                                          \
+        env->cc_op = 3;                                                        \
+    } else if (saturated) {                                                    \
+        env->cc_op = 1;                                                        \
+    } else {                                                                   \
+        env->cc_op = 0;                                                        \
+    }                                                                          \
+}
+DEF_VPKS(64, 32)
+DEF_VPKS(32, 16)
+DEF_VPKS(16, 8)
+
+#define DEF_VPKLS(BITS, TBITS)                                                 \
+static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated)      \
+{                                                                              \
+    if (src > UINT##TBITS##_MAX) {                                             \
+        (*saturated)++;                                                        \
+        return UINT##TBITS##_MAX;                                              \
+    }                                                                          \
+    return src;                                                                \
+}                                                                              \
+void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3,        \
+                              uint32_t desc)                                   \
+{                                                                              \
+    vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e);                               \
+}                                                                              \
+void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3,     \
+                                 CPUS390XState *env, uint32_t desc)            \
+{                                                                              \
+    int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e);               \
+                                                                               \
+    if (saturated == (128 / TBITS)) {                                          \
+        env->cc_op = 3;                                                        \
+    } else if (saturated) {                                                    \
+        env->cc_op = 1;                                                        \
+    } else {                                                                   \
+        env->cc_op = 0;                                                        \
+    }                                                                          \
+}
+DEF_VPKLS(64, 32)
+DEF_VPKLS(32, 16)
+DEF_VPKLS(16, 8)
+
+void HELPER(gvec_vperm)(void *v1, const void *v2, const void *v3,
+                        const void *v4, uint32_t desc)
+{
+    S390Vector tmp;
+    int i;
+
+    for (i = 0; i < 16; i++) {
+        const uint8_t selector = s390_vec_read_element8(v4, i) & 0x1f;
+        uint8_t byte;
+
+        if (selector < 16) {
+            byte = s390_vec_read_element8(v2, selector);
+        } else {
+            byte = s390_vec_read_element8(v3, selector - 16);
+        }
+        s390_vec_write_element8(&tmp, i, byte);
+    }
+    *(S390Vector *)v1 = tmp;
+}
+
+void HELPER(vstl)(CPUS390XState *env, const void *v1, uint64_t addr,
+                  uint64_t bytes)
+{
+    /* Probe write access before actually modifying memory */
+    probe_write_access(env, addr, bytes, GETPC());
+
+    if (likely(bytes >= 16)) {
+        cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 0), GETPC());
+        addr = wrap_address(env, addr + 8);
+        cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 1), GETPC());
+    } else {
+        S390Vector tmp = {};
+        int i;
+
+        for (i = 0; i < bytes; i++) {
+            uint8_t byte = s390_vec_read_element8(v1, i);
+
+            cpu_stb_data_ra(env, addr, byte, GETPC());
+            addr = wrap_address(env, addr + 1);
+        }
+        *(S390Vector *)v1 = tmp;
+    }
+}
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
index 58a48f3..c591748 100644
--- a/tests/boot-serial-test.c
+++ b/tests/boot-serial-test.c
@@ -100,7 +100,9 @@
     { "ppc64", "ppce500", "", "U-Boot" },
     { "ppc64", "40p", "-m 192", "Memory: 192M" },
     { "ppc64", "mac99", "", "PowerPC,970FX" },
-    { "ppc64", "pseries", "", "Open Firmware" },
+    { "ppc64", "pseries",
+      "-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken",
+      "Open Firmware" },
     { "ppc64", "powernv", "-cpu POWER8", "OPAL" },
     { "ppc64", "sam460ex", "-device e1000", "8086  100e" },
     { "i386", "isapc", "-cpu qemu32 -device sga", "SGABIOS" },
diff --git a/tests/pnv-xscom-test.c b/tests/pnv-xscom-test.c
index 974f8da..63d4640 100644
--- a/tests/pnv-xscom-test.c
+++ b/tests/pnv-xscom-test.c
@@ -39,7 +39,6 @@
         .cfam_id    = 0x120d304980000000ull,
         .first_core = 0x1,
     },
-#if 0 /* POWER9 support is not ready yet */
     {
         .chip_type  = PNV_CHIP_POWER9,
         .cpu_model  = "POWER9",
@@ -47,7 +46,6 @@
         .cfam_id    = 0x220d104900008000ull,
         .first_core = 0x0,
     },
-#endif
 };
 
 static uint64_t pnv_xscom_addr(const PnvChip *chip, uint32_t pcba)
diff --git a/tests/prom-env-test.c b/tests/prom-env-test.c
index 4821254..61bc1d1 100644
--- a/tests/prom-env-test.c
+++ b/tests/prom-env-test.c
@@ -44,11 +44,18 @@
 
 static void test_machine(const void *machine)
 {
-    const char *extra_args;
+    const char *extra_args = "";
     QTestState *qts;
 
-    /* The pseries firmware boots much faster without the default devices */
-    extra_args = strcmp(machine, "pseries") == 0 ? "-nodefaults" : "";
+    /*
+     * The pseries firmware boots much faster without the default
+     * devices, it also needs Spectre/Meltdown workarounds disabled to
+     * avoid warnings with TCG
+     */
+    if (strcmp(machine, "pseries") == 0) {
+        extra_args = "-nodefaults"
+            " -machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken";
+    }
 
     qts = qtest_initf("-M %s,accel=tcg %s -prom-env 'use-nvramrc?=true' "
                       "-prom-env 'nvramrc=%x %x l!' ", (const char *)machine,
diff --git a/tests/pxe-test.c b/tests/pxe-test.c
index 73ac1d1..948b0fb 100644
--- a/tests/pxe-test.c
+++ b/tests/pxe-test.c
@@ -25,6 +25,7 @@
 typedef struct testdef {
     const char *machine;    /* Machine type */
     const char *model;      /* NIC device model */
+    const char *extra;      /* Any additional parameters */
 } testdef_t;
 
 static testdef_t x86_tests[] = {
@@ -44,13 +45,16 @@
 };
 
 static testdef_t ppc64_tests[] = {
-    { "pseries", "spapr-vlan" },
-    { "pseries", "virtio-net-pci", },
+    { "pseries", "spapr-vlan",
+      "-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken" },
+    { "pseries", "virtio-net-pci",
+      "-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken" },
     { NULL },
 };
 
 static testdef_t ppc64_tests_slow[] = {
-    { "pseries", "e1000" },
+    { "pseries", "e1000",
+      "-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken" },
     { NULL },
 };
 
@@ -63,13 +67,18 @@
 {
     QTestState *qts;
     char *args;
+    const char *extra = test->extra;
+
+    if (!extra) {
+        extra = "";
+    }
 
     args = g_strdup_printf(
         "-machine %s,accel=kvm:tcg -nodefaults -boot order=n "
         "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s,ipv4=%s,ipv6=%s "
-        "-device %s,bootindex=1,netdev=" NETNAME,
+        "-device %s,bootindex=1,netdev=" NETNAME " %s",
         test->machine, disk, ipv6 ? "off" : "on", ipv6 ? "on" : "off",
-        test->model);
+        test->model, extra);
 
     qts = qtest_init(args);
     boot_sector_test(qts);
diff --git a/tests/tcg/mips/include/test_inputs.h b/tests/tcg/mips/include/test_inputs_128.h
similarity index 96%
rename from tests/tcg/mips/include/test_inputs.h
rename to tests/tcg/mips/include/test_inputs_128.h
index 5406e4e..e4c22dd 100644
--- a/tests/tcg/mips/include/test_inputs.h
+++ b/tests/tcg/mips/include/test_inputs_128.h
@@ -1,8 +1,8 @@
 /*
  *  Header file for pattern and random test inputs
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef TEST_INPUTS_H
-#define TEST_INPUTS_H
+#ifndef TEST_INPUTS_128_H
+#define TEST_INPUTS_128_H
 
 #include <stdint.h>
 
diff --git a/tests/tcg/mips/include/test_utils.h b/tests/tcg/mips/include/test_utils_128.h
similarity index 92%
rename from tests/tcg/mips/include/test_utils.h
rename to tests/tcg/mips/include/test_utils_128.h
index 9672903..cfd7ad3 100644
--- a/tests/tcg/mips/include/test_utils.h
+++ b/tests/tcg/mips/include/test_utils_128.h
@@ -1,8 +1,8 @@
 /*
  *  Header file for test utilities
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef TEST_UTILS_H
-#define TEST_UTILS_H
+#ifndef TEST_UTILS_128_H
+#define TEST_UTILS_128_H
 
 #include <stdio.h>
 #include <stdint.h>
diff --git a/tests/tcg/mips/include/wrappers_msa.h b/tests/tcg/mips/include/wrappers_msa.h
index 9cffd55..254e215 100644
--- a/tests/tcg/mips/include/wrappers_msa.h
+++ b/tests/tcg/mips/include/wrappers_msa.h
@@ -1,8 +1,8 @@
 /*
  *  Header file for wrappers around MSA instructions assembler invocations
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c
index d629431..c73ed24 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLOC.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c
index fad220c..b10fb23 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLOC.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c
index 84cf974..c1dc075 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLOC.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c
index a0ed202..4f7a556 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nloc_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLOC.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c
index 9906eae..c202ba4 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLZC.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c
index 21222e3..1edead2 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLZC.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c
index fbab9c3..b2724c5 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLZC.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c
index dc33366..b547c73 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_nlzc_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NLZC.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c
index f9033c7..5918e7f 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCNT.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c
index 132b4d0..667ca31 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCNT.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c
index f469c09..2951f86 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCNT.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c
index d73eff7..ab43ea9 100644
--- a/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c
+++ b/tests/tcg/mips/user/ase/msa/bit-count/test_msa_pcnt_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCNT.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (PATTERN_INPUTS_COUNT + RANDOM_INPUTS_COUNT)
 
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c
index 9dca167..d2ea54f 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_b.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADD_A.B
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c
index 06a7a50..56b81f9 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_d.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADD_A.D
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c
index 5e59142..fe3c664 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_h.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADD_A.H
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c
index a12f9b9..205117e 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_add_a_w.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADD_A.W
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c
index 61b8e6e..6939e91 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_b.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_A.B
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c
index 8350f8f..af0f3d3 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_d.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_A.D
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c
index 952f9f8..4d3774f 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_h.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_A.H
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c
index d058c64..6f06fdc 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_a_w.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_A.W
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c
index 63e27da..e6cb987 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_b.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_S.B
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c
index 2719cee..2cda5d9 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_d.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_S.D
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c
index 5274096..5539322 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_h.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_S.H
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c
index c3a6292..4f2cc38 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_s_w.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_S.W
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c
index df5d85f..e2d9be3 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_b.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_U.B
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c
index 10c665b..8418c63 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_d.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_U.D
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c
index 1e32f00..8a3b5c5 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_h.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_U.H
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c
index 938d2da..b18bdc3 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_adds_u_w.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDS_U.W
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c
index 5dba386..c86c992 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_b.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDV.B
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c
index 339878c..0f30151 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_d.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDV.D
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c
index 3add379..c6b4cf6 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_h.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDV.H
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c
index 41f86ab..2a565e8 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_addv_w.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction ADDV.W
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c
index a6975e7..7845dc0 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_d.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction HADD_S.D
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c
index 3b95551..ddc2de3 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_h.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction HADD_S.H
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c
index 7a940b2..887cd1c 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_s_w.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction HADD_S.W
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c
index d4cbe44..f0710f1 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_d.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction HADD_U.D
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c
index ca25057..fe55d3e 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_h.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction HADD_U.H
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c
index b302727..babe04d 100644
--- a/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-add/test_msa_hadd_u_w.c
@@ -1,7 +1,7 @@
 /*
  *  Test program for MSA instruction HADD_U.W
  *
- *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  RT-RK Computer Based Systems LLC
  *  Copyright (C) 2019  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_b.c
new file mode 100644
index 0000000..675fb90
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_S.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_S.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd4d4d4d4d4d4d4d4ULL, 0xd4d4d4d4d4d4d4d4ULL, },
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },
+        { 0xe5e5e5e5e5e5e5e5ULL, 0xe5e5e5e5e5e5e5e5ULL, },
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },
+        { 0xf1c61bf1c61bf1c6ULL, 0x1bf1c61bf1c61bf1ULL, },
+        { 0x0d38e30d38e30d38ULL, 0xe30d38e30d38e30dULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },
+        { 0xf1c71cf1c71cf1c7ULL, 0x1cf1c71cf1c71cf1ULL, },
+        { 0x0e38e30e38e30e38ULL, 0xe30e38e30e38e30eULL, },
+        { 0xd4d4d4d4d4d4d4d4ULL, 0xd4d4d4d4d4d4d4d4ULL, },    /*  16  */
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0xc69cf1c69cf1c69cULL, 0xf1c69cf1c69cf1c6ULL, },
+        { 0xe30db8e30db8e30dULL, 0xb8e30db8e30db8e3ULL, },
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },    /*  24  */
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1010101010101010ULL, 0x1010101010101010ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1cf1461cf1461cf1ULL, 0x461cf1461cf1461cULL, },
+        { 0x38630e38630e3863ULL, 0x0e38630e38630e38ULL, },
+        { 0xe5e5e5e5e5e5e5e5ULL, 0xe5e5e5e5e5e5e5e5ULL, },    /*  32  */
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1010101010101010ULL, 0x1010101010101010ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd7ad02d7ad02d7adULL, 0x02d7ad02d7ad02d7ULL, },
+        { 0xf41ec9f41ec9f41eULL, 0xc9f41ec9f41ec9f4ULL, },
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },    /*  40  */
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0be0350be0350be0ULL, 0x350be0350be0350bULL, },
+        { 0x2752fd2752fd2752ULL, 0xfd2752fd2752fd27ULL, },
+        { 0xf1c61bf1c61bf1c6ULL, 0x1bf1c61bf1c61bf1ULL, },    /*  48  */
+        { 0xf1c71cf1c71cf1c7ULL, 0x1cf1c71cf1c71cf1ULL, },
+        { 0xc69cf1c69cf1c69cULL, 0xf1c69cf1c69cf1c6ULL, },
+        { 0x1cf1461cf1461cf1ULL, 0x461cf1461cf1461cULL, },
+        { 0xd7ad02d7ad02d7adULL, 0x02d7ad02d7ad02d7ULL, },
+        { 0x0be0350be0350be0ULL, 0x350be0350be0350bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0d38e30d38e30d38ULL, 0xe30d38e30d38e30dULL, },    /*  56  */
+        { 0x0e38e30e38e30e38ULL, 0xe30e38e30e38e30eULL, },
+        { 0xe30db8e30db8e30dULL, 0xb8e30db8e30db8e3ULL, },
+        { 0x38630e38630e3863ULL, 0x0e38630e38630e38ULL, },
+        { 0xf41ec9f41ec9f41eULL, 0xc9f41ec9f41ec9f4ULL, },
+        { 0x2752fd2752fd2752ULL, 0xfd2752fd2752fd27ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc114f3173afa0e24ULL, 0x2e2fe33c095d0104ULL, },
+        { 0x9a62cabbf018f0e0ULL, 0x391fe82ed453ea10ULL, },
+        { 0xfc5cfe0c43491b47ULL, 0xec2cc91bd35ec9d6ULL, },
+        { 0xc114f3173afa0e24ULL, 0x2e2fe33c095d0104ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd30cd70603b1a9c4ULL, 0x1ce7c00ce0353b08ULL, },
+        { 0x35060b5855e2d42bULL, 0xcff4a1f9df401aceULL, },
+        { 0x9a62cabbf018f0e0ULL, 0x391fe82ed453ea10ULL, },    /*  72  */
+        { 0xd30cd70603b1a9c4ULL, 0x1ce7c00ce0353b08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e54e2fb0b00b6e7ULL, 0xdae4a7ebaa3603daULL, },
+        { 0xfc5cfe0c43491b47ULL, 0xec2cc91bd35ec9d6ULL, },
+        { 0x35060b5855e2d42bULL, 0xcff4a1f9df401aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_d.c
new file mode 100644
index 0000000..e87d414
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_S.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_S.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd555555555555554ULL, 0xd555555555555554ULL, },
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },
+        { 0xe666666666666665ULL, 0xe666666666666665ULL, },
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71c71c71c71ULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e38e38e38eULL, },
+        { 0xd555555555555554ULL, 0xd555555555555554ULL, },    /*  16  */
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0xc71c71c71c71c71cULL, 0xf1c71c71c71c71c6ULL, },
+        { 0xe38e38e38e38e38dULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1111111111111110ULL, 0x1111111111111110ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1c71c71c71c71c71ULL, 0x471c71c71c71c71cULL, },
+        { 0x38e38e38e38e38e3ULL, 0x0e38e38e38e38e38ULL, },
+        { 0xe666666666666665ULL, 0xe666666666666665ULL, },    /*  32  */
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1111111111111110ULL, 0x1111111111111110ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd82d82d82d82d82dULL, 0x02d82d82d82d82d7ULL, },
+        { 0xf49f49f49f49f49eULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },    /*  40  */
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0b60b60b60b60b60ULL, 0x360b60b60b60b60bULL, },
+        { 0x27d27d27d27d27d2ULL, 0xfd27d27d27d27d27ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x1c71c71c71c71c71ULL, },    /*  48  */
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71c71c71c71ULL, },
+        { 0xc71c71c71c71c71cULL, 0xf1c71c71c71c71c6ULL, },
+        { 0x1c71c71c71c71c71ULL, 0x471c71c71c71c71cULL, },
+        { 0xd82d82d82d82d82dULL, 0x02d82d82d82d82d7ULL, },
+        { 0x0b60b60b60b60b60ULL, 0x360b60b60b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },    /*  56  */
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e38e38e38eULL, },
+        { 0xe38e38e38e38e38dULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e3ULL, 0x0e38e38e38e38e38ULL, },
+        { 0xf49f49f49f49f49eULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x27d27d27d27d27d2ULL, 0xfd27d27d27d27d27ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },
+        { 0xfc5cfe8cc34a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f95f411aceULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },    /*  72  */
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e54e27c0c00b6e7ULL, 0xdae527ec2a3703daULL, },
+        { 0xfc5cfe8cc34a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f95f411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_h.c
new file mode 100644
index 0000000..c850543
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_S.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_S.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd554d554d554d554ULL, 0xd554d554d554d554ULL, },
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },
+        { 0xe665e665e665e665ULL, 0xe665e665e665e665ULL, },
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },
+        { 0xf1c61c71c71bf1c6ULL, 0x1c71c71bf1c61c71ULL, },
+        { 0x0e38e38d38e30e38ULL, 0xe38d38e30e38e38dULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },
+        { 0xf1c71c71c71cf1c7ULL, 0x1c71c71cf1c71c71ULL, },
+        { 0x0e38e38e38e30e38ULL, 0xe38e38e30e38e38eULL, },
+        { 0xd554d554d554d554ULL, 0xd554d554d554d554ULL, },    /*  16  */
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0xc71cf1c69c71c71cULL, 0xf1c69c71c71cf1c6ULL, },
+        { 0xe38db8e30e38e38dULL, 0xb8e30e38e38db8e3ULL, },
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },    /*  24  */
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1110111011101110ULL, 0x1110111011101110ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1c71471cf1c61c71ULL, 0x471cf1c61c71471cULL, },
+        { 0x38e30e38638e38e3ULL, 0x0e38638e38e30e38ULL, },
+        { 0xe665e665e665e665ULL, 0xe665e665e665e665ULL, },    /*  32  */
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1110111011101110ULL, 0x1110111011101110ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd82d02d7ad82d82dULL, 0x02d7ad82d82d02d7ULL, },
+        { 0xf49ec9f41f49f49eULL, 0xc9f41f49f49ec9f4ULL, },
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },    /*  40  */
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0b60360be0b50b60ULL, 0x360be0b50b60360bULL, },
+        { 0x27d2fd27527d27d2ULL, 0xfd27527d27d2fd27ULL, },
+        { 0xf1c61c71c71bf1c6ULL, 0x1c71c71bf1c61c71ULL, },    /*  48  */
+        { 0xf1c71c71c71cf1c7ULL, 0x1c71c71cf1c71c71ULL, },
+        { 0xc71cf1c69c71c71cULL, 0xf1c69c71c71cf1c6ULL, },
+        { 0x1c71471cf1c61c71ULL, 0x471cf1c61c71471cULL, },
+        { 0xd82d02d7ad82d82dULL, 0x02d7ad82d82d02d7ULL, },
+        { 0x0b60360be0b50b60ULL, 0x360be0b50b60360bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0e38e38d38e30e38ULL, 0xe38d38e30e38e38dULL, },    /*  56  */
+        { 0x0e38e38e38e30e38ULL, 0xe38e38e30e38e38eULL, },
+        { 0xe38db8e30e38e38dULL, 0xb8e30e38e38db8e3ULL, },
+        { 0x38e30e38638e38e3ULL, 0x0e38638e38e30e38ULL, },
+        { 0xf49ec9f41f49f49eULL, 0xc9f41f49f49ec9f4ULL, },
+        { 0x27d2fd27527d27d2ULL, 0xfd27527d27d2fd27ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc214f3973afa0e24ULL, 0x2f2fe33c09dd0184ULL, },
+        { 0x9a62cabbf118f060ULL, 0x399fe92ed4d3ea90ULL, },
+        { 0xfc5cfe8c43491bc7ULL, 0xecacca1bd3dec956ULL, },
+        { 0xc214f3973afa0e24ULL, 0x2f2fe33c09dd0184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40cd78603b1a944ULL, 0x1d67c10ce0353c08ULL, },
+        { 0x36060b5855e2d4abULL, 0xd074a1f9df401aceULL, },
+        { 0x9a62cabbf118f060ULL, 0x399fe92ed4d3ea90ULL, },    /*  72  */
+        { 0xd40cd78603b1a944ULL, 0x1d67c10ce0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e54e27b0c00b6e7ULL, 0xdae4a7ebaa3603daULL, },
+        { 0xfc5cfe8c43491bc7ULL, 0xecacca1bd3dec956ULL, },
+        { 0x36060b5855e2d4abULL, 0xd074a1f9df401aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_w.c
new file mode 100644
index 0000000..3220574
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_s_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_S.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_S.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd5555554d5555554ULL, 0xd5555554d5555554ULL, },
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },
+        { 0xe6666665e6666665ULL, 0xe6666665e6666665ULL, },
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x1c71c71bf1c71c71ULL, },
+        { 0x0e38e38d38e38e38ULL, 0xe38e38e30e38e38dULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71cf1c71c71ULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e30e38e38eULL, },
+        { 0xd5555554d5555554ULL, 0xd5555554d5555554ULL, },    /*  16  */
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0xc71c71c69c71c71cULL, 0xf1c71c71c71c71c6ULL, },
+        { 0xe38e38e30e38e38dULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1111111011111110ULL, 0x1111111011111110ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1c71c71cf1c71c71ULL, 0x471c71c61c71c71cULL, },
+        { 0x38e38e38638e38e3ULL, 0x0e38e38e38e38e38ULL, },
+        { 0xe6666665e6666665ULL, 0xe6666665e6666665ULL, },    /*  32  */
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1111111011111110ULL, 0x1111111011111110ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xd82d82d7ad82d82dULL, 0x02d82d82d82d82d7ULL, },
+        { 0xf49f49f41f49f49eULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },    /*  40  */
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },
+        { 0xeeeeeeeeeeeeeeeeULL, 0xeeeeeeeeeeeeeeeeULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0b60b60be0b60b60ULL, 0x360b60b50b60b60bULL, },
+        { 0x27d27d27527d27d2ULL, 0xfd27d27d27d27d27ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x1c71c71bf1c71c71ULL, },    /*  48  */
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71cf1c71c71ULL, },
+        { 0xc71c71c69c71c71cULL, 0xf1c71c71c71c71c6ULL, },
+        { 0x1c71c71cf1c71c71ULL, 0x471c71c61c71c71cULL, },
+        { 0xd82d82d7ad82d82dULL, 0x02d82d82d82d82d7ULL, },
+        { 0x0b60b60be0b60b60ULL, 0x360b60b50b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0e38e38d38e38e38ULL, 0xe38e38e30e38e38dULL, },    /*  56  */
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e30e38e38eULL, },
+        { 0xe38e38e30e38e38dULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x38e38e38638e38e3ULL, 0x0e38e38e38e38e38ULL, },
+        { 0xf49f49f41f49f49eULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x27d27d27527d27d2ULL, 0xfd27d27d27d27d27ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc21473973afb0e24ULL, 0x2f2f633c09dd8184ULL, },
+        { 0x9a62cabbf118f060ULL, 0x399fe92ed4d36a90ULL, },
+        { 0xfc5cfe8c434a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0xc21473973afb0e24ULL, 0x2f2f633c09dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578603b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f9df411aceULL, },
+        { 0x9a62cabbf118f060ULL, 0x399fe92ed4d36a90ULL, },    /*  72  */
+        { 0xd40c578603b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e54e27b0c00b6e7ULL, 0xdae527ebaa3703daULL, },
+        { 0xfc5cfe8c434a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f9df411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_S_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_b.c
new file mode 100644
index 0000000..c3f96a6
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_U.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_U.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0xd4d4d4d4d4d4d4d4ULL, 0xd4d4d4d4d4d4d4d4ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe5e5e5e5e5e5e5e5ULL, 0xe5e5e5e5e5e5e5e5ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c69bf1c69bf1c6ULL, 0x9bf1c69bf1c69bf1ULL, },
+        { 0x8db8e38db8e38db8ULL, 0xe38db8e38db8e38dULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },
+        { 0x71471c71471c7147ULL, 0x1c71471c71471c71ULL, },
+        { 0x0e38630e38630e38ULL, 0x630e38630e38630eULL, },
+        { 0xd4d4d4d4d4d4d4d4ULL, 0xd4d4d4d4d4d4d4d4ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6e6e6e6e6e6e6e6eULL, 0x6e6e6e6e6e6e6e6eULL, },
+        { 0xc69c71c69c71c69cULL, 0x71c69c71c69c71c6ULL, },
+        { 0x638db8638db8638dULL, 0xb8638db8638db863ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9090909090909090ULL, 0x9090909090909090ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c71469c71469c71ULL, 0x469c71469c71469cULL, },
+        { 0x38638e38638e3863ULL, 0x8e38638e38638e38ULL, },
+        { 0xe5e5e5e5e5e5e5e5ULL, 0xe5e5e5e5e5e5e5e5ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9090909090909090ULL, 0x9090909090909090ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0xd7ad82d7ad82d7adULL, 0x82d7ad82d7ad82d7ULL, },
+        { 0x749ec9749ec9749eULL, 0xc9749ec9749ec974ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },
+        { 0x6e6e6e6e6e6e6e6eULL, 0x6e6e6e6e6e6e6e6eULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b60358b60358b60ULL, 0x358b60358b60358bULL, },
+        { 0x27527d27527d2752ULL, 0x7d27527d27527d27ULL, },
+        { 0xf1c69bf1c69bf1c6ULL, 0x9bf1c69bf1c69bf1ULL, },    /*  48  */
+        { 0x71471c71471c7147ULL, 0x1c71471c71471c71ULL, },
+        { 0xc69c71c69c71c69cULL, 0x71c69c71c69c71c6ULL, },
+        { 0x9c71469c71469c71ULL, 0x469c71469c71469cULL, },
+        { 0xd7ad82d7ad82d7adULL, 0x82d7ad82d7ad82d7ULL, },
+        { 0x8b60358b60358b60ULL, 0x358b60358b60358bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x8db8e38db8e38db8ULL, 0xe38db8e38db8e38dULL, },    /*  56  */
+        { 0x0e38630e38630e38ULL, 0x630e38630e38630eULL, },
+        { 0x638db8638db8638dULL, 0xb8638db8638db863ULL, },
+        { 0x38638e38638e3863ULL, 0x8e38638e38638e38ULL, },
+        { 0x749ec9749ec9749eULL, 0xc9749ec9749ec974ULL, },
+        { 0x27527d27527d2752ULL, 0x7d27527d27527d27ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc19473973a7a8e24ULL, 0x2eaf633c895d8184ULL, },
+        { 0x9a62cabb70987060ULL, 0x399f68aed4536a10ULL, },
+        { 0x7c5c7e8c43499b47ULL, 0x6cac499bd35ec956ULL, },
+        { 0xc19473973a7a8e24ULL, 0x2eaf633c895d8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd38c578683b1a944ULL, 0x1ce7c08c60353b88ULL, },
+        { 0xb5860b585562d42bULL, 0x4ff4a1795f409aceULL, },
+        { 0x9a62cabb70987060ULL, 0x399f68aed4536a10ULL, },    /*  72  */
+        { 0xd38c578683b1a944ULL, 0x1ce7c08c60353b88ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e54627b8b80b667ULL, 0x5ae4a7ebaa36835aULL, },
+        { 0x7c5c7e8c43499b47ULL, 0x6cac499bd35ec956ULL, },
+        { 0xb5860b585562d42bULL, 0x4ff4a1795f409aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_d.c
new file mode 100644
index 0000000..3a78629
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_U.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_U.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0xd555555555555554ULL, 0xd555555555555554ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe666666666666665ULL, 0xe666666666666665ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x9c71c71c71c71c71ULL, },
+        { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c71ULL, },
+        { 0x0e38e38e38e38e38ULL, 0x638e38e38e38e38eULL, },
+        { 0xd555555555555554ULL, 0xd555555555555554ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6eeeeeeeeeeeeeeeULL, 0x6eeeeeeeeeeeeeeeULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c6ULL, },
+        { 0x638e38e38e38e38dULL, 0xb8e38e38e38e38e3ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9111111111111110ULL, 0x9111111111111110ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c71c71c71c71c71ULL, 0x471c71c71c71c71cULL, },
+        { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e38ULL, },
+        { 0xe666666666666665ULL, 0xe666666666666665ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9111111111111110ULL, 0x9111111111111110ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0xd82d82d82d82d82dULL, 0x82d82d82d82d82d7ULL, },
+        { 0x749f49f49f49f49eULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },
+        { 0x6eeeeeeeeeeeeeeeULL, 0x6eeeeeeeeeeeeeeeULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b60b60b60b60b60ULL, 0x360b60b60b60b60bULL, },
+        { 0x27d27d27d27d27d2ULL, 0x7d27d27d27d27d27ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x9c71c71c71c71c71ULL, },    /*  48  */
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c71ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c6ULL, },
+        { 0x9c71c71c71c71c71ULL, 0x471c71c71c71c71cULL, },
+        { 0xd82d82d82d82d82dULL, 0x82d82d82d82d82d7ULL, },
+        { 0x8b60b60b60b60b60ULL, 0x360b60b60b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38dULL, },    /*  56  */
+        { 0x0e38e38e38e38e38ULL, 0x638e38e38e38e38eULL, },
+        { 0x638e38e38e38e38dULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e38ULL, },
+        { 0x749f49f49f49f49eULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x27d27d27d27d27d2ULL, 0x7d27d27d27d27d27ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },
+        { 0x7c5cfe8cc34a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },    /*  72  */
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e54e27c0c00b6e7ULL, 0x5ae527ec2a3703daULL, },
+        { 0x7c5cfe8cc34a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_h.c
new file mode 100644
index 0000000..b7db518
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_U.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_U.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0xd554d554d554d554ULL, 0xd554d554d554d554ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe665e665e665e665ULL, 0xe665e665e665e665ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c69c71c71bf1c6ULL, 0x9c71c71bf1c69c71ULL, },
+        { 0x8e38e38db8e38e38ULL, 0xe38db8e38e38e38dULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },
+        { 0x71c71c71471c71c7ULL, 0x1c71471c71c71c71ULL, },
+        { 0x0e38638e38e30e38ULL, 0x638e38e30e38638eULL, },
+        { 0xd554d554d554d554ULL, 0xd554d554d554d554ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6eee6eee6eee6eeeULL, 0x6eee6eee6eee6eeeULL, },
+        { 0xc71c71c69c71c71cULL, 0x71c69c71c71c71c6ULL, },
+        { 0x638db8e38e38638dULL, 0xb8e38e38638db8e3ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9110911091109110ULL, 0x9110911091109110ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c71471c71c69c71ULL, 0x471c71c69c71471cULL, },
+        { 0x38e38e38638e38e3ULL, 0x8e38638e38e38e38ULL, },
+        { 0xe665e665e665e665ULL, 0xe665e665e665e665ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9110911091109110ULL, 0x9110911091109110ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0xd82d82d7ad82d82dULL, 0x82d7ad82d82d82d7ULL, },
+        { 0x749ec9f49f49749eULL, 0xc9f49f49749ec9f4ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },
+        { 0x6eee6eee6eee6eeeULL, 0x6eee6eee6eee6eeeULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b60360b60b58b60ULL, 0x360b60b58b60360bULL, },
+        { 0x27d27d27527d27d2ULL, 0x7d27527d27d27d27ULL, },
+        { 0xf1c69c71c71bf1c6ULL, 0x9c71c71bf1c69c71ULL, },    /*  48  */
+        { 0x71c71c71471c71c7ULL, 0x1c71471c71c71c71ULL, },
+        { 0xc71c71c69c71c71cULL, 0x71c69c71c71c71c6ULL, },
+        { 0x9c71471c71c69c71ULL, 0x471c71c69c71471cULL, },
+        { 0xd82d82d7ad82d82dULL, 0x82d7ad82d82d82d7ULL, },
+        { 0x8b60360b60b58b60ULL, 0x360b60b58b60360bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x8e38e38db8e38e38ULL, 0xe38db8e38e38e38dULL, },    /*  56  */
+        { 0x0e38638e38e30e38ULL, 0x638e38e30e38638eULL, },
+        { 0x638db8e38e38638dULL, 0xb8e38e38638db8e3ULL, },
+        { 0x38e38e38638e38e3ULL, 0x8e38638e38e38e38ULL, },
+        { 0x749ec9f49f49749eULL, 0xc9f49f49749ec9f4ULL, },
+        { 0x27d27d27527d27d2ULL, 0x7d27527d27d27d27ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc21473973afa8e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb71187060ULL, 0x399f692ed4d36a90ULL, },
+        { 0x7c5c7e8c43499bc7ULL, 0x6cac4a1bd3dec956ULL, },
+        { 0xc21473973afa8e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578683b1a944ULL, 0x1d67c10c60353c08ULL, },
+        { 0xb6060b5855e2d4abULL, 0x5074a1f95f409aceULL, },
+        { 0x9a62cabb71187060ULL, 0x399f692ed4d36a90ULL, },    /*  72  */
+        { 0xd40c578683b1a944ULL, 0x1d67c10c60353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e54627b8c00b6e7ULL, 0x5ae4a7ebaa3683daULL, },
+        { 0x7c5c7e8c43499bc7ULL, 0x6cac4a1bd3dec956ULL, },
+        { 0xb6060b5855e2d4abULL, 0x5074a1f95f409aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_w.c
new file mode 100644
index 0000000..75e2409
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_ave_u_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVE_U.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVE_U.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0xd5555554d5555554ULL, 0xd5555554d5555554ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe6666665e6666665ULL, 0xe6666665e6666665ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x9c71c71bf1c71c71ULL, },
+        { 0x8e38e38db8e38e38ULL, 0xe38e38e38e38e38dULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },
+        { 0x71c71c71471c71c7ULL, 0x1c71c71c71c71c71ULL, },
+        { 0x0e38e38e38e38e38ULL, 0x638e38e30e38e38eULL, },
+        { 0xd5555554d5555554ULL, 0xd5555554d5555554ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6eeeeeee6eeeeeeeULL, 0x6eeeeeee6eeeeeeeULL, },
+        { 0xc71c71c69c71c71cULL, 0x71c71c71c71c71c6ULL, },
+        { 0x638e38e38e38e38dULL, 0xb8e38e38638e38e3ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9111111091111110ULL, 0x9111111091111110ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c71c71c71c71c71ULL, 0x471c71c69c71c71cULL, },
+        { 0x38e38e38638e38e3ULL, 0x8e38e38e38e38e38ULL, },
+        { 0xe6666665e6666665ULL, 0xe6666665e6666665ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9111111091111110ULL, 0x9111111091111110ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0xd82d82d7ad82d82dULL, 0x82d82d82d82d82d7ULL, },
+        { 0x749f49f49f49f49eULL, 0xc9f49f49749f49f4ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },
+        { 0x6eeeeeee6eeeeeeeULL, 0x6eeeeeee6eeeeeeeULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b60b60b60b60b60ULL, 0x360b60b58b60b60bULL, },
+        { 0x27d27d27527d27d2ULL, 0x7d27d27d27d27d27ULL, },
+        { 0xf1c71c71c71c71c6ULL, 0x9c71c71bf1c71c71ULL, },    /*  48  */
+        { 0x71c71c71471c71c7ULL, 0x1c71c71c71c71c71ULL, },
+        { 0xc71c71c69c71c71cULL, 0x71c71c71c71c71c6ULL, },
+        { 0x9c71c71c71c71c71ULL, 0x471c71c69c71c71cULL, },
+        { 0xd82d82d7ad82d82dULL, 0x82d82d82d82d82d7ULL, },
+        { 0x8b60b60b60b60b60ULL, 0x360b60b58b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x8e38e38db8e38e38ULL, 0xe38e38e38e38e38dULL, },    /*  56  */
+        { 0x0e38e38e38e38e38ULL, 0x638e38e30e38e38eULL, },
+        { 0x638e38e38e38e38dULL, 0xb8e38e38638e38e3ULL, },
+        { 0x38e38e38638e38e3ULL, 0x8e38e38e38e38e38ULL, },
+        { 0x749f49f49f49f49eULL, 0xc9f49f49749f49f4ULL, },
+        { 0x27d27d27527d27d2ULL, 0x7d27d27d27d27d27ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc21473973afb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92ed4d36a90ULL, },
+        { 0x7c5cfe8c434a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xc21473973afb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578683b1a944ULL, 0x1d68410c60353c08ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92ed4d36a90ULL, },    /*  72  */
+        { 0xd40c578683b1a944ULL, 0x1d68410c60353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e54e27b8c00b6e7ULL, 0x5ae527ebaa3703daULL, },
+        { 0x7c5cfe8c434a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVE_U_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_b.c
new file mode 100644
index 0000000..59bba28
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_S.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_S.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },
+        { 0xf1c71cf1c71cf1c7ULL, 0x1cf1c71cf1c71cf1ULL, },
+        { 0x0e38e30e38e30e38ULL, 0xe30e38e30e38e30eULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },
+        { 0x2b2b2b2b2b2b2b2bULL, 0x2b2b2b2b2b2b2b2bULL, },
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },
+        { 0x1a1a1a1a1a1a1a1aULL, 0x1a1a1a1a1a1a1a1aULL, },
+        { 0xf2c71cf2c71cf2c7ULL, 0x1cf2c71cf2c71cf2ULL, },
+        { 0x0e39e40e39e40e39ULL, 0xe40e39e40e39e40eULL, },
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },    /*  16  */
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xefefefefefefefefULL, 0xefefefefefefefefULL, },
+        { 0xc79cf1c79cf1c79cULL, 0xf1c79cf1c79cf1c7ULL, },
+        { 0xe30eb9e30eb9e30eULL, 0xb9e30eb9e30eb9e3ULL, },
+        { 0x2a2a2a2a2a2a2a2aULL, 0x2a2a2a2a2a2a2a2aULL, },    /*  24  */
+        { 0x2b2b2b2b2b2b2b2bULL, 0x2b2b2b2b2b2b2b2bULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1cf2471cf2471cf2ULL, 0x471cf2471cf2471cULL, },
+        { 0x39630e39630e3963ULL, 0x0e39630e39630e39ULL, },
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },    /*  32  */
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd8ad02d8ad02d8adULL, 0x02d8ad02d8ad02d8ULL, },
+        { 0xf41fcaf41fcaf41fULL, 0xcaf41fcaf41fcaf4ULL, },
+        { 0x1919191919191919ULL, 0x1919191919191919ULL, },    /*  40  */
+        { 0x1a1a1a1a1a1a1a1aULL, 0x1a1a1a1a1a1a1a1aULL, },
+        { 0xefefefefefefefefULL, 0xefefefefefefefefULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0be1360be1360be1ULL, 0x360be1360be1360bULL, },
+        { 0x2852fd2852fd2852ULL, 0xfd2852fd2852fd28ULL, },
+        { 0xf1c71cf1c71cf1c7ULL, 0x1cf1c71cf1c71cf1ULL, },    /*  48  */
+        { 0xf2c71cf2c71cf2c7ULL, 0x1cf2c71cf2c71cf2ULL, },
+        { 0xc79cf1c79cf1c79cULL, 0xf1c79cf1c79cf1c7ULL, },
+        { 0x1cf2471cf2471cf2ULL, 0x471cf2471cf2471cULL, },
+        { 0xd8ad02d8ad02d8adULL, 0x02d8ad02d8ad02d8ULL, },
+        { 0x0be1360be1360be1ULL, 0x360be1360be1360bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0e38e30e38e30e38ULL, 0xe30e38e30e38e30eULL, },    /*  56  */
+        { 0x0e39e40e39e40e39ULL, 0xe40e39e40e39e40eULL, },
+        { 0xe30eb9e30eb9e30eULL, 0xb9e30eb9e30eb9e3ULL, },
+        { 0x39630e39630e3963ULL, 0x0e39630e39630e39ULL, },
+        { 0xf41fcaf41fcaf41fULL, 0xcaf41fcaf41fcaf4ULL, },
+        { 0x2852fd2852fd2852ULL, 0xfd2852fd2852fd28ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc214f3183bfb0e24ULL, 0x2f2fe33c0a5d0104ULL, },
+        { 0x9a62cabbf119f0e0ULL, 0x3920e92fd553eb10ULL, },
+        { 0xfc5dfe0d434a1c47ULL, 0xec2cca1bd45fc9d6ULL, },
+        { 0xc214f3183bfb0e24ULL, 0x2f2fe33c0a5d0104ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40cd70703b1a9c4ULL, 0x1de8c10de0353c08ULL, },
+        { 0x36070b5856e2d52bULL, 0xd0f4a2f9df411aceULL, },
+        { 0x9a62cabbf119f0e0ULL, 0x3920e92fd553eb10ULL, },    /*  72  */
+        { 0xd40cd70703b1a9c4ULL, 0x1de8c10de0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e55e2fc0c00b7e7ULL, 0xdae5a7ecaa3704daULL, },
+        { 0xfc5dfe0d434a1c47ULL, 0xec2cca1bd45fc9d6ULL, },
+        { 0x36070b5856e2d52bULL, 0xd0f4a2f9df411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_d.c
new file mode 100644
index 0000000..435c09f
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_S.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_S.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71c71c71c71ULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e38e38e38eULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },
+        { 0x2aaaaaaaaaaaaaabULL, 0x2aaaaaaaaaaaaaabULL, },
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },
+        { 0x199999999999999aULL, 0x199999999999999aULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x0e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },    /*  16  */
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xeeeeeeeeeeeeeeefULL, 0xeeeeeeeeeeeeeeefULL, },
+        { 0xc71c71c71c71c71cULL, 0xf1c71c71c71c71c7ULL, },
+        { 0xe38e38e38e38e38eULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x2aaaaaaaaaaaaaaaULL, 0x2aaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaaaaaaaaaabULL, 0x2aaaaaaaaaaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1c71c71c71c71c72ULL, 0x471c71c71c71c71cULL, },
+        { 0x38e38e38e38e38e3ULL, 0x0e38e38e38e38e39ULL, },
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },    /*  32  */
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd82d82d82d82d82dULL, 0x02d82d82d82d82d8ULL, },
+        { 0xf49f49f49f49f49fULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x1999999999999999ULL, 0x1999999999999999ULL, },    /*  40  */
+        { 0x199999999999999aULL, 0x199999999999999aULL, },
+        { 0xeeeeeeeeeeeeeeefULL, 0xeeeeeeeeeeeeeeefULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0b60b60b60b60b61ULL, 0x360b60b60b60b60bULL, },
+        { 0x27d27d27d27d27d2ULL, 0xfd27d27d27d27d28ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71c71c71c71ULL, },    /*  48  */
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0xc71c71c71c71c71cULL, 0xf1c71c71c71c71c7ULL, },
+        { 0x1c71c71c71c71c72ULL, 0x471c71c71c71c71cULL, },
+        { 0xd82d82d82d82d82dULL, 0x02d82d82d82d82d8ULL, },
+        { 0x0b60b60b60b60b61ULL, 0x360b60b60b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e38e38e38eULL, },    /*  56  */
+        { 0x0e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0xe38e38e38e38e38eULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e3ULL, 0x0e38e38e38e38e39ULL, },
+        { 0xf49f49f49f49f49fULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x27d27d27d27d27d2ULL, 0xfd27d27d27d27d28ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },
+        { 0xfc5cfe8cc34a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f95f411aceULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },    /*  72  */
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e54e27c0c00b6e7ULL, 0xdae527ec2a3703daULL, },
+        { 0xfc5cfe8cc34a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f95f411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_h.c
new file mode 100644
index 0000000..0902e50
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_S.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_S.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },
+        { 0xf1c71c71c71cf1c7ULL, 0x1c71c71cf1c71c71ULL, },
+        { 0x0e38e38e38e30e38ULL, 0xe38e38e30e38e38eULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },
+        { 0x2aab2aab2aab2aabULL, 0x2aab2aab2aab2aabULL, },
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },
+        { 0x199a199a199a199aULL, 0x199a199a199a199aULL, },
+        { 0xf1c71c72c71cf1c7ULL, 0x1c72c71cf1c71c72ULL, },
+        { 0x0e39e38e38e40e39ULL, 0xe38e38e40e39e38eULL, },
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },    /*  16  */
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xeeefeeefeeefeeefULL, 0xeeefeeefeeefeeefULL, },
+        { 0xc71cf1c79c71c71cULL, 0xf1c79c71c71cf1c7ULL, },
+        { 0xe38eb8e30e39e38eULL, 0xb8e30e39e38eb8e3ULL, },
+        { 0x2aaa2aaa2aaa2aaaULL, 0x2aaa2aaa2aaa2aaaULL, },    /*  24  */
+        { 0x2aab2aab2aab2aabULL, 0x2aab2aab2aab2aabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1c72471cf1c71c72ULL, 0x471cf1c71c72471cULL, },
+        { 0x38e30e39638e38e3ULL, 0x0e39638e38e30e39ULL, },
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },    /*  32  */
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd82d02d8ad82d82dULL, 0x02d8ad82d82d02d8ULL, },
+        { 0xf49fc9f41f4af49fULL, 0xc9f41f4af49fc9f4ULL, },
+        { 0x1999199919991999ULL, 0x1999199919991999ULL, },    /*  40  */
+        { 0x199a199a199a199aULL, 0x199a199a199a199aULL, },
+        { 0xeeefeeefeeefeeefULL, 0xeeefeeefeeefeeefULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0b61360be0b60b61ULL, 0x360be0b60b61360bULL, },
+        { 0x27d2fd28527d27d2ULL, 0xfd28527d27d2fd28ULL, },
+        { 0xf1c71c71c71cf1c7ULL, 0x1c71c71cf1c71c71ULL, },    /*  48  */
+        { 0xf1c71c72c71cf1c7ULL, 0x1c72c71cf1c71c72ULL, },
+        { 0xc71cf1c79c71c71cULL, 0xf1c79c71c71cf1c7ULL, },
+        { 0x1c72471cf1c71c72ULL, 0x471cf1c71c72471cULL, },
+        { 0xd82d02d8ad82d82dULL, 0x02d8ad82d82d02d8ULL, },
+        { 0x0b61360be0b60b61ULL, 0x360be0b60b61360bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0e38e38e38e30e38ULL, 0xe38e38e30e38e38eULL, },    /*  56  */
+        { 0x0e39e38e38e40e39ULL, 0xe38e38e40e39e38eULL, },
+        { 0xe38eb8e30e39e38eULL, 0xb8e30e39e38eb8e3ULL, },
+        { 0x38e30e39638e38e3ULL, 0x0e39638e38e30e39ULL, },
+        { 0xf49fc9f41f4af49fULL, 0xc9f41f4af49fc9f4ULL, },
+        { 0x27d2fd28527d27d2ULL, 0xfd28527d27d2fd28ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc214f3983afb0e24ULL, 0x2f2fe33c09dd0184ULL, },
+        { 0x9a62cabbf119f060ULL, 0x39a0e92fd4d3ea90ULL, },
+        { 0xfc5dfe8d434a1bc7ULL, 0xecacca1bd3dfc956ULL, },
+        { 0xc214f3983afb0e24ULL, 0x2f2fe33c09dd0184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40cd78703b1a944ULL, 0x1d68c10de0353c08ULL, },
+        { 0x36070b5855e2d4abULL, 0xd074a1f9df411aceULL, },
+        { 0x9a62cabbf119f060ULL, 0x39a0e92fd4d3ea90ULL, },    /*  72  */
+        { 0xd40cd78703b1a944ULL, 0x1d68c10de0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e55e27c0c00b6e7ULL, 0xdae5a7ecaa3703daULL, },
+        { 0xfc5dfe8d434a1bc7ULL, 0xecacca1bd3dfc956ULL, },
+        { 0x36070b5855e2d4abULL, 0xd074a1f9df411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_w.c
new file mode 100644
index 0000000..31f4553
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_s_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_S.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_S.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71cf1c71c71ULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e30e38e38eULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },
+        { 0x2aaaaaab2aaaaaabULL, 0x2aaaaaab2aaaaaabULL, },
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },
+        { 0x1999999a1999999aULL, 0x1999999a1999999aULL, },
+        { 0xf1c71c72c71c71c7ULL, 0x1c71c71cf1c71c72ULL, },
+        { 0x0e38e38e38e38e39ULL, 0xe38e38e40e38e38eULL, },
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },    /*  16  */
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0xeeeeeeefeeeeeeefULL, 0xeeeeeeefeeeeeeefULL, },
+        { 0xc71c71c79c71c71cULL, 0xf1c71c71c71c71c7ULL, },
+        { 0xe38e38e30e38e38eULL, 0xb8e38e39e38e38e3ULL, },
+        { 0x2aaaaaaa2aaaaaaaULL, 0x2aaaaaaa2aaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaab2aaaaaabULL, 0x2aaaaaab2aaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x1c71c71cf1c71c72ULL, 0x471c71c71c71c71cULL, },
+        { 0x38e38e39638e38e3ULL, 0x0e38e38e38e38e39ULL, },
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },    /*  32  */
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x1111111111111111ULL, 0x1111111111111111ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd82d82d8ad82d82dULL, 0x02d82d82d82d82d8ULL, },
+        { 0xf49f49f41f49f49fULL, 0xc9f49f4af49f49f4ULL, },
+        { 0x1999999919999999ULL, 0x1999999919999999ULL, },    /*  40  */
+        { 0x1999999a1999999aULL, 0x1999999a1999999aULL, },
+        { 0xeeeeeeefeeeeeeefULL, 0xeeeeeeefeeeeeeefULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0b60b60be0b60b61ULL, 0x360b60b60b60b60bULL, },
+        { 0x27d27d28527d27d2ULL, 0xfd27d27d27d27d28ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x1c71c71cf1c71c71ULL, },    /*  48  */
+        { 0xf1c71c72c71c71c7ULL, 0x1c71c71cf1c71c72ULL, },
+        { 0xc71c71c79c71c71cULL, 0xf1c71c71c71c71c7ULL, },
+        { 0x1c71c71cf1c71c72ULL, 0x471c71c71c71c71cULL, },
+        { 0xd82d82d8ad82d82dULL, 0x02d82d82d82d82d8ULL, },
+        { 0x0b60b60be0b60b61ULL, 0x360b60b60b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0e38e38e38e38e38ULL, 0xe38e38e30e38e38eULL, },    /*  56  */
+        { 0x0e38e38e38e38e39ULL, 0xe38e38e40e38e38eULL, },
+        { 0xe38e38e30e38e38eULL, 0xb8e38e39e38e38e3ULL, },
+        { 0x38e38e39638e38e3ULL, 0x0e38e38e38e38e39ULL, },
+        { 0xf49f49f41f49f49fULL, 0xc9f49f4af49f49f4ULL, },
+        { 0x27d27d28527d27d2ULL, 0xfd27d27d27d27d28ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc21473983afb0e24ULL, 0x2f2f633c09dd8184ULL, },
+        { 0x9a62cabbf118f060ULL, 0x399fe92fd4d36a90ULL, },
+        { 0xfc5cfe8d434a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0xc21473983afb0e24ULL, 0x2f2f633c09dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578703b1a944ULL, 0x1d68410de0353c08ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f9df411aceULL, },
+        { 0x9a62cabbf118f060ULL, 0x399fe92fd4d36a90ULL, },    /*  72  */
+        { 0xd40c578703b1a944ULL, 0x1d68410de0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x0e54e27c0c00b6e7ULL, 0xdae527ecaa3703daULL, },
+        { 0xfc5cfe8d434a1bc7ULL, 0xecac4a1bd3df4956ULL, },
+        { 0x36068b5855e2d4abULL, 0xd074a1f9df411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_S_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_b.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_b.c
new file mode 100644
index 0000000..8aa7ec6
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_U.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_U.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c79cf1c79cf1c7ULL, 0x9cf1c79cf1c79cf1ULL, },
+        { 0x8eb8e38eb8e38eb8ULL, 0xe38eb8e38eb8e38eULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2b2b2b2b2b2b2b2bULL, 0x2b2b2b2b2b2b2b2bULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x1a1a1a1a1a1a1a1aULL, 0x1a1a1a1a1a1a1a1aULL, },
+        { 0x72471c72471c7247ULL, 0x1c72471c72471c72ULL, },
+        { 0x0e39640e39640e39ULL, 0x640e39640e39640eULL, },
+        { 0xd5d5d5d5d5d5d5d5ULL, 0xd5d5d5d5d5d5d5d5ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6f6f6f6f6f6f6f6fULL, 0x6f6f6f6f6f6f6f6fULL, },
+        { 0xc79c71c79c71c79cULL, 0x71c79c71c79c71c7ULL, },
+        { 0x638eb9638eb9638eULL, 0xb9638eb9638eb963ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2b2b2b2b2b2b2b2bULL, 0x2b2b2b2b2b2b2b2bULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9191919191919191ULL, 0x9191919191919191ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c72479c72479c72ULL, 0x479c72479c72479cULL, },
+        { 0x39638e39638e3963ULL, 0x8e39638e39638e39ULL, },
+        { 0xe6e6e6e6e6e6e6e6ULL, 0xe6e6e6e6e6e6e6e6ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9191919191919191ULL, 0x9191919191919191ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0xd8ad82d8ad82d8adULL, 0x82d8ad82d8ad82d8ULL, },
+        { 0x749fca749fca749fULL, 0xca749fca749fca74ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x1a1a1a1a1a1a1a1aULL, 0x1a1a1a1a1a1a1a1aULL, },
+        { 0x6f6f6f6f6f6f6f6fULL, 0x6f6f6f6f6f6f6f6fULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b61368b61368b61ULL, 0x368b61368b61368bULL, },
+        { 0x28527d28527d2852ULL, 0x7d28527d28527d28ULL, },
+        { 0xf1c79cf1c79cf1c7ULL, 0x9cf1c79cf1c79cf1ULL, },    /*  48  */
+        { 0x72471c72471c7247ULL, 0x1c72471c72471c72ULL, },
+        { 0xc79c71c79c71c79cULL, 0x71c79c71c79c71c7ULL, },
+        { 0x9c72479c72479c72ULL, 0x479c72479c72479cULL, },
+        { 0xd8ad82d8ad82d8adULL, 0x82d8ad82d8ad82d8ULL, },
+        { 0x8b61368b61368b61ULL, 0x368b61368b61368bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0x8eb8e38eb8e38eb8ULL, 0xe38eb8e38eb8e38eULL, },    /*  56  */
+        { 0x0e39640e39640e39ULL, 0x640e39640e39640eULL, },
+        { 0x638eb9638eb9638eULL, 0xb9638eb9638eb963ULL, },
+        { 0x39638e39638e3963ULL, 0x8e39638e39638e39ULL, },
+        { 0x749fca749fca749fULL, 0xca749fca749fca74ULL, },
+        { 0x28527d28527d2852ULL, 0x7d28527d28527d28ULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc29473983b7b8e24ULL, 0x2faf633c8a5d8184ULL, },
+        { 0x9a62cabb71997060ULL, 0x39a069afd5536b10ULL, },
+        { 0x7c5d7e8d434a9c47ULL, 0x6cac4a9bd45fc956ULL, },
+        { 0xc29473983b7b8e24ULL, 0x2faf633c8a5d8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd48c578783b1a944ULL, 0x1de8c18d60353c88ULL, },
+        { 0xb6870b585662d52bULL, 0x50f4a2795f419aceULL, },
+        { 0x9a62cabb71997060ULL, 0x39a069afd5536b10ULL, },    /*  72  */
+        { 0xd48c578783b1a944ULL, 0x1de8c18d60353c88ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e55627c8c80b767ULL, 0x5ae5a7ecaa37845aULL, },
+        { 0x7c5d7e8d434a9c47ULL, 0x6cac4a9bd45fc956ULL, },
+        { 0xb6870b585662d52bULL, 0x50f4a2795f419aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_d.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_d.c
new file mode 100644
index 0000000..9b16e12
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_U.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_U.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x9c71c71c71c71c71ULL, },
+        { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38eULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2aaaaaaaaaaaaaabULL, 0x2aaaaaaaaaaaaaabULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x199999999999999aULL, 0x199999999999999aULL, },
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x0e38e38e38e38e39ULL, 0x638e38e38e38e38eULL, },
+        { 0xd555555555555555ULL, 0xd555555555555555ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6eeeeeeeeeeeeeefULL, 0x6eeeeeeeeeeeeeefULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x638e38e38e38e38eULL, 0xb8e38e38e38e38e3ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaaaaaaaaaabULL, 0x2aaaaaaaaaaaaaabULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9111111111111111ULL, 0x9111111111111111ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c71c71c71c71c72ULL, 0x471c71c71c71c71cULL, },
+        { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xe666666666666666ULL, 0xe666666666666666ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9111111111111111ULL, 0x9111111111111111ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0xd82d82d82d82d82dULL, 0x82d82d82d82d82d8ULL, },
+        { 0x749f49f49f49f49fULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x199999999999999aULL, 0x199999999999999aULL, },
+        { 0x6eeeeeeeeeeeeeefULL, 0x6eeeeeeeeeeeeeefULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b60b60b60b60b61ULL, 0x360b60b60b60b60bULL, },
+        { 0x27d27d27d27d27d2ULL, 0x7d27d27d27d27d28ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x9c71c71c71c71c71ULL, },    /*  48  */
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x9c71c71c71c71c72ULL, 0x471c71c71c71c71cULL, },
+        { 0xd82d82d82d82d82dULL, 0x82d82d82d82d82d8ULL, },
+        { 0x8b60b60b60b60b61ULL, 0x360b60b60b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0x8e38e38e38e38e38ULL, 0xe38e38e38e38e38eULL, },    /*  56  */
+        { 0x0e38e38e38e38e39ULL, 0x638e38e38e38e38eULL, },
+        { 0x638e38e38e38e38eULL, 0xb8e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x749f49f49f49f49fULL, 0xc9f49f49f49f49f4ULL, },
+        { 0x27d27d27d27d27d2ULL, 0x7d27d27d27d27d28ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },
+        { 0x7c5cfe8cc34a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xc2147397bafb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92f54d36a90ULL, },    /*  72  */
+        { 0xd40c578703b1a944ULL, 0x1d68410ce0353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e54e27c0c00b6e7ULL, 0x5ae527ec2a3703daULL, },
+        { 0x7c5cfe8cc34a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_h.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_h.c
new file mode 100644
index 0000000..191e4ac
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_U.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_U.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c79c71c71cf1c7ULL, 0x9c71c71cf1c79c71ULL, },
+        { 0x8e38e38eb8e38e38ULL, 0xe38eb8e38e38e38eULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2aab2aab2aab2aabULL, 0x2aab2aab2aab2aabULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x199a199a199a199aULL, 0x199a199a199a199aULL, },
+        { 0x71c71c72471c71c7ULL, 0x1c72471c71c71c72ULL, },
+        { 0x0e39638e38e40e39ULL, 0x638e38e40e39638eULL, },
+        { 0xd555d555d555d555ULL, 0xd555d555d555d555ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6eef6eef6eef6eefULL, 0x6eef6eef6eef6eefULL, },
+        { 0xc71c71c79c71c71cULL, 0x71c79c71c71c71c7ULL, },
+        { 0x638eb8e38e39638eULL, 0xb8e38e39638eb8e3ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aab2aab2aab2aabULL, 0x2aab2aab2aab2aabULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9111911191119111ULL, 0x9111911191119111ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c72471c71c79c72ULL, 0x471c71c79c72471cULL, },
+        { 0x38e38e39638e38e3ULL, 0x8e39638e38e38e39ULL, },
+        { 0xe666e666e666e666ULL, 0xe666e666e666e666ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9111911191119111ULL, 0x9111911191119111ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0xd82d82d8ad82d82dULL, 0x82d8ad82d82d82d8ULL, },
+        { 0x749fc9f49f4a749fULL, 0xc9f49f4a749fc9f4ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x199a199a199a199aULL, 0x199a199a199a199aULL, },
+        { 0x6eef6eef6eef6eefULL, 0x6eef6eef6eef6eefULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b61360b60b68b61ULL, 0x360b60b68b61360bULL, },
+        { 0x27d27d28527d27d2ULL, 0x7d28527d27d27d28ULL, },
+        { 0xf1c79c71c71cf1c7ULL, 0x9c71c71cf1c79c71ULL, },    /*  48  */
+        { 0x71c71c72471c71c7ULL, 0x1c72471c71c71c72ULL, },
+        { 0xc71c71c79c71c71cULL, 0x71c79c71c71c71c7ULL, },
+        { 0x9c72471c71c79c72ULL, 0x471c71c79c72471cULL, },
+        { 0xd82d82d8ad82d82dULL, 0x82d8ad82d82d82d8ULL, },
+        { 0x8b61360b60b68b61ULL, 0x360b60b68b61360bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0x8e38e38eb8e38e38ULL, 0xe38eb8e38e38e38eULL, },    /*  56  */
+        { 0x0e39638e38e40e39ULL, 0x638e38e40e39638eULL, },
+        { 0x638eb8e38e39638eULL, 0xb8e38e39638eb8e3ULL, },
+        { 0x38e38e39638e38e3ULL, 0x8e39638e38e38e39ULL, },
+        { 0x749fc9f49f4a749fULL, 0xc9f49f4a749fc9f4ULL, },
+        { 0x27d27d28527d27d2ULL, 0x7d28527d27d27d28ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc21473983afb8e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb71197060ULL, 0x39a0692fd4d36a90ULL, },
+        { 0x7c5d7e8d434a9bc7ULL, 0x6cac4a1bd3dfc956ULL, },
+        { 0xc21473983afb8e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578783b1a944ULL, 0x1d68c10d60353c08ULL, },
+        { 0xb6070b5855e2d4abULL, 0x5074a1f95f419aceULL, },
+        { 0x9a62cabb71197060ULL, 0x39a0692fd4d36a90ULL, },    /*  72  */
+        { 0xd40c578783b1a944ULL, 0x1d68c10d60353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e55627c8c00b6e7ULL, 0x5ae5a7ecaa3783daULL, },
+        { 0x7c5d7e8d434a9bc7ULL, 0x6cac4a1bd3dfc956ULL, },
+        { 0xb6070b5855e2d4abULL, 0x5074a1f95f419aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_w.c b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_w.c
new file mode 100644
index 0000000..e0d6b17
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-average/test_msa_aver_u_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction AVER_U.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "AVER_U.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x9c71c71cf1c71c71ULL, },
+        { 0x8e38e38eb8e38e38ULL, 0xe38e38e38e38e38eULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x2aaaaaab2aaaaaabULL, 0x2aaaaaab2aaaaaabULL, },
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0x1999999a1999999aULL, 0x1999999a1999999aULL, },
+        { 0x71c71c72471c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x0e38e38e38e38e39ULL, 0x638e38e40e38e38eULL, },
+        { 0xd5555555d5555555ULL, 0xd5555555d5555555ULL, },    /*  16  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x6eeeeeef6eeeeeefULL, 0x6eeeeeef6eeeeeefULL, },
+        { 0xc71c71c79c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x638e38e38e38e38eULL, 0xb8e38e39638e38e3ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },    /*  24  */
+        { 0x2aaaaaab2aaaaaabULL, 0x2aaaaaab2aaaaaabULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x9111111191111111ULL, 0x9111111191111111ULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x9c71c71c71c71c72ULL, 0x471c71c79c71c71cULL, },
+        { 0x38e38e39638e38e3ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xe6666666e6666666ULL, 0xe6666666e6666666ULL, },    /*  32  */
+        { 0x6666666666666666ULL, 0x6666666666666666ULL, },
+        { 0xbbbbbbbbbbbbbbbbULL, 0xbbbbbbbbbbbbbbbbULL, },
+        { 0x9111111191111111ULL, 0x9111111191111111ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0xd82d82d8ad82d82dULL, 0x82d82d82d82d82d8ULL, },
+        { 0x749f49f49f49f49fULL, 0xc9f49f4a749f49f4ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },    /*  40  */
+        { 0x1999999a1999999aULL, 0x1999999a1999999aULL, },
+        { 0x6eeeeeef6eeeeeefULL, 0x6eeeeeef6eeeeeefULL, },
+        { 0x4444444444444444ULL, 0x4444444444444444ULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8b60b60b60b60b61ULL, 0x360b60b68b60b60bULL, },
+        { 0x27d27d28527d27d2ULL, 0x7d27d27d27d27d28ULL, },
+        { 0xf1c71c71c71c71c7ULL, 0x9c71c71cf1c71c71ULL, },    /*  48  */
+        { 0x71c71c72471c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0xc71c71c79c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x9c71c71c71c71c72ULL, 0x471c71c79c71c71cULL, },
+        { 0xd82d82d8ad82d82dULL, 0x82d82d82d82d82d8ULL, },
+        { 0x8b60b60b60b60b61ULL, 0x360b60b68b60b60bULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0x8e38e38eb8e38e38ULL, 0xe38e38e38e38e38eULL, },    /*  56  */
+        { 0x0e38e38e38e38e39ULL, 0x638e38e40e38e38eULL, },
+        { 0x638e38e38e38e38eULL, 0xb8e38e39638e38e3ULL, },
+        { 0x38e38e39638e38e3ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x749f49f49f49f49fULL, 0xc9f49f4a749f49f4ULL, },
+        { 0x27d27d28527d27d2ULL, 0x7d27d27d27d27d28ULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x886ae6cc28625540ULL, 0x4b670b5efe7bb00cULL, },    /*  64  */
+        { 0xc21473983afb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92fd4d36a90ULL, },
+        { 0x7c5cfe8d434a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xc21473983afb0e24ULL, 0x2f2f633c89dd8184ULL, },
+        { 0xfbbe00634d93c708ULL, 0x12f7bb1a153f52fcULL, },
+        { 0xd40c578783b1a944ULL, 0x1d68410d60353c08ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+        { 0x9a62cabb7118f060ULL, 0x399fe92fd4d36a90ULL, },    /*  72  */
+        { 0xd40c578783b1a944ULL, 0x1d68410d60353c08ULL, },
+        { 0xac5aaeaab9cf8b80ULL, 0x27d8c6ffab2b2514ULL, },
+        { 0x8e54e27c8c00b6e7ULL, 0x5ae527ecaa3703daULL, },
+        { 0x7c5cfe8d434a1bc7ULL, 0x6cac4a1bd3df4956ULL, },
+        { 0xb6068b5855e2d4abULL, 0x5074a1f95f411aceULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_AVER_U_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c
index b47b42e..bb884ee 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CEQ.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c
index e169bdc..ef13f7d 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CEQ.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c
index 9f03cb0..1c43d40 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CEQ.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c
index a927d96..1297d41 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_ceq_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CEQ.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c
index 1c1cb3b..afd5f635 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_S.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c
index b51907c..04d58d1 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_S.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c
index 20ebbfb..ed1a1e2 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_S.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c
index 4a78cce..ea4dc1a 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_s_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_S.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c
index 9990a5b..6e4fdd8 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_U.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c
index cde86d8..b2b2f55 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_U.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c
index 70e4b48..b226775 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_U.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c
index f38feac..00e930c 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_cle_u_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLE_U.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c
index b81b569..4a52ebe 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_S.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c
index 393457a..cc945cd 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_S.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c
index 56860d7..b228dfe 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_S.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c
index 346b293..6cb192a 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_s_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_S.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c
index be79646..b6189d6 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_U.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c
index afbe490..4f547d8 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_U.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c
index 126597a..9fcd81c 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_U.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c
index b405929..8f648af 100644
--- a/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-compare/test_msa_clt_u_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction CLT_U.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_b.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_b.c
new file mode 100644
index 0000000..38e3670
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_S.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_S.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*   0  */
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },    /*  16  */
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0200ff0200ff0200ULL, 0xff0200ff0200ff02ULL, },
+        { 0xfd0001fd0001fd00ULL, 0x01fd0001fd0001fdULL, },
+        { 0xababababababababULL, 0xababababababababULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0xfe0001fe0001fe00ULL, 0x01fe0001fe0001feULL, },
+        { 0x0300ff0300ff0300ULL, 0xff0300ff0300ff03ULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },    /*  32  */
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0100000100000100ULL, 0x0001000001000001ULL, },
+        { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0xff0000ff0000ff00ULL, 0x00ff0000ff0000ffULL, },
+        { 0x0100000100000100ULL, 0x0001000001000001ULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },    /*  48  */
+        { 0x0101ff0101ff0101ULL, 0xff0101ff0101ff01ULL, },
+        { 0x0001000001000001ULL, 0x0000010000010000ULL, },
+        { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+        { 0x0002ff0002ff0002ULL, 0xff0002ff0002ff00ULL, },
+        { 0x00fe0100fe0100feULL, 0x0100fe0100fe0100ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },    /*  56  */
+        { 0xffff01ffff01ffffULL, 0x01ffff01ffff01ffULL, },
+        { 0x00ff0000ff0000ffULL, 0x0000ff0000ff0000ULL, },
+        { 0x0001000001000001ULL, 0x0000010000010000ULL, },
+        { 0x00fe0100fe0100feULL, 0x0100fe0100fe0100ULL, },
+        { 0x0002ff0002ff0002ULL, 0xff0002ff0002ff00ULL, },
+        { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*  64  */
+        { 0x18ff01000000ff08ULL, 0x04f50003000100fdULL, },
+        { 0x0101000000fe0000ULL, 0x01fe00a20002fe00ULL, },
+        { 0xff01ff000002fe00ULL, 0x00fa00fe00010200ULL, },
+        { 0x000000ff01ff0000ULL, 0x0000fa00f600ff00ULL, },
+        { 0x0101ff0101010101ULL, 0x0101010101010101ULL, },
+        { 0x000000ffff020000ULL, 0x000001e600010200ULL, },
+        { 0x0000000100fe0100ULL, 0x000000000000fe00ULL, },
+        { 0x00000301ff00fffeULL, 0x0000fb002a000001ULL, },    /*  72  */
+        { 0x10ff0100000002f0ULL, 0x02040000fc0000fbULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0001fdff00ff03ffULL, 0x000200000000ff00ULL, },
+        { 0x000000ff02000001ULL, 0xff00f6002b0000f8ULL, },
+        { 0xeaffff0001000009ULL, 0xfa0101fffc010018ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_d.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_d.c
new file mode 100644
index 0000000..d92b695
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_S.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_S.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*   0  */
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },    /*  16  */
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000003ULL, 0xffffffffffffffffULL, },
+        { 0xfffffffffffffffdULL, 0x0000000000000001ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xfffffffffffffffeULL, 0x0000000000000001ULL, },
+        { 0x0000000000000003ULL, 0xffffffffffffffffULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },    /*  32  */
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },    /*  48  */
+        { 0x0000000000000001ULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },    /*  56  */
+        { 0xffffffffffffffffULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*  64  */
+        { 0x000000000000001cULL, 0x0000000000000003ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  72  */
+        { 0x0000000000000013ULL, 0x0000000000000002ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+        { 0xffffffffffffffe6ULL, 0xfffffffffffffffaULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_h.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_h.c
new file mode 100644
index 0000000..f191b98
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_S.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_S.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*   0  */
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },    /*  16  */
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0003ffff00000003ULL, 0xffff00000003ffffULL, },
+        { 0xfffd00010000fffdULL, 0x00010000fffd0001ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xfffe00010000fffeULL, 0x00010000fffe0001ULL, },
+        { 0x0003ffff00000003ULL, 0xffff00000003ffffULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },    /*  32  */
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0001000000000001ULL, 0x0000000000010000ULL, },
+        { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xffff00000000ffffULL, 0x00000000ffff0000ULL, },
+        { 0x0001000000000001ULL, 0x0000000000010000ULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },    /*  48  */
+        { 0x0001ffff00010001ULL, 0xffff00010001ffffULL, },
+        { 0x0000000000010000ULL, 0x0000000100000000ULL, },
+        { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+        { 0x0000ffff00020000ULL, 0xffff00020000ffffULL, },
+        { 0x00000001fffe0000ULL, 0x0001fffe00000001ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },    /*  56  */
+        { 0xffff0001ffffffffULL, 0x0001ffffffff0001ULL, },
+        { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+        { 0x0000000000010000ULL, 0x0000000100000000ULL, },
+        { 0x00000001fffe0000ULL, 0x0001fffe00000001ULL, },
+        { 0x0000ffff00020000ULL, 0xffff00020000ffffULL, },
+        { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*  64  */
+        { 0x001cffbf0000ffffULL, 0x0003000000000000ULL, },
+        { 0x0001000000000000ULL, 0x000100000000fffeULL, },
+        { 0xffffffff0000fffeULL, 0x0000000000000002ULL, },
+        { 0x0000000000010000ULL, 0x0000fffafff3ffffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x00000000ffff0000ULL, 0x0000000100000002ULL, },
+        { 0x0000000000000001ULL, 0x000000000000fffeULL, },
+        { 0x00000003ffffffffULL, 0x0000fffb00370000ULL, },    /*  72  */
+        { 0x0013ff2e00000002ULL, 0x00020000fffd0000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0000fffd00000003ULL, 0x000000000000ffffULL, },
+        { 0x0000000000020000ULL, 0xfffffff600390000ULL, },
+        { 0xffe6003900010000ULL, 0xfffa0001fffc0000ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_w.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_w.c
new file mode 100644
index 0000000..0baaff1
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_s_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_S.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_S.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*   0  */
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },    /*  16  */
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000200000000ULL, 0xffffffff00000002ULL, },
+        { 0xfffffffd00000000ULL, 0x00000001fffffffdULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xfffffffe00000000ULL, 0x00000001fffffffeULL, },
+        { 0x0000000300000000ULL, 0xffffffff00000003ULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },    /*  32  */
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000000ULL, 0x0000000000000001ULL, },
+        { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },
+        { 0x0000000100000000ULL, 0x0000000000000001ULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },    /*  48  */
+        { 0x0000000100000001ULL, 0xffffffff00000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+        { 0x0000000000000002ULL, 0xffffffff00000000ULL, },
+        { 0x00000000fffffffeULL, 0x0000000100000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },    /*  56  */
+        { 0xffffffffffffffffULL, 0x00000001ffffffffULL, },
+        { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x00000000fffffffeULL, 0x0000000100000000ULL, },
+        { 0x0000000000000002ULL, 0xffffffff00000000ULL, },
+        { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*  64  */
+        { 0x0000001c00000000ULL, 0x0000000300000000ULL, },
+        { 0x0000000100000000ULL, 0x0000000100000000ULL, },
+        { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x00000000fffffff2ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x00000000ffffffffULL, 0x0000000000000037ULL, },    /*  72  */
+        { 0x0000001300000000ULL, 0x00000002fffffffdULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000002ULL, 0xffffffff00000039ULL, },
+        { 0xffffffe600000001ULL, 0xfffffffafffffffcULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_S_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_b.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_b.c
new file mode 100644
index 0000000..770544a
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_U.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_U.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0303030303030303ULL, 0x0303030303030303ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0505050505050505ULL, 0x0505050505050505ULL, },
+        { 0x0101040101040101ULL, 0x0401010401010401ULL, },
+        { 0x0902010902010902ULL, 0x0109020109020109ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0202020202020202ULL, 0x0202020202020202ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0303030303030303ULL, 0x0303030303030303ULL, },
+        { 0x0001030001030001ULL, 0x0300010300010300ULL, },
+        { 0x0601000601000601ULL, 0x0006010006010006ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0000010000010000ULL, 0x0100000100000100ULL, },
+        { 0x0300000300000300ULL, 0x0003000003000003ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0202020202020202ULL, 0x0202020202020202ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0404040404040404ULL, 0x0404040404040404ULL, },
+        { 0x0001030001030001ULL, 0x0300010300010300ULL, },
+        { 0x0701010701010701ULL, 0x0107010107010107ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0100000100000100ULL, 0x0001000001000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0100000100000100ULL, 0x0001000001000001ULL, },
+        { 0x0201000201000201ULL, 0x0002010002010002ULL, },
+        { 0x0100000100000100ULL, 0x0001000001000001ULL, },
+        { 0x0402010402010402ULL, 0x0104020104020104ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0801000801000801ULL, 0x0008010008010008ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000010000010000ULL, 0x0100000100000100ULL, },
+        { 0x0001020001020001ULL, 0x0200010200010200ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0002030002030002ULL, 0x0300020300020300ULL, },
+        { 0x0000030000030000ULL, 0x0300000300000300ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*  64  */
+        { 0x0000ff0200000008ULL, 0x040000030c010200ULL, },
+        { 0x0001010100000000ULL, 0x0100000001020400ULL, },
+        { 0x01010a0200020000ULL, 0x0000000001010000ULL, },
+        { 0x0101000001010200ULL, 0x0002110000000015ULL, },
+        { 0x0101ff0101010101ULL, 0x0101010101010101ULL, },
+        { 0x0102000000000100ULL, 0x000100000001020cULL, },
+        { 0x0202000100030000ULL, 0x0001010000000001ULL, },
+        { 0x0100000004020102ULL, 0x0002120200000001ULL, },    /*  72  */
+        { 0x0000ff0102010010ULL, 0x0200010908000000ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },
+        { 0x0101070201040001ULL, 0x0000010101000000ULL, },
+        { 0x0000000002000201ULL, 0x01020c020000010dULL, },
+        { 0x0000ff0001000109ULL, 0x0700000808010200ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_d.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_d.c
new file mode 100644
index 0000000..9653e7d
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_U.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_U.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000003ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000005ULL, 0x0000000000000005ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000004ULL, },
+        { 0x0000000000000009ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000002ULL, 0x0000000000000002ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000003ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000006ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000003ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000002ULL, 0x0000000000000002ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000004ULL, 0x0000000000000004ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000007ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000002ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000004ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000008ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000002ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*  64  */
+        { 0x0000000000000000ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000002ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },    /*  72  */
+        { 0x0000000000000000ULL, 0x0000000000000002ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000007ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_h.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_h.c
new file mode 100644
index 0000000..3dcd30b
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_U.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_U.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0003000300030003ULL, 0x0003000300030003ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0005000500050005ULL, 0x0005000500050005ULL, },
+        { 0x0001000400010001ULL, 0x0004000100010004ULL, },
+        { 0x0009000100020009ULL, 0x0001000200090001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0002000200020002ULL, 0x0002000200020002ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0003000300030003ULL, 0x0003000300030003ULL, },
+        { 0x0000000300010000ULL, 0x0003000100000003ULL, },
+        { 0x0006000000010006ULL, 0x0000000100060000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0000000100000000ULL, 0x0001000000000001ULL, },
+        { 0x0003000000000003ULL, 0x0000000000030000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0002000200020002ULL, 0x0002000200020002ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0004000400040004ULL, 0x0004000400040004ULL, },
+        { 0x0000000300010000ULL, 0x0003000100000003ULL, },
+        { 0x0007000100010007ULL, 0x0001000100070001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000000000001ULL, 0x0000000000010000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0001000000000001ULL, 0x0000000000010000ULL, },
+        { 0x0002000000010002ULL, 0x0000000100020000ULL, },
+        { 0x0001000000000001ULL, 0x0000000000010000ULL, },
+        { 0x0004000100020004ULL, 0x0001000200040001ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0008000000010008ULL, 0x0000000100080000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000000ULL, 0x0001000000000001ULL, },
+        { 0x0000000200010000ULL, 0x0002000100000002ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000300020000ULL, 0x0003000200000003ULL, },
+        { 0x0000000300000000ULL, 0x0003000000000003ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*  64  */
+        { 0x0000025400000000ULL, 0x00030000000b0002ULL, },
+        { 0x0000000100000000ULL, 0x0001000000010004ULL, },
+        { 0x0001000a00000000ULL, 0x0000000000010000ULL, },
+        { 0x0001000000010002ULL, 0x0000001000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0001000000000001ULL, 0x0000000000000002ULL, },
+        { 0x0002000000000000ULL, 0x0000000100000000ULL, },
+        { 0x0001000000040001ULL, 0x0000001100000000ULL, },    /*  72  */
+        { 0x000001c300020000ULL, 0x0002000100080000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0x0001000700010000ULL, 0x0000000100010000ULL, },
+        { 0x0000000000020002ULL, 0x0001000c00000001ULL, },
+        { 0x0000003900010001ULL, 0x0007000000070002ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_w.c b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_w.c
new file mode 100644
index 0000000..fd395ef
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-divide/test_msa_div_u_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DIV_U.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DIV_U.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000300000003ULL, 0x0000000300000003ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000500000005ULL, 0x0000000500000005ULL, },
+        { 0x0000000100000001ULL, 0x0000000400000001ULL, },
+        { 0x0000000900000002ULL, 0x0000000100000009ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000200000002ULL, 0x0000000200000002ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000300000003ULL, 0x0000000300000003ULL, },
+        { 0x0000000000000001ULL, 0x0000000300000000ULL, },
+        { 0x0000000600000001ULL, 0x0000000000000006ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000100000000ULL, },
+        { 0x0000000300000000ULL, 0x0000000000000003ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000200000002ULL, 0x0000000200000002ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000400000004ULL, 0x0000000400000004ULL, },
+        { 0x0000000000000001ULL, 0x0000000300000000ULL, },
+        { 0x0000000700000001ULL, 0x0000000100000007ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000100000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000200000001ULL, 0x0000000000000002ULL, },
+        { 0x0000000100000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000400000002ULL, 0x0000000100000004ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000800000001ULL, 0x0000000000000008ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000100000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000200000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000002ULL, 0x0000000300000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000300000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*  64  */
+        { 0x0000000000000000ULL, 0x000000030000000bULL, },
+        { 0x0000000000000000ULL, 0x0000000100000001ULL, },
+        { 0x0000000100000000ULL, 0x0000000000000001ULL, },
+        { 0x0000000100000001ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000100000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000200000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000004ULL, 0x0000000000000000ULL, },    /*  72  */
+        { 0x0000000000000002ULL, 0x0000000200000008ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0x0000000100000001ULL, 0x0000000000000001ULL, },
+        { 0x0000000000000002ULL, 0x0000000100000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000700000007ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DIV_U_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_d.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_d.c
new file mode 100644
index 0000000..af8d609
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DOTP_S.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DOTP_S.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000002ULL, 0x0000000000000002ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x00000000aaaaaaacULL, 0x00000000aaaaaaacULL, },
+        { 0xffffffff55555556ULL, 0xffffffff55555556ULL, },
+        { 0x0000000066666668ULL, 0x0000000066666668ULL, },
+        { 0xffffffff9999999aULL, 0xffffffff9999999aULL, },
+        { 0x000000008e38e38fULL, 0xffffffffe38e38e5ULL, },
+        { 0xffffffff71c71c73ULL, 0x000000001c71c71dULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x00000000aaaaaaacULL, 0x00000000aaaaaaacULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e38e39c71c71c8ULL, 0x38e38e39c71c71c8ULL, },
+        { 0xc71c71c6e38e38e4ULL, 0xc71c71c6e38e38e4ULL, },
+        { 0x22222222eeeeeef0ULL, 0x22222222eeeeeef0ULL, },
+        { 0xddddddddbbbbbbbcULL, 0xddddddddbbbbbbbcULL, },
+        { 0x2f684bdab425ed0aULL, 0xf684bda197b425eeULL, },
+        { 0xd097b425f684bda2ULL, 0x097b425f12f684beULL, },
+        { 0xffffffff55555556ULL, 0xffffffff55555556ULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c6e38e38e4ULL, 0xc71c71c6e38e38e4ULL, },
+        { 0x38e38e3871c71c72ULL, 0x38e38e3871c71c72ULL, },
+        { 0xdddddddd77777778ULL, 0xdddddddd77777778ULL, },
+        { 0x22222221dddddddeULL, 0x22222221dddddddeULL, },
+        { 0xd097b425da12f685ULL, 0x097b425e4bda12f7ULL, },
+        { 0x2f684bd97b425ed1ULL, 0xf684bda1097b425fULL, },
+        { 0x0000000066666668ULL, 0x0000000066666668ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x22222222eeeeeef0ULL, 0x22222222eeeeeef0ULL, },
+        { 0xdddddddd77777778ULL, 0xdddddddd77777778ULL, },
+        { 0x147ae14851eb8520ULL, 0x147ae14851eb8520ULL, },
+        { 0xeb851eb8147ae148ULL, 0xeb851eb8147ae148ULL, },
+        { 0x1c71c71d0b60b60cULL, 0xfa4fa4fa82d82d84ULL, },
+        { 0xe38e38e35b05b05cULL, 0x05b05b05e38e38e4ULL, },
+        { 0xffffffff9999999aULL, 0xffffffff9999999aULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xddddddddbbbbbbbcULL, 0xddddddddbbbbbbbcULL, },
+        { 0x22222221dddddddeULL, 0x22222221dddddddeULL, },
+        { 0xeb851eb8147ae148ULL, 0xeb851eb8147ae148ULL, },
+        { 0x147ae147851eb852ULL, 0x147ae147851eb852ULL, },
+        { 0xe38e38e382d82d83ULL, 0x05b05b0560b60b61ULL, },
+        { 0x1c71c71c16c16c17ULL, 0xfa4fa4fa38e38e39ULL, },
+        { 0x000000008e38e38fULL, 0xffffffffe38e38e5ULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2f684bdab425ed0aULL, 0xf684bda197b425eeULL, },
+        { 0xd097b425da12f685ULL, 0x097b425e4bda12f7ULL, },
+        { 0x1c71c71d0b60b60cULL, 0xfa4fa4fa82d82d84ULL, },
+        { 0xe38e38e382d82d83ULL, 0x05b05b0560b60b61ULL, },
+        { 0x35ba78199add3c0dULL, 0x0fcd6e9dc0ca4589ULL, },
+        { 0xca4587e6f35ba782ULL, 0xf032916222c3f35cULL, },
+        { 0xffffffff71c71c73ULL, 0x000000001c71c71dULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd097b425f684bda2ULL, 0x097b425f12f684beULL, },
+        { 0x2f684bd97b425ed1ULL, 0xf684bda1097b425fULL, },
+        { 0xe38e38e35b05b05cULL, 0x05b05b05e38e38e4ULL, },
+        { 0x1c71c71c16c16c17ULL, 0xfa4fa4fa38e38e39ULL, },
+        { 0xca4587e6f35ba782ULL, 0xf032916222c3f35cULL, },
+        { 0x35ba78187e6b74f1ULL, 0x0fcd6e9df9add3c1ULL, },
+        { 0x3e3ad4ae1266c290ULL, 0x1637d725aebdb714ULL, },    /*  64  */
+        { 0x0e3a0c27f7d6aae4ULL, 0x0575fbb7f08ff55cULL, },
+        { 0x1c00082337c84b78ULL, 0x0c3d39640fde8392ULL, },
+        { 0xda65cd5e9f696cdcULL, 0xdeeb6bec644a26d0ULL, },
+        { 0x0e3a0c27f7d6aae4ULL, 0x0575fbb7f08ff55cULL, },
+        { 0x17945c09b2e19689ULL, 0x032b395187d966b4ULL, },
+        { 0xec1f0e54b5aa67beULL, 0xfbe95b6e67ae6296ULL, },
+        { 0x1aad30609bff5437ULL, 0xf059a43d01b40370ULL, },
+        { 0x1c00082337c84b78ULL, 0x0c3d39640fde8392ULL, },    /*  72  */
+        { 0xec1f0e54b5aa67beULL, 0xfbe95b6e67ae6296ULL, },
+        { 0x2e9326619bb7c8e4ULL, 0x225024d84d163b91ULL, },
+        { 0xc17a5d0372a2a622ULL, 0x0afd6368668933a8ULL, },
+        { 0xda65cd5e9f696cdcULL, 0xdeeb6bec644a26d0ULL, },
+        { 0x1aad30609bff5437ULL, 0xf059a43d01b40370ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_S_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_S_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_h.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_h.c
new file mode 100644
index 0000000..40de72a
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DOTP_S.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DOTP_S.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0002000200020002ULL, 0x0002000200020002ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x00ac00ac00ac00acULL, 0x00ac00ac00ac00acULL, },
+        { 0xff56ff56ff56ff56ULL, 0xff56ff56ff56ff56ULL, },
+        { 0x0068006800680068ULL, 0x0068006800680068ULL, },
+        { 0xff9aff9aff9aff9aULL, 0xff9aff9aff9aff9aULL, },
+        { 0x008fffe5003a008fULL, 0xffe5003a008fffe5ULL, },
+        { 0xff73001dffc8ff73ULL, 0x001dffc8ff73001dULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x00ac00ac00ac00acULL, 0x00ac00ac00ac00acULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x39c839c839c839c8ULL, 0x39c839c839c839c8ULL, },
+        { 0xc6e4c6e4c6e4c6e4ULL, 0xc6e4c6e4c6e4c6e4ULL, },
+        { 0x22f022f022f022f0ULL, 0x22f022f022f022f0ULL, },
+        { 0xddbcddbcddbcddbcULL, 0xddbcddbcddbcddbcULL, },
+        { 0x300af6ee137c300aULL, 0xf6ee137c300af6eeULL, },
+        { 0xd0a209beed30d0a2ULL, 0x09beed30d0a209beULL, },
+        { 0xff56ff56ff56ff56ULL, 0xff56ff56ff56ff56ULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc6e4c6e4c6e4c6e4ULL, 0xc6e4c6e4c6e4c6e4ULL, },
+        { 0x3872387238723872ULL, 0x3872387238723872ULL, },
+        { 0xdd78dd78dd78dd78ULL, 0xdd78dd78dd78dd78ULL, },
+        { 0x21de21de21de21deULL, 0x21de21de21de21deULL, },
+        { 0xd08508f7ecbed085ULL, 0x08f7ecbed08508f7ULL, },
+        { 0x2ed1f65f12982ed1ULL, 0xf65f12982ed1f65fULL, },
+        { 0x0068006800680068ULL, 0x0068006800680068ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x22f022f022f022f0ULL, 0x22f022f022f022f0ULL, },
+        { 0xdd78dd78dd78dd78ULL, 0xdd78dd78dd78dd78ULL, },
+        { 0x1520152015201520ULL, 0x1520152015201520ULL, },
+        { 0xeb48eb48eb48eb48ULL, 0xeb48eb48eb48eb48ULL, },
+        { 0x1d0cfa840bc81d0cULL, 0xfa840bc81d0cfa84ULL, },
+        { 0xe35c05e4f4a0e35cULL, 0x05e4f4a0e35c05e4ULL, },
+        { 0xff9aff9aff9aff9aULL, 0xff9aff9aff9aff9aULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xddbcddbcddbcddbcULL, 0xddbcddbcddbcddbcULL, },
+        { 0x21de21de21de21deULL, 0x21de21de21de21deULL, },
+        { 0xeb48eb48eb48eb48ULL, 0xeb48eb48eb48eb48ULL, },
+        { 0x1452145214521452ULL, 0x1452145214521452ULL, },
+        { 0xe3830561f472e383ULL, 0x0561f472e3830561ULL, },
+        { 0x1c17fa390b281c17ULL, 0xfa390b281c17fa39ULL, },
+        { 0x008fffe5003a008fULL, 0xffe5003a008fffe5ULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x300af6ee137c300aULL, 0xf6ee137c300af6eeULL, },
+        { 0xd08508f7ecbed085ULL, 0x08f7ecbed08508f7ULL, },
+        { 0x1d0cfa840bc81d0cULL, 0xfa840bc81d0cfa84ULL, },
+        { 0xe3830561f472e383ULL, 0x0561f472e3830561ULL, },
+        { 0x360d0f893f04360dULL, 0x0f893f04360d0f89ULL, },
+        { 0xca82f05cc136ca82ULL, 0xf05cc136ca82f05cULL, },
+        { 0xff73001dffc8ff73ULL, 0x001dffc8ff73001dULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xd0a209beed30d0a2ULL, 0x09beed30d0a209beULL, },
+        { 0x2ed1f65f12982ed1ULL, 0xf65f12982ed1f65fULL, },
+        { 0xe35c05e4f4a0e35cULL, 0x05e4f4a0e35c05e4ULL, },
+        { 0x1c17fa390b281c17ULL, 0xfa390b281c17fa39ULL, },
+        { 0xca82f05cc136ca82ULL, 0xf05cc136ca82f05cULL, },
+        { 0x34f10fc13e9234f1ULL, 0x0fc13e9234f10fc1ULL, },
+        { 0x64240d342bc42c39ULL, 0x3f6a22fd3b1d1990ULL, },    /*  64  */
+        { 0xe704ebe4e24eef13ULL, 0x01a706951e1be630ULL, },
+        { 0x4ca419cce226b927ULL, 0xfb55fd241553f560ULL, },
+        { 0xec36ee202172098aULL, 0xd846ec28206404e0ULL, },
+        { 0xe704ebe4e24eef13ULL, 0x01a706951e1be630ULL, },
+        { 0x111d264945920cf1ULL, 0x0195153d113a1a54ULL, },
+        { 0xea70debeff82160dULL, 0x04260f88039c0b8aULL, },
+        { 0xe9721dc70769091eULL, 0xf8711c48091bf7e4ULL, },
+        { 0x4ca419cce226b927ULL, 0xfb55fd241553f560ULL, },    /*  72  */
+        { 0xea70debeff82160dULL, 0x04260f88039c0b8aULL, },
+        { 0x3b3437281d127579ULL, 0x0c310d25237206e9ULL, },
+        { 0xf706df16dc8de6b6ULL, 0xf0d31b5827f9f42aULL, },
+        { 0xec36ee202172098aULL, 0xd846ec28206404e0ULL, },
+        { 0xe9721dc70769091eULL, 0xf8711c48091bf7e4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_S_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_S_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_w.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_w.c
new file mode 100644
index 0000000..2f1d23b
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_s_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DOTP_S.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DOTP_S.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000200000002ULL, 0x0000000200000002ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000aaac0000aaacULL, 0x0000aaac0000aaacULL, },
+        { 0xffff5556ffff5556ULL, 0xffff5556ffff5556ULL, },
+        { 0x0000666800006668ULL, 0x0000666800006668ULL, },
+        { 0xffff999affff999aULL, 0xffff999affff999aULL, },
+        { 0xffffe38f00008e3aULL, 0x000038e5ffffe38fULL, },
+        { 0x00001c73ffff71c8ULL, 0xffffc71d00001c73ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000aaac0000aaacULL, 0x0000aaac0000aaacULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e471c838e471c8ULL, 0x38e471c838e471c8ULL, },
+        { 0xc71c38e4c71c38e4ULL, 0xc71c38e4c71c38e4ULL, },
+        { 0x2222eef02222eef0ULL, 0x2222eef02222eef0ULL, },
+        { 0xddddbbbcddddbbbcULL, 0xddddbbbcddddbbbcULL, },
+        { 0xf684ed0a2f69097cULL, 0x12f725eef684ed0aULL, },
+        { 0x097bbda2d097a130ULL, 0xed0984be097bbda2ULL, },
+        { 0xffff5556ffff5556ULL, 0xffff5556ffff5556ULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c38e4c71c38e4ULL, 0xc71c38e4c71c38e4ULL, },
+        { 0x38e31c7238e31c72ULL, 0x38e31c7238e31c72ULL, },
+        { 0xdddd7778dddd7778ULL, 0xdddd7778dddd7778ULL, },
+        { 0x2221ddde2221dddeULL, 0x2221ddde2221dddeULL, },
+        { 0x097af685d09784beULL, 0xed0912f7097af685ULL, },
+        { 0xf6845ed12f67d098ULL, 0x12f6425ff6845ed1ULL, },
+        { 0x0000666800006668ULL, 0x0000666800006668ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222eef02222eef0ULL, 0x2222eef02222eef0ULL, },
+        { 0xdddd7778dddd7778ULL, 0xdddd7778dddd7778ULL, },
+        { 0x147b8520147b8520ULL, 0x147b8520147b8520ULL, },
+        { 0xeb84e148eb84e148ULL, 0xeb84e148eb84e148ULL, },
+        { 0xfa4fb60c1c7271c8ULL, 0x0b612d84fa4fb60cULL, },
+        { 0x05b0b05ce38df4a0ULL, 0xf49f38e405b0b05cULL, },
+        { 0xffff999affff999aULL, 0xffff999affff999aULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xddddbbbcddddbbbcULL, 0xddddbbbcddddbbbcULL, },
+        { 0x2221ddde2221dddeULL, 0x2221ddde2221dddeULL, },
+        { 0xeb84e148eb84e148ULL, 0xeb84e148eb84e148ULL, },
+        { 0x147ab852147ab852ULL, 0x147ab852147ab852ULL, },
+        { 0x05b02d83e38e1c72ULL, 0xf49f0b6105b02d83ULL, },
+        { 0xfa4f6c171c717d28ULL, 0x0b608e39fa4f6c17ULL, },
+        { 0xffffe38f00008e3aULL, 0x000038e5ffffe38fULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xf684ed0a2f69097cULL, 0x12f725eef684ed0aULL, },
+        { 0x097af685d09784beULL, 0xed0912f7097af685ULL, },
+        { 0xfa4fb60c1c7271c8ULL, 0x0b612d84fa4fb60cULL, },
+        { 0x05b02d83e38e1c72ULL, 0xf49f0b6105b02d83ULL, },
+        { 0x0fcd3c0d35bb4f04ULL, 0x3f3645890fcd3c0dULL, },
+        { 0xf032a782ca453f36ULL, 0xc0c9f35cf032a782ULL, },
+        { 0x00001c73ffff71c8ULL, 0xffffc71d00001c73ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x097bbda2d097a130ULL, 0xed0984be097bbda2ULL, },
+        { 0xf6845ed12f67d098ULL, 0x12f6425ff6845ed1ULL, },
+        { 0x05b0b05ce38df4a0ULL, 0xf49f38e405b0b05cULL, },
+        { 0xfa4f6c171c717d28ULL, 0x0b608e39fa4f6c17ULL, },
+        { 0xf032a782ca453f36ULL, 0xc0c9f35cf032a782ULL, },
+        { 0x0fcd74f135ba3292ULL, 0x3f35d3c10fcd74f1ULL, },
+        { 0x3a57fe7422c25584ULL, 0x16b6b9f518facfa9ULL, },    /*  64  */
+        { 0x01f36d90f9441446ULL, 0x0286cfede5f4db15ULL, },
+        { 0x2f1518bcce21d93eULL, 0x0934568af4ec6499ULL, },
+        { 0xc9576c1204f83042ULL, 0xd91d3e4709b06e36ULL, },
+        { 0x01f36d90f9441446ULL, 0x0286cfede5f4db15ULL, },
+        { 0x0012474d242f32a9ULL, 0x13f2a8f51ca9cd91ULL, },
+        { 0x0144b48a04a7d0ddULL, 0x124b1c4e04fa8e45ULL, },
+        { 0xfe2a6f6923268793ULL, 0x179e9377ef4766beULL, },
+        { 0x2f1518bcce21d93eULL, 0x0934568af4ec6499ULL, },    /*  72  */
+        { 0x0144b48a04a7d0ddULL, 0x124b1c4e04fa8e45ULL, },
+        { 0x352c988848431561ULL, 0x12e4f841217b42c9ULL, },
+        { 0xd437b4e8f3b0139fULL, 0x08c7d980187d5896ULL, },
+        { 0xc9576c1204f83042ULL, 0xd91d3e4709b06e36ULL, },
+        { 0xfe2a6f6923268793ULL, 0x179e9377ef4766beULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_S_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_S_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_d.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_d.c
new file mode 100644
index 0000000..e998e00
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DOTP_U.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DOTP_U.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xfffffffc00000002ULL, 0xfffffffc00000002ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x55555552aaaaaaacULL, 0x55555552aaaaaaacULL, },
+        { 0xaaaaaaa955555556ULL, 0xaaaaaaa955555556ULL, },
+        { 0x9999999666666668ULL, 0x9999999666666668ULL, },
+        { 0x666666659999999aULL, 0x666666659999999aULL, },
+        { 0x71c71c6f8e38e38fULL, 0x1c71c719e38e38e5ULL, },
+        { 0x8e38e38c71c71c73ULL, 0xe38e38e21c71c71dULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x55555552aaaaaaacULL, 0x55555552aaaaaaacULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xe38e38e1c71c71c8ULL, 0xe38e38e1c71c71c8ULL, },
+        { 0x71c71c70e38e38e4ULL, 0x71c71c70e38e38e4ULL, },
+        { 0x1111110eeeeeeef0ULL, 0x1111110eeeeeeef0ULL, },
+        { 0x44444443bbbbbbbcULL, 0x44444443bbbbbbbcULL, },
+        { 0xf684bd9fb425ed0aULL, 0xbda12f6697b425eeULL, },
+        { 0x5ed097b2f684bda2ULL, 0x97b425ec12f684beULL, },
+        { 0xaaaaaaa955555556ULL, 0xaaaaaaa955555556ULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x71c71c70e38e38e4ULL, 0x71c71c70e38e38e4ULL, },
+        { 0x38e38e3871c71c72ULL, 0x38e38e3871c71c72ULL, },
+        { 0x8888888777777778ULL, 0x8888888777777778ULL, },
+        { 0x22222221dddddddeULL, 0x22222221dddddddeULL, },
+        { 0x7b425ecfda12f685ULL, 0x5ed097b34bda12f7ULL, },
+        { 0x2f684bd97b425ed1ULL, 0x4bda12f6097b425fULL, },
+        { 0x9999999666666668ULL, 0x9999999666666668ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1111110eeeeeeef0ULL, 0x1111110eeeeeeef0ULL, },
+        { 0x8888888777777778ULL, 0x8888888777777778ULL, },
+        { 0x47ae147851eb8520ULL, 0x47ae147851eb8520ULL, },
+        { 0x51eb851e147ae148ULL, 0x51eb851e147ae148ULL, },
+        { 0x27d27d260b60b60cULL, 0xe38e38e182d82d84ULL, },
+        { 0x71c71c705b05b05cULL, 0xb60b60b4e38e38e4ULL, },
+        { 0x666666659999999aULL, 0x666666659999999aULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x44444443bbbbbbbcULL, 0x44444443bbbbbbbcULL, },
+        { 0x22222221dddddddeULL, 0x22222221dddddddeULL, },
+        { 0x51eb851e147ae148ULL, 0x51eb851e147ae148ULL, },
+        { 0x147ae147851eb852ULL, 0x147ae147851eb852ULL, },
+        { 0x49f49f4982d82d83ULL, 0x38e38e3860b60b61ULL, },
+        { 0x1c71c71c16c16c17ULL, 0x2d82d82d38e38e39ULL, },
+        { 0x71c71c6f8e38e38fULL, 0x1c71c719e38e38e5ULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xf684bd9fb425ed0aULL, 0xbda12f6697b425eeULL, },
+        { 0x7b425ecfda12f685ULL, 0x5ed097b34bda12f7ULL, },
+        { 0x27d27d260b60b60cULL, 0xe38e38e182d82d84ULL, },
+        { 0x49f49f4982d82d83ULL, 0x38e38e3860b60b61ULL, },
+        { 0x1948b0fb9add3c0dULL, 0xd6e9e063c0ca4589ULL, },
+        { 0x587e6b73f35ba782ULL, 0x4587e6b622c3f35cULL, },
+        { 0x8e38e38c71c71c73ULL, 0xe38e38e21c71c71dULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5ed097b2f684bda2ULL, 0x97b425ec12f684beULL, },
+        { 0x2f684bd97b425ed1ULL, 0x4bda12f6097b425fULL, },
+        { 0x71c71c705b05b05cULL, 0xb60b60b4e38e38e4ULL, },
+        { 0x1c71c71c16c16c17ULL, 0x2d82d82d38e38e39ULL, },
+        { 0x587e6b73f35ba782ULL, 0x4587e6b622c3f35cULL, },
+        { 0x35ba78187e6b74f1ULL, 0x9e06522bf9add3c1ULL, },
+        { 0x4f10a2461266c290ULL, 0x132f373daebdb714ULL, },    /*  64  */
+        { 0x9262f356f7d6aae4ULL, 0x1ab54eb3f08ff55cULL, },
+        { 0x7927f2d937c84b78ULL, 0xb5e40e840fde8392ULL, },
+        { 0x4ab4e3ab9f696cdcULL, 0xd21109f6644a26d0ULL, },
+        { 0x9262f356f7d6aae4ULL, 0x1ab54eb3f08ff55cULL, },
+        { 0x0f105ccfb2e19689ULL, 0x032b395187d966b4ULL, },
+        { 0xe1cb8469b5aa67beULL, 0x1128ae6a67ae6296ULL, },
+        { 0x8afc46ad9bff5437ULL, 0x1890b25301b40370ULL, },
+        { 0x7927f2d937c84b78ULL, 0xb5e40e840fde8392ULL, },    /*  72  */
+        { 0xe1cb8469b5aa67beULL, 0x1128ae6a67ae6296ULL, },
+        { 0xfae79ab59bb7c8e4ULL, 0x78a66f004d163b91ULL, },
+        { 0x8ffb559e72a2a622ULL, 0x8744321b668933a8ULL, },
+        { 0x4ab4e3ab9f696cdcULL, 0xd21109f6644a26d0ULL, },
+        { 0x8afc46ad9bff5437ULL, 0x1890b25301b40370ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_U_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_U_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_h.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_h.c
new file mode 100644
index 0000000..e8db601
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DOTP_U.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DOTP_U.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xfc02fc02fc02fc02ULL, 0xfc02fc02fc02fc02ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x52ac52ac52ac52acULL, 0x52ac52ac52ac52acULL, },
+        { 0xa956a956a956a956ULL, 0xa956a956a956a956ULL, },
+        { 0x9668966896689668ULL, 0x9668966896689668ULL, },
+        { 0x659a659a659a659aULL, 0x659a659a659a659aULL, },
+        { 0x6f8f19e5c53a6f8fULL, 0x19e5c53a6f8f19e5ULL, },
+        { 0x8c73e21d36c88c73ULL, 0xe21d36c88c73e21dULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x52ac52ac52ac52acULL, 0x52ac52ac52ac52acULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xe1c8e1c8e1c8e1c8ULL, 0xe1c8e1c8e1c8e1c8ULL, },
+        { 0x70e470e470e470e4ULL, 0x70e470e470e470e4ULL, },
+        { 0x0ef00ef00ef00ef0ULL, 0x0ef00ef00ef00ef0ULL, },
+        { 0x43bc43bc43bc43bcULL, 0x43bc43bc43bc43bcULL, },
+        { 0xf50abbee837cf50aULL, 0xbbee837cf50abbeeULL, },
+        { 0x5da296becf305da2ULL, 0x96becf305da296beULL, },
+        { 0xa956a956a956a956ULL, 0xa956a956a956a956ULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x70e470e470e470e4ULL, 0x70e470e470e470e4ULL, },
+        { 0x3872387238723872ULL, 0x3872387238723872ULL, },
+        { 0x8778877887788778ULL, 0x8778877887788778ULL, },
+        { 0x21de21de21de21deULL, 0x21de21de21de21deULL, },
+        { 0x7a855df741be7a85ULL, 0x5df741be7a855df7ULL, },
+        { 0x2ed14b5f67982ed1ULL, 0x4b5f67982ed14b5fULL, },
+        { 0x9668966896689668ULL, 0x9668966896689668ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0ef00ef00ef00ef0ULL, 0x0ef00ef00ef00ef0ULL, },
+        { 0x8778877887788778ULL, 0x8778877887788778ULL, },
+        { 0x4520452045204520ULL, 0x4520452045204520ULL, },
+        { 0x5148514851485148ULL, 0x5148514851485148ULL, },
+        { 0x260ce1849dc8260cULL, 0xe1849dc8260ce184ULL, },
+        { 0x705cb4e4f8a0705cULL, 0xb4e4f8a0705cb4e4ULL, },
+        { 0x659a659a659a659aULL, 0x659a659a659a659aULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x43bc43bc43bc43bcULL, 0x43bc43bc43bc43bcULL, },
+        { 0x21de21de21de21deULL, 0x21de21de21de21deULL, },
+        { 0x5148514851485148ULL, 0x5148514851485148ULL, },
+        { 0x1452145214521452ULL, 0x1452145214521452ULL, },
+        { 0x4983386127724983ULL, 0x3861277249833861ULL, },
+        { 0x1c172d393e281c17ULL, 0x2d393e281c172d39ULL, },
+        { 0x6f8f19e5c53a6f8fULL, 0x19e5c53a6f8f19e5ULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xf50abbee837cf50aULL, 0xbbee837cf50abbeeULL, },
+        { 0x7a855df741be7a85ULL, 0x5df741be7a855df7ULL, },
+        { 0x260ce1849dc8260cULL, 0xe1849dc8260ce184ULL, },
+        { 0x4983386127724983ULL, 0x3861277249833861ULL, },
+        { 0x180dd5895b04180dULL, 0xd5895b04180dd589ULL, },
+        { 0x5782445c6a365782ULL, 0x445c6a365782445cULL, },
+        { 0x8c73e21d36c88c73ULL, 0xe21d36c88c73e21dULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5da296becf305da2ULL, 0x96becf305da296beULL, },
+        { 0x2ed14b5f67982ed1ULL, 0x4b5f67982ed14b5fULL, },
+        { 0x705cb4e4f8a0705cULL, 0xb4e4f8a0705cb4e4ULL, },
+        { 0x1c172d393e281c17ULL, 0x2d393e281c172d39ULL, },
+        { 0x5782445c6a365782ULL, 0x445c6a365782445cULL, },
+        { 0x34f19dc1cc9234f1ULL, 0x9dc1cc9234f19dc1ULL, },
+        { 0x742471342bc42c39ULL, 0x3f6a22fd371d7990ULL, },    /*  64  */
+        { 0xd4044ee4444e4413ULL, 0x68a71195331b4430ULL, },
+        { 0x80a423cc6c264e27ULL, 0x62556624be531a60ULL, },
+        { 0x5c36512021725e8aULL, 0x8a465528c764a2e0ULL, },
+        { 0xd4044ee4444e4413ULL, 0x68a71195331b4430ULL, },
+        { 0x831d26496b929af1ULL, 0xef958b3d113a1254ULL, },
+        { 0xeb7041beae82700dULL, 0xd326aa88189c1f8aULL, },
+        { 0xa8721dc73869b21eULL, 0xf27179481e1be5e4ULL, },
+        { 0x80a423cc6c264e27ULL, 0x62556624be531a60ULL, },    /*  72  */
+        { 0xeb7041beae82700dULL, 0xd326aa88189c1f8aULL, },
+        { 0x9334e7282d128b79ULL, 0xbc319725797206e9ULL, },
+        { 0x670642166b8da1b6ULL, 0xe0d340587bf92d2aULL, },
+        { 0x5c36512021725e8aULL, 0x8a465528c764a2e0ULL, },
+        { 0xa8721dc73869b21eULL, 0xf27179481e1be5e4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_U_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_U_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_w.c b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_w.c
new file mode 100644
index 0000000..cf5bd13
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-dot-product/test_msa_dotp_u_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction DOTP_U.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "DOTP_U.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xfffc0002fffc0002ULL, 0xfffc0002fffc0002ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5552aaac5552aaacULL, 0x5552aaac5552aaacULL, },
+        { 0xaaa95556aaa95556ULL, 0xaaa95556aaa95556ULL, },
+        { 0x9996666899966668ULL, 0x9996666899966668ULL, },
+        { 0x6665999a6665999aULL, 0x6665999a6665999aULL, },
+        { 0x1c6fe38f71c48e3aULL, 0xc71a38e51c6fe38fULL, },
+        { 0xe38c1c738e3771c8ULL, 0x38e1c71de38c1c73ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5552aaac5552aaacULL, 0x5552aaac5552aaacULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xe38c71c8e38c71c8ULL, 0xe38c71c8e38c71c8ULL, },
+        { 0x71c638e471c638e4ULL, 0x71c638e471c638e4ULL, },
+        { 0x110eeef0110eeef0ULL, 0x110eeef0110eeef0ULL, },
+        { 0x4443bbbc4443bbbcULL, 0x4443bbbc4443bbbcULL, },
+        { 0xbd9fed0af683097cULL, 0x84bc25eebd9fed0aULL, },
+        { 0x97b2bda25ecfa130ULL, 0xd09684be97b2bda2ULL, },
+        { 0xaaa95556aaa95556ULL, 0xaaa95556aaa95556ULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x71c638e471c638e4ULL, 0x71c638e471c638e4ULL, },
+        { 0x38e31c7238e31c72ULL, 0x38e31c7238e31c72ULL, },
+        { 0x8887777888877778ULL, 0x8887777888877778ULL, },
+        { 0x2221ddde2221dddeULL, 0x2221ddde2221dddeULL, },
+        { 0x5ecff6857b4184beULL, 0x425e12f75ecff685ULL, },
+        { 0x4bd95ed12f67d098ULL, 0x684b425f4bd95ed1ULL, },
+        { 0x9996666899966668ULL, 0x9996666899966668ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x110eeef0110eeef0ULL, 0x110eeef0110eeef0ULL, },
+        { 0x8887777888877778ULL, 0x8887777888877778ULL, },
+        { 0x47ab852047ab8520ULL, 0x47ab852047ab8520ULL, },
+        { 0x51eae14851eae148ULL, 0x51eae14851eae148ULL, },
+        { 0xe38cb60c27d071c8ULL, 0x9f482d84e38cb60cULL, },
+        { 0xb609b05c71c5f4a0ULL, 0xfa4e38e4b609b05cULL, },
+        { 0x6665999a6665999aULL, 0x6665999a6665999aULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4443bbbc4443bbbcULL, 0x4443bbbc4443bbbcULL, },
+        { 0x2221ddde2221dddeULL, 0x2221ddde2221dddeULL, },
+        { 0x51eae14851eae148ULL, 0x51eae14851eae148ULL, },
+        { 0x147ab852147ab852ULL, 0x147ab852147ab852ULL, },
+        { 0x38e32d8349f41c72ULL, 0x27d20b6138e32d83ULL, },
+        { 0x2d826c171c717d28ULL, 0x3e938e392d826c17ULL, },
+        { 0x1c6fe38f71c48e3aULL, 0xc71a38e51c6fe38fULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xbd9fed0af683097cULL, 0x84bc25eebd9fed0aULL, },
+        { 0x5ecff6857b4184beULL, 0x425e12f75ecff685ULL, },
+        { 0xe38cb60c27d071c8ULL, 0x9f482d84e38cb60cULL, },
+        { 0x38e32d8349f41c72ULL, 0x27d20b6138e32d83ULL, },
+        { 0xd6e93c0d19474f04ULL, 0x5ba64589d6e93c0dULL, },
+        { 0x4586a782587d3f36ULL, 0x6b73f35c4586a782ULL, },
+        { 0xe38c1c738e3771c8ULL, 0x38e1c71de38c1c73ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x97b2bda25ecfa130ULL, 0xd09684be97b2bda2ULL, },
+        { 0x4bd95ed12f67d098ULL, 0x684b425f4bd95ed1ULL, },
+        { 0xb609b05c71c5f4a0ULL, 0xfa4e38e4b609b05cULL, },
+        { 0x2d826c171c717d28ULL, 0x3e938e392d826c17ULL, },
+        { 0x4586a782587d3f36ULL, 0x6b73f35c4586a782ULL, },
+        { 0x9e0574f135ba3292ULL, 0xcd6dd3c19e0574f1ULL, },
+        { 0x18c3fe7422c25584ULL, 0x16b6b9f57608cfa9ULL, },    /*  64  */
+        { 0x867e6d904e841446ULL, 0x0de4cfed4e2fdb15ULL, },
+        { 0xf94f18bc4bc3d93eULL, 0x1492568ac3a66499ULL, },
+        { 0x4ff36c125a383042ULL, 0x2fe23e4744196e36ULL, },
+        { 0x867e6d904e841446ULL, 0x0de4cfed4e2fdb15ULL, },
+        { 0xf78e474db23f32a9ULL, 0x8a26a8f51ca9cd91ULL, },
+        { 0xa9bfb48aa4c2d0ddULL, 0x94641c4e1a398e45ULL, },
+        { 0x6e796f69cc7c8793ULL, 0x6e879377578266beULL, },
+        { 0xf94f18bc4bc3d93eULL, 0x1492568ac3a66499ULL, },    /*  72  */
+        { 0xa9bfb48aa4c2d0ddULL, 0x94641c4e1a398e45ULL, },
+        { 0xeb349888d2e11561ULL, 0xa0e2f84177d142c9ULL, },
+        { 0x5ad3b4e8bfaf139fULL, 0x8076d98091fe5896ULL, },
+        { 0x4ff36c125a383042ULL, 0x2fe23e4744196e36ULL, },
+        { 0x6e796f69cc7c8793ULL, 0x6e879377578266beULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_U_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_DOTP_U_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c
index b7a9a61..5fa2644 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_A.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c
index dfffaf5..9d97982 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_A.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c
index e0c1bd4..3365f72 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_A.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c
index 40c30c5..b33f4b7 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_a_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_A.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c
index ab50eee..71e571d 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_S.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c
index 2957db4..e088ab9 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_S.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c
index e101764..6d1b81a 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_S.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c
index 119f03f..bd64294 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_s_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_S.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c
index d18b6bf..206d907 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_U.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c
index 1396e74..4dd247f 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_U.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c
index c7dff10..0e6a765 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_U.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c
index 910dbfc..db61440 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_max_u_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MAX_U.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c
index c632fe9..d2a93a2 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_A.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c
index 5f9a9d4..69fd3c7 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_A.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c
index dc73927..9f45b55 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_A.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c
index 67b33f3..b08231d 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_a_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_A.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c
index 76bb133..80b5201 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_S.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c
index 8ef57a9..0ed3190 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_S.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c
index e206040..b049054 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_S.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c
index 7532bce..2bcd0a0 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_s_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_S.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c
index 1f61145..2a06b43 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_U.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c
index 4626c62..37924f3 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_U.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c
index 5eeb8d0..1846995 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_U.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c
index e70964a..8b20c05 100644
--- a/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c
+++ b/tests/tcg/mips/user/ase/msa/int-max-min/test_msa_min_u_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction MIN_U.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_h.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_h.c
new file mode 100644
index 0000000..f152608
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MUL_Q.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MUL_Q.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+        { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e438e438e438e4ULL, 0x38e438e438e438e4ULL, },
+        { 0xc71cc71cc71cc71cULL, 0xc71cc71cc71cc71cULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x12f6da134bdb12f6ULL, 0xda134bdb12f6da13ULL, },
+        { 0xed0925edb425ed09ULL, 0x25edb425ed0925edULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71cc71cc71cc71cULL, 0xc71cc71cc71cc71cULL, },
+        { 0x38e338e338e338e3ULL, 0x38e338e338e338e3ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x2221222122212221ULL, 0x2221222122212221ULL, },
+        { 0xed0925ecb425ed09ULL, 0x25ecb425ed0925ecULL, },
+        { 0x12f5da124bd912f5ULL, 0xda124bd912f5da12ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x147b147b147b147bULL, 0x147b147b147b147bULL, },
+        { 0xeb84eb84eb84eb84ULL, 0xeb84eb84eb84eb84ULL, },
+        { 0x0b60e93e2d830b60ULL, 0xe93e2d830b60e93eULL, },
+        { 0xf49f16c1d27cf49fULL, 0x16c1d27cf49f16c1ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x2221222122212221ULL, 0x2221222122212221ULL, },
+        { 0xeb84eb84eb84eb84ULL, 0xeb84eb84eb84eb84ULL, },
+        { 0x147a147a147a147aULL, 0x147a147a147a147aULL, },
+        { 0xf49f16c1d27cf49fULL, 0x16c1d27cf49f16c1ULL, },
+        { 0x0b60e93e2d820b60ULL, 0xe93e2d820b60e93eULL, },
+        { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x12f6da134bdb12f6ULL, 0xda134bdb12f6da13ULL, },
+        { 0xed0925ecb425ed09ULL, 0x25ecb425ed0925ecULL, },
+        { 0x0b60e93e2d830b60ULL, 0xe93e2d830b60e93eULL, },
+        { 0xf49f16c1d27cf49fULL, 0x16c1d27cf49f16c1ULL, },
+        { 0x0652194865240652ULL, 0x1948652406521948ULL, },
+        { 0xf9ade6b79adcf9adULL, 0xe6b79adcf9ade6b7ULL, },
+        { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xed0925edb425ed09ULL, 0x25edb425ed0925edULL, },
+        { 0x12f5da124bd912f5ULL, 0xda124bd912f5da12ULL, },
+        { 0xf49f16c1d27cf49fULL, 0x16c1d27cf49f16c1ULL, },
+        { 0x0b60e93e2d820b60ULL, 0xe93e2d820b60e93eULL, },
+        { 0xf9ade6b79adcf9adULL, 0xe6b79adcf9ade6b7ULL, },
+        { 0x0651194965220651ULL, 0x1949652206511949ULL, },
+        { 0x6fb904f60cbd38c7ULL, 0x2c6b0102000431f1ULL, },    /*  64  */
+        { 0x03faffec1879da0eULL, 0x0b2bf9e1ffbfcc2aULL, },
+        { 0x4e261003e9dab268ULL, 0x1778faf00101e8d6ULL, },
+        { 0x9712fb9b1db7ec38ULL, 0xbccff56b01071259ULL, },
+        { 0x03faffec1879da0eULL, 0x0b2bf9e1ffbfcc2aULL, },
+        { 0x002400002f03195aULL, 0x02cf2515038635ccULL, },
+        { 0x02c8ffc1d57533d9ULL, 0x05e71eaef1eb1809ULL, },
+        { 0xfc43001139150d37ULL, 0xef194023f19aecf4ULL, },
+        { 0x4e261003e9dab268ULL, 0x1778faf00101e8d6ULL, },    /*  72  */
+        { 0x02c8ffc1d57533d9ULL, 0x05e71eaef1eb1809ULL, },
+        { 0x36aa33af267d6a08ULL, 0x0c67196238380abdULL, },
+        { 0xb69bf1d4cc591b07ULL, 0xdc7e3510397df77dULL, },
+        { 0x9712fb9b1db7ec38ULL, 0xbccff56b01071259ULL, },
+        { 0xfc43001139150d37ULL, 0xef194023f19aecf4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MUL_Q_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MUL_Q_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_w.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_w.c
new file mode 100644
index 0000000..df815ee
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mul_q_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MUL_Q.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MUL_Q.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+        { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e38e3938e38e39ULL, 0x38e38e3938e38e39ULL, },
+        { 0xc71c71c6c71c71c6ULL, 0xc71c71c6c71c71c6ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x12f684be4bda12f7ULL, 0xda12f68512f684beULL, },
+        { 0xed097b42b425ed09ULL, 0x25ed097bed097b42ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c6c71c71c6ULL, 0xc71c71c6c71c71c6ULL, },
+        { 0x38e38e3838e38e38ULL, 0x38e38e3838e38e38ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x2222222122222221ULL, 0x2222222122222221ULL, },
+        { 0xed097b42b425ed09ULL, 0x25ed097aed097b42ULL, },
+        { 0x12f684bd4bda12f5ULL, 0xda12f68412f684bdULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x147ae148147ae148ULL, 0x147ae148147ae148ULL, },
+        { 0xeb851eb8eb851eb8ULL, 0xeb851eb8eb851eb8ULL, },
+        { 0x0b60b60b2d82d82eULL, 0xe93e93e90b60b60bULL, },
+        { 0xf49f49f4d27d27d2ULL, 0x16c16c17f49f49f4ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x2222222122222221ULL, 0x2222222122222221ULL, },
+        { 0xeb851eb8eb851eb8ULL, 0xeb851eb8eb851eb8ULL, },
+        { 0x147ae147147ae147ULL, 0x147ae147147ae147ULL, },
+        { 0xf49f49f4d27d27d2ULL, 0x16c16c16f49f49f4ULL, },
+        { 0x0b60b60b2d82d82dULL, 0xe93e93e90b60b60bULL, },
+        { 0x0000000000000000ULL, 0xffffffff00000000ULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x12f684be4bda12f7ULL, 0xda12f68512f684beULL, },
+        { 0xed097b42b425ed09ULL, 0x25ed097aed097b42ULL, },
+        { 0x0b60b60b2d82d82eULL, 0xe93e93e90b60b60bULL, },
+        { 0xf49f49f4d27d27d2ULL, 0x16c16c16f49f49f4ULL, },
+        { 0x06522c3f6522c3f3ULL, 0x1948b0fc06522c3fULL, },
+        { 0xf9add3c09add3c0dULL, 0xe6b74f03f9add3c0ULL, },
+        { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xed097b42b425ed09ULL, 0x25ed097bed097b42ULL, },
+        { 0x12f684bd4bda12f5ULL, 0xda12f68412f684bdULL, },
+        { 0xf49f49f4d27d27d2ULL, 0x16c16c17f49f49f4ULL, },
+        { 0x0b60b60b2d82d82dULL, 0xe93e93e90b60b60bULL, },
+        { 0xf9add3c09add3c0dULL, 0xe6b74f03f9add3c0ULL, },
+        { 0x06522c3f6522c3f1ULL, 0x1948b0fc06522c3fULL, },
+        { 0x6fb7e8890cbdc0d2ULL, 0x2c6b144600049a04ULL, },    /*  64  */
+        { 0x03fa514e1879c701ULL, 0x0b2c6ca9ffbf8ac6ULL, },
+        { 0x4e252086e9daefbfULL, 0x1779189301015a34ULL, },
+        { 0x9713a7171db7f3a5ULL, 0xbccfb4690107236fULL, },
+        { 0x03fa514e1879c701ULL, 0x0b2c6ca9ffbf8ac6ULL, },
+        { 0x002442012f047611ULL, 0x02cf8c140386e68eULL, },
+        { 0x02c84b87d575d121ULL, 0x05e79a8af1eb1c52ULL, },
+        { 0xfc439edc3916c1e4ULL, 0xef19389cf19a0fddULL, },
+        { 0x4e252086e9daefbfULL, 0x1779189301015a34ULL, },    /*  72  */
+        { 0x02c84b87d575d121ULL, 0x05e79a8af1eb1c52ULL, },
+        { 0x36a93aff267d11c3ULL, 0x0c6788643838c14cULL, },
+        { 0xb69baa39cc590fcdULL, 0xdc7e6df7397c58d9ULL, },
+        { 0x9713a7171db7f3a5ULL, 0xbccfb4690107236fULL, },
+        { 0xfc439edc3916c1e4ULL, 0xef19389cf19a0fddULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MUL_Q_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MUL_Q_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_h.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_h.c
new file mode 100644
index 0000000..fd0a5fa
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MULR_Q.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MULR_Q.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000010000ULL, 0x0000000100000000ULL, },
+        { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e438e438e438e4ULL, 0x38e438e438e438e4ULL, },
+        { 0xc71cc71cc71cc71cULL, 0xc71cc71cc71cc71cULL, },
+        { 0x2223222322232223ULL, 0x2223222322232223ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x12f7da134bdb12f7ULL, 0xda134bdb12f7da13ULL, },
+        { 0xed0a25eeb425ed0aULL, 0x25eeb425ed0a25eeULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71cc71cc71cc71cULL, 0xc71cc71cc71cc71cULL, },
+        { 0x38e338e338e338e3ULL, 0x38e338e338e338e3ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xed0925edb426ed09ULL, 0x25edb426ed0925edULL, },
+        { 0x12f6da134bda12f6ULL, 0xda134bda12f6da13ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2223222322232223ULL, 0x2223222322232223ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x147c147c147c147cULL, 0x147c147c147c147cULL, },
+        { 0xeb85eb85eb85eb85ULL, 0xeb85eb85eb85eb85ULL, },
+        { 0x0b61e93e2d840b61ULL, 0xe93e2d840b61e93eULL, },
+        { 0xf49f16c2d27cf49fULL, 0x16c2d27cf49f16c2ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xeb85eb85eb85eb85ULL, 0xeb85eb85eb85eb85ULL, },
+        { 0x147b147b147b147bULL, 0x147b147b147b147bULL, },
+        { 0xf49f16c1d27df49fULL, 0x16c1d27df49f16c1ULL, },
+        { 0x0b60e93e2d830b60ULL, 0xe93e2d830b60e93eULL, },
+        { 0x0000000000010000ULL, 0x0000000100000000ULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x12f7da134bdb12f7ULL, 0xda134bdb12f7da13ULL, },
+        { 0xed0925edb426ed09ULL, 0x25edb426ed0925edULL, },
+        { 0x0b61e93e2d840b61ULL, 0xe93e2d840b61e93eULL, },
+        { 0xf49f16c1d27df49fULL, 0x16c1d27df49f16c1ULL, },
+        { 0x0652194865240652ULL, 0x1948652406521948ULL, },
+        { 0xf9aee6b79addf9aeULL, 0xe6b79addf9aee6b7ULL, },
+        { 0x00000000ffff0000ULL, 0x0000ffff00000000ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xed0a25eeb425ed0aULL, 0x25eeb425ed0a25eeULL, },
+        { 0x12f6da134bda12f6ULL, 0xda134bda12f6da13ULL, },
+        { 0xf49f16c2d27cf49fULL, 0x16c2d27cf49f16c2ULL, },
+        { 0x0b60e93e2d830b60ULL, 0xe93e2d830b60e93eULL, },
+        { 0xf9aee6b79addf9aeULL, 0xe6b79addf9aee6b7ULL, },
+        { 0x0652194965230652ULL, 0x1949652306521949ULL, },
+        { 0x6fba04f60cbe38c7ULL, 0x2c6b0102000531f1ULL, },    /*  64  */
+        { 0x03faffed1879da0fULL, 0x0b2cf9e2ffbfcc2aULL, },
+        { 0x4e261004e9dbb269ULL, 0x1779faf00102e8d7ULL, },
+        { 0x9713fb9c1db7ec39ULL, 0xbccff56b01081259ULL, },
+        { 0x03faffed1879da0fULL, 0x0b2cf9e2ffbfcc2aULL, },
+        { 0x002400002f04195bULL, 0x02cf2516038735cdULL, },
+        { 0x02c8ffc1d57633daULL, 0x05e71eaff1eb180aULL, },
+        { 0xfc44001139160d37ULL, 0xef1a4023f19aecf5ULL, },
+        { 0x4e261004e9dbb269ULL, 0x1779faf00102e8d7ULL, },    /*  72  */
+        { 0x02c8ffc1d57633daULL, 0x05e71eaff1eb180aULL, },
+        { 0x36aa33af267e6a09ULL, 0x0c67196338390abeULL, },
+        { 0xb69bf1d4cc591b07ULL, 0xdc7f3511397df77eULL, },
+        { 0x9713fb9c1db7ec39ULL, 0xbccff56b01081259ULL, },
+        { 0xfc44001139160d37ULL, 0xef1a4023f19aecf5ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULR_Q_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULR_Q_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_w.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_w.c
new file mode 100644
index 0000000..f28b0d0
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulr_q_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MULR_Q.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MULR_Q.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },
+        { 0x00000000ffffffffULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e38e3a38e38e3aULL, 0x38e38e3a38e38e3aULL, },
+        { 0xc71c71c7c71c71c7ULL, 0xc71c71c7c71c71c7ULL, },
+        { 0x2222222322222223ULL, 0x2222222322222223ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x12f684be4bda12f7ULL, 0xda12f68512f684beULL, },
+        { 0xed097b43b425ed09ULL, 0x25ed097ced097b43ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c7c71c71c7ULL, 0xc71c71c7c71c71c7ULL, },
+        { 0x38e38e3838e38e38ULL, 0x38e38e3838e38e38ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xed097b42b425ed0aULL, 0x25ed097bed097b42ULL, },
+        { 0x12f684bd4bda12f6ULL, 0xda12f68512f684bdULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222222322222223ULL, 0x2222222322222223ULL, },
+        { 0xddddddddddddddddULL, 0xddddddddddddddddULL, },
+        { 0x147ae148147ae148ULL, 0x147ae148147ae148ULL, },
+        { 0xeb851eb8eb851eb8ULL, 0xeb851eb8eb851eb8ULL, },
+        { 0x0b60b60c2d82d82eULL, 0xe93e93e90b60b60cULL, },
+        { 0xf49f49f5d27d27d2ULL, 0x16c16c17f49f49f5ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0xeb851eb8eb851eb8ULL, 0xeb851eb8eb851eb8ULL, },
+        { 0x147ae148147ae148ULL, 0x147ae148147ae148ULL, },
+        { 0xf49f49f4d27d27d3ULL, 0x16c16c16f49f49f4ULL, },
+        { 0x0b60b60b2d82d82dULL, 0xe93e93e90b60b60bULL, },
+        { 0x0000000000000001ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x12f684be4bda12f7ULL, 0xda12f68512f684beULL, },
+        { 0xed097b42b425ed0aULL, 0x25ed097bed097b42ULL, },
+        { 0x0b60b60c2d82d82eULL, 0xe93e93e90b60b60cULL, },
+        { 0xf49f49f4d27d27d3ULL, 0x16c16c16f49f49f4ULL, },
+        { 0x06522c3f6522c3f4ULL, 0x1948b0fc06522c3fULL, },
+        { 0xf9add3c19add3c0dULL, 0xe6b74f04f9add3c1ULL, },
+        { 0x00000000ffffffffULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xed097b43b425ed09ULL, 0x25ed097ced097b43ULL, },
+        { 0x12f684bd4bda12f6ULL, 0xda12f68512f684bdULL, },
+        { 0xf49f49f5d27d27d2ULL, 0x16c16c17f49f49f5ULL, },
+        { 0x0b60b60b2d82d82dULL, 0xe93e93e90b60b60bULL, },
+        { 0xf9add3c19add3c0dULL, 0xe6b74f04f9add3c1ULL, },
+        { 0x06522c3f6522c3f2ULL, 0x1948b0fd06522c3fULL, },
+        { 0x6fb7e8890cbdc0d3ULL, 0x2c6b144600049a05ULL, },    /*  64  */
+        { 0x03fa514e1879c702ULL, 0x0b2c6ca9ffbf8ac7ULL, },
+        { 0x4e252087e9daefc0ULL, 0x1779189301015a35ULL, },
+        { 0x9713a7171db7f3a6ULL, 0xbccfb46a0107236fULL, },
+        { 0x03fa514e1879c702ULL, 0x0b2c6ca9ffbf8ac7ULL, },
+        { 0x002442012f047612ULL, 0x02cf8c140386e68fULL, },
+        { 0x02c84b88d575d121ULL, 0x05e79a8bf1eb1c52ULL, },
+        { 0xfc439edd3916c1e4ULL, 0xef19389cf19a0fdeULL, },
+        { 0x4e252087e9daefc0ULL, 0x1779189301015a35ULL, },    /*  72  */
+        { 0x02c84b88d575d121ULL, 0x05e79a8bf1eb1c52ULL, },
+        { 0x36a93aff267d11c4ULL, 0x0c6788643838c14cULL, },
+        { 0xb69baa3acc590fcdULL, 0xdc7e6df7397c58daULL, },
+        { 0x9713a7171db7f3a6ULL, 0xbccfb46a0107236fULL, },
+        { 0xfc439edd3916c1e4ULL, 0xef19389cf19a0fdeULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULR_Q_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULR_Q_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_b.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_b.c
new file mode 100644
index 0000000..6beeda9
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MULV.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MULV.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xe4e4e4e4e4e4e4e4ULL, 0xe4e4e4e4e4e4e4e4ULL, },
+        { 0x7272727272727272ULL, 0x7272727272727272ULL, },
+        { 0x7878787878787878ULL, 0x7878787878787878ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0xbe4c30be4c30be4cULL, 0x30be4c30be4c30beULL, },
+        { 0x980a26980a26980aULL, 0x26980a26980a2698ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7272727272727272ULL, 0x7272727272727272ULL, },
+        { 0x3939393939393939ULL, 0x3939393939393939ULL, },
+        { 0xbcbcbcbcbcbcbcbcULL, 0xbcbcbcbcbcbcbcbcULL, },
+        { 0xefefefefefefefefULL, 0xefefefefefefefefULL, },
+        { 0x5f26985f26985f26ULL, 0x985f26985f26985fULL, },
+        { 0x4c85134c85134c85ULL, 0x134c85134c85134cULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7878787878787878ULL, 0x7878787878787878ULL, },
+        { 0xbcbcbcbcbcbcbcbcULL, 0xbcbcbcbcbcbcbcbcULL, },
+        { 0x9090909090909090ULL, 0x9090909090909090ULL, },
+        { 0xa4a4a4a4a4a4a4a4ULL, 0xa4a4a4a4a4a4a4a4ULL, },
+        { 0xe428a0e428a0e428ULL, 0xa0e428a0e428a0e4ULL, },
+        { 0x500c94500c94500cULL, 0x94500c94500c9450ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0xefefefefefefefefULL, 0xefefefefefefefefULL, },
+        { 0xa4a4a4a4a4a4a4a4ULL, 0xa4a4a4a4a4a4a4a4ULL, },
+        { 0x2929292929292929ULL, 0x2929292929292929ULL, },
+        { 0x394a28394a28394aULL, 0x28394a28394a2839ULL, },
+        { 0x9483a59483a59483ULL, 0xa59483a59483a594ULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xbe4c30be4c30be4cULL, 0x30be4c30be4c30beULL, },
+        { 0x5f26985f26985f26ULL, 0x985f26985f26985fULL, },
+        { 0xe428a0e428a0e428ULL, 0xa0e428a0e428a0e4ULL, },
+        { 0x394a28394a28394aULL, 0x28394a28394a2839ULL, },
+        { 0x49c44049c44049c4ULL, 0x4049c44049c44049ULL, },
+        { 0xd4ae88d4ae88d4aeULL, 0x88d4ae88d4ae88d4ULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x980a26980a26980aULL, 0x26980a26980a2698ULL, },
+        { 0x4c85134c85134c85ULL, 0x134c85134c85134cULL, },
+        { 0x500c94500c94500cULL, 0x94500c94500c9450ULL, },
+        { 0x9483a59483a59483ULL, 0xa59483a59483a594ULL, },
+        { 0xd4ae88d4ae88d4aeULL, 0x88d4ae88d4ae88d4ULL, },
+        { 0x10e1b110e1b110e1ULL, 0xb110e1b110e1b110ULL, },
+        { 0x40e4a49040843900ULL, 0xf971798404190090ULL, },    /*  64  */
+        { 0x58ac00e408461300ULL, 0x4661098cd64560d0ULL, },
+        { 0x60445478e83e2700ULL, 0x6de882a2aaa970f0ULL, },
+        { 0x80b6c45cb0c20a80ULL, 0x4ff7d850aeb66080ULL, },
+        { 0x58ac00e408461300ULL, 0x4661098cd64560d0ULL, },
+        { 0x190400492969b140ULL, 0x445199a4b9814410ULL, },
+        { 0xa4cc00bea5dd0d00ULL, 0xbe68a2e60795dab0ULL, },
+        { 0xd0a200c74623ae70ULL, 0xea8758f0dd3e6480ULL, },
+        { 0x60445478e83e2700ULL, 0x6de882a2aaa970f0ULL, },    /*  72  */
+        { 0xa4cc00bea5dd0d00ULL, 0xbe68a2e60795dab0ULL, },
+        { 0x90a444e4b1617900ULL, 0xf140240139395990ULL, },
+        { 0x40c6f422ee9fb600ULL, 0x7b583028e316aa80ULL, },
+        { 0x80b6c45cb0c20a80ULL, 0x4ff7d850aeb66080ULL, },
+        { 0xd0a200c74623ae70ULL, 0xea8758f0dd3e6480ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_d.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_d.c
new file mode 100644
index 0000000..3205d4b
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MULV.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MULV.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x38e38e38e38e38e4ULL, },
+        { 0x1c71c71c71c71c72ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x7777777777777778ULL, 0x7777777777777778ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x12f684bda12f684cULL, 0x2f684bda12f684beULL, },
+        { 0x425ed097b425ed0aULL, 0x25ed097b425ed098ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71c71c71c72ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x8e38e38e38e38e39ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xbbbbbbbbbbbbbbbcULL, 0xbbbbbbbbbbbbbbbcULL, },
+        { 0xeeeeeeeeeeeeeeefULL, 0xeeeeeeeeeeeeeeefULL, },
+        { 0x097b425ed097b426ULL, 0x97b425ed097b425fULL, },
+        { 0xa12f684bda12f685ULL, 0x12f684bda12f684cULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7777777777777778ULL, 0x7777777777777778ULL, },
+        { 0xbbbbbbbbbbbbbbbcULL, 0xbbbbbbbbbbbbbbbcULL, },
+        { 0xf5c28f5c28f5c290ULL, 0xf5c28f5c28f5c290ULL, },
+        { 0x3d70a3d70a3d70a4ULL, 0x3d70a3d70a3d70a4ULL, },
+        { 0x7d27d27d27d27d28ULL, 0x38e38e38e38e38e4ULL, },
+        { 0xb60b60b60b60b60cULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0xeeeeeeeeeeeeeeefULL, 0xeeeeeeeeeeeeeeefULL, },
+        { 0x3d70a3d70a3d70a4ULL, 0x3d70a3d70a3d70a4ULL, },
+        { 0x8f5c28f5c28f5c29ULL, 0x8f5c28f5c28f5c29ULL, },
+        { 0x9f49f49f49f49f4aULL, 0x8e38e38e38e38e39ULL, },
+        { 0x2d82d82d82d82d83ULL, 0x3e93e93e93e93e94ULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x12f684bda12f684cULL, 0x2f684bda12f684beULL, },
+        { 0x097b425ed097b426ULL, 0x97b425ed097b425fULL, },
+        { 0x7d27d27d27d27d28ULL, 0x38e38e38e38e38e4ULL, },
+        { 0x9f49f49f49f49f4aULL, 0x8e38e38e38e38e39ULL, },
+        { 0xb0fcd6e9e06522c4ULL, 0x522c3f35ba781949ULL, },
+        { 0x6b74f0329161f9aeULL, 0x74f0329161f9add4ULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x425ed097b425ed0aULL, 0x25ed097b425ed098ULL, },
+        { 0xa12f684bda12f685ULL, 0x12f684bda12f684cULL, },
+        { 0xb60b60b60b60b60cULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0x2d82d82d82d82d83ULL, 0x3e93e93e93e93e94ULL, },
+        { 0x6b74f0329161f9aeULL, 0x74f0329161f9add4ULL, },
+        { 0x781948b0fcd6e9e1ULL, 0xc3f35ba781948b10ULL, },
+        { 0xad45be6961639000ULL, 0x3297fdea74988090ULL, },    /*  64  */
+        { 0xefa7a5a0e7176a00ULL, 0xb8110a1f6f1923d0ULL, },
+        { 0x08c6139fc4346000ULL, 0xab209f86581f7cf0ULL, },
+        { 0xfbe1883aee787980ULL, 0x821d25438dd09f80ULL, },
+        { 0xefa7a5a0e7176a00ULL, 0xb8110a1f6f1923d0ULL, },
+        { 0x37ae2b38fded7040ULL, 0x682476774aee6810ULL, },
+        { 0x6acb3d68be6cdc00ULL, 0xafdad2311444e7b0ULL, },
+        { 0xedbf72842143b470ULL, 0x7f8223caefce5580ULL, },
+        { 0x08c6139fc4346000ULL, 0xab209f86581f7cf0ULL, },    /*  72  */
+        { 0x6acb3d68be6cdc00ULL, 0xafdad2311444e7b0ULL, },
+        { 0x8624e5e1e5044000ULL, 0xd98178a63216c990ULL, },
+        { 0x76a5ab8089e38100ULL, 0xa1019a60d4dad480ULL, },
+        { 0xfbe1883aee787980ULL, 0x821d25438dd09f80ULL, },
+        { 0xedbf72842143b470ULL, 0x7f8223caefce5580ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_h.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_h.c
new file mode 100644
index 0000000..e7bd985
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MULV.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MULV.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x38e438e438e438e4ULL, 0x38e438e438e438e4ULL, },
+        { 0x1c721c721c721c72ULL, 0x1c721c721c721c72ULL, },
+        { 0x7778777877787778ULL, 0x7778777877787778ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x684c84bea130684cULL, 0x84bea130684c84beULL, },
+        { 0xed0ad098b426ed0aULL, 0xd098b426ed0ad098ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c721c721c721c72ULL, 0x1c721c721c721c72ULL, },
+        { 0x8e398e398e398e39ULL, 0x8e398e398e398e39ULL, },
+        { 0xbbbcbbbcbbbcbbbcULL, 0xbbbcbbbcbbbcbbbcULL, },
+        { 0xeeefeeefeeefeeefULL, 0xeeefeeefeeefeeefULL, },
+        { 0xb426425fd098b426ULL, 0x425fd098b426425fULL, },
+        { 0xf685684cda13f685ULL, 0x684cda13f685684cULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7778777877787778ULL, 0x7778777877787778ULL, },
+        { 0xbbbcbbbcbbbcbbbcULL, 0xbbbcbbbcbbbcbbbcULL, },
+        { 0xc290c290c290c290ULL, 0xc290c290c290c290ULL, },
+        { 0x70a470a470a470a4ULL, 0x70a470a470a470a4ULL, },
+        { 0x7d2838e4f4a07d28ULL, 0x38e4f4a07d2838e4ULL, },
+        { 0xb60cfa503e94b60cULL, 0xfa503e94b60cfa50ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0xeeefeeefeeefeeefULL, 0xeeefeeefeeefeeefULL, },
+        { 0x70a470a470a470a4ULL, 0x70a470a470a470a4ULL, },
+        { 0x5c295c295c295c29ULL, 0x5c295c295c295c29ULL, },
+        { 0x9f4a8e397d289f4aULL, 0x8e397d289f4a8e39ULL, },
+        { 0x2d833e944fa52d83ULL, 0x3e944fa52d833e94ULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x684c84bea130684cULL, 0x84bea130684c84beULL, },
+        { 0xb426425fd098b426ULL, 0x425fd098b426425fULL, },
+        { 0x7d2838e4f4a07d28ULL, 0x38e4f4a07d2838e4ULL, },
+        { 0x9f4a8e397d289f4aULL, 0x8e397d289f4a8e39ULL, },
+        { 0x22c419492c4022c4ULL, 0x19492c4022c41949ULL, },
+        { 0xf9aeadd44588f9aeULL, 0xadd44588f9aeadd4ULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xed0ad098b426ed0aULL, 0xd098b426ed0ad098ULL, },
+        { 0xf685684cda13f685ULL, 0x684cda13f685684cULL, },
+        { 0xb60cfa503e94b60cULL, 0xfa503e94b60cfa50ULL, },
+        { 0x2d833e944fa52d83ULL, 0x3e944fa52d833e94ULL, },
+        { 0xf9aeadd44588f9aeULL, 0xadd44588f9aeadd4ULL, },
+        { 0xe9e18b1048b1e9e1ULL, 0x8b1048b1e9e18b10ULL, },
+        { 0xcbe43290c5849000ULL, 0x837136844f198090ULL, },    /*  64  */
+        { 0x2cac40e4aa466a00ULL, 0xfe61d18cb74523d0ULL, },
+        { 0x2d44eb78793e6000ULL, 0x4fe806a2e7a97cf0ULL, },
+        { 0x78b6f35cb6c27980ULL, 0xb6f78750ceb69f80ULL, },
+        { 0x2cac40e4aa466a00ULL, 0xfe61d18cb74523d0ULL, },
+        { 0x21042649c2697040ULL, 0xaa51fea465816810ULL, },
+        { 0x28cc8bbef4dddc00ULL, 0xa1687ae6a695e7b0ULL, },
+        { 0xcfa29fc7d323b470ULL, 0xe587adf0113e5580ULL, },
+        { 0x2d44eb78793e6000ULL, 0x4fe806a2e7a97cf0ULL, },    /*  72  */
+        { 0x28cc8bbef4dddc00ULL, 0xa1687ae6a695e7b0ULL, },
+        { 0x0fa488e4d5614000ULL, 0x864072017939c990ULL, },
+        { 0x8fc62522929f8100ULL, 0x7a585f288416d480ULL, },
+        { 0x78b6f35cb6c27980ULL, 0xb6f78750ceb69f80ULL, },
+        { 0xcfa29fc7d323b470ULL, 0xe587adf0113e5580ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_w.c b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_w.c
new file mode 100644
index 0000000..9c318b3
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-multiply/test_msa_mulv_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction MULV.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "MULV.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*   0  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },    /*  16  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xe38e38e4e38e38e4ULL, 0xe38e38e4e38e38e4ULL, },
+        { 0x71c71c7271c71c72ULL, 0x71c71c7271c71c72ULL, },
+        { 0x7777777877777778ULL, 0x7777777877777778ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x12f684bea12f684cULL, 0x84bda13012f684beULL, },
+        { 0x425ed098b425ed0aULL, 0xd097b426425ed098ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },    /*  24  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x71c71c7271c71c72ULL, 0x71c71c7271c71c72ULL, },
+        { 0x38e38e3938e38e39ULL, 0x38e38e3938e38e39ULL, },
+        { 0xbbbbbbbcbbbbbbbcULL, 0xbbbbbbbcbbbbbbbcULL, },
+        { 0xeeeeeeefeeeeeeefULL, 0xeeeeeeefeeeeeeefULL, },
+        { 0x097b425fd097b426ULL, 0x425ed098097b425fULL, },
+        { 0xa12f684cda12f685ULL, 0x684bda13a12f684cULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },    /*  32  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7777777877777778ULL, 0x7777777877777778ULL, },
+        { 0xbbbbbbbcbbbbbbbcULL, 0xbbbbbbbcbbbbbbbcULL, },
+        { 0x28f5c29028f5c290ULL, 0x28f5c29028f5c290ULL, },
+        { 0x0a3d70a40a3d70a4ULL, 0x0a3d70a40a3d70a4ULL, },
+        { 0xe38e38e427d27d28ULL, 0x9f49f4a0e38e38e4ULL, },
+        { 0x4fa4fa500b60b60cULL, 0x93e93e944fa4fa50ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },    /*  40  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0xeeeeeeefeeeeeeefULL, 0xeeeeeeefeeeeeeefULL, },
+        { 0x0a3d70a40a3d70a4ULL, 0x0a3d70a40a3d70a4ULL, },
+        { 0xc28f5c29c28f5c29ULL, 0xc28f5c29c28f5c29ULL, },
+        { 0x38e38e3949f49f4aULL, 0x27d27d2838e38e39ULL, },
+        { 0x93e93e9482d82d83ULL, 0xa4fa4fa593e93e94ULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },    /*  48  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x12f684bea12f684cULL, 0x84bda13012f684beULL, },
+        { 0x097b425fd097b426ULL, 0x425ed098097b425fULL, },
+        { 0xe38e38e427d27d28ULL, 0x9f49f4a0e38e38e4ULL, },
+        { 0x38e38e3949f49f4aULL, 0x27d27d2838e38e39ULL, },
+        { 0xba781949e06522c4ULL, 0x06522c40ba781949ULL, },
+        { 0x61f9add49161f9aeULL, 0xc0ca458861f9add4ULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },    /*  56  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x425ed098b425ed0aULL, 0xd097b426425ed098ULL, },
+        { 0xa12f684cda12f685ULL, 0x684bda13a12f684cULL, },
+        { 0x4fa4fa500b60b60cULL, 0x93e93e944fa4fa50ULL, },
+        { 0x93e93e9482d82d83ULL, 0xa4fa4fa593e93e94ULL, },
+        { 0x61f9add49161f9aeULL, 0xc0ca458861f9add4ULL, },
+        { 0x81948b10fcd6e9e1ULL, 0x781948b181948b10ULL, },
+        { 0xb103329061639000ULL, 0x3a25368474988090ULL, },    /*  64  */
+        { 0x10bf40e4e7176a00ULL, 0x8176d18c6f1923d0ULL, },
+        { 0x7393eb78c4346000ULL, 0xb7bf06a2581f7cf0ULL, },
+        { 0xb0f0f35cee787980ULL, 0xd67987508dd09f80ULL, },
+        { 0x10bf40e4e7176a00ULL, 0x8176d18c6f1923d0ULL, },
+        { 0xb4f42649fded7040ULL, 0x3ceafea44aee6810ULL, },
+        { 0xf73d8bbebe6cdc00ULL, 0x53697ae61444e7b0ULL, },
+        { 0x7abb9fc72143b470ULL, 0x11e5adf0efce5580ULL, },
+        { 0x7393eb78c4346000ULL, 0xb7bf06a2581f7cf0ULL, },    /*  72  */
+        { 0xf73d8bbebe6cdc00ULL, 0x53697ae61444e7b0ULL, },
+        { 0xb6b388e4e5044000ULL, 0x1aff72013216c990ULL, },
+        { 0xe8bf252289e38100ULL, 0x91ae5f28d4dad480ULL, },
+        { 0xb0f0f35cee787980ULL, 0xd67987508dd09f80ULL, },
+        { 0x7abb9fc72143b470ULL, 0x11e5adf0efce5580ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_MULV_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_b.c
new file mode 100644
index 0000000..04e6159
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_S.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_S.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0xc71c80c71c80c71cULL, 0x80c71c80c71c80c7ULL, },
+        { 0x8e80e38e80e38e80ULL, 0xe38e80e38e80e38eULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x727f1d727f1d727fULL, 0x1d727f1d727f1d72ULL, },
+        { 0x39e47f39e47f39e4ULL, 0x7f39e47f39e47f39ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e94e93e94e93eULL, 0x94e93e94e93e94e9ULL, },
+        { 0xb08005b08005b080ULL, 0x05b08005b08005b0ULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0x6767676767676767ULL, 0x6767676767676767ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x507ffb507ffb507fULL, 0xfb507ffb507ffb50ULL, },
+        { 0x17c26c17c26c17c2ULL, 0x6c17c26c17c26c17ULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x39e47f39e47f39e4ULL, 0x7f39e47f39e47f39ULL, },
+        { 0x8e80e38e80e38e80ULL, 0xe38e80e38e80e38eULL, },
+        { 0x17c26c17c26c17c2ULL, 0x6c17c26c17c26c17ULL, },
+        { 0xb08005b08005b080ULL, 0x05b08005b08005b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc78071c78071c780ULL, 0x71c78071c78071c7ULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x727f1d727f1d727fULL, 0x1d727f1d727f1d72ULL, },
+        { 0xc71c80c71c80c71cULL, 0x80c71c80c71c80c7ULL, },
+        { 0x507ffb507ffb507fULL, 0xfb507ffb507ffb50ULL, },
+        { 0xe93e94e93e94e93eULL, 0x94e93e94e93e94e9ULL, },
+        { 0x397f8f397f8f397fULL, 0x8f397f8f397f8f39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8d7fe680db7f7f38ULL, 0x39705044e93c8010ULL, },
+        { 0xdc1038226f7f7f7fULL, 0x247f455f53508bf8ULL, },
+        { 0x801bd080ca3173f2ULL, 0x7f767f7f5539ce6cULL, },
+        { 0x73801a7f258080c8ULL, 0xc790b0bc17c47ff0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f80527f7fc43c7fULL, 0xeb1ff51b6a142de8ULL, },
+        { 0x8b80ea16ef80e5baULL, 0x7f0633426cfd705cULL, },
+        { 0x24f0c8de91808080ULL, 0xdc80bba1adb07508ULL, },    /*  72  */
+        { 0xb17fae80803cc480ULL, 0x15e10be596ecd318ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x800b9880809ea980ULL, 0x7fe73e2702e94374ULL, },
+        { 0x7fe5307f36cf8d0eULL, 0x808a8080abc73294ULL, },
+        { 0x757f16ea117f1b46ULL, 0x80facdbe940390a4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_d.c
new file mode 100644
index 0000000..195137f
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_S.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_S.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0xc71c71c71c71c71cULL, 0x8000000000000000ULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x7fffffffffffffffULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e93e93e93e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x6666666666666667ULL, 0x6666666666666667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa4fa4fa4fa4fa5ULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x7fffffffffffffffULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c71c71c71dULL, 0x71c71c71c71c71c7ULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0xc71c71c71c71c71cULL, 0x8000000000000000ULL, },
+        { 0x4fa4fa4fa4fa4fa5ULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e93e93e93e9ULL, },
+        { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace668dace8e38ULL, 0x386f5044e93c5d10ULL, },
+        { 0xdc1038216e92c9c0ULL, 0x238e445f53508af8ULL, },
+        { 0x8000000000000000ULL, 0x7fffffffffffffffULL, },
+        { 0x73531997253171c8ULL, 0xc790afbb16c3a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b893c43b88ULL, 0xeb1ef41a6a142de8ULL, },
+        { 0x8b6eea15ef61e4baULL, 0x7fffffffffffffffULL, },
+        { 0x23efc7de916d3640ULL, 0xdc71bba0acaf7508ULL, },    /*  72  */
+        { 0xb09cae476c3bc478ULL, 0x14e10be595ebd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000000000000000ULL, 0x7fffffffffffffffULL, },
+        { 0x7fffffffffffffffULL, 0x8000000000000000ULL, },
+        { 0x749115ea109e1b46ULL, 0x8000000000000000ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_h.c
new file mode 100644
index 0000000..c57238d
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_S.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_S.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0xc71c80001c72c71cULL, 0x80001c72c71c8000ULL, },
+        { 0x8e39e38e80008e39ULL, 0xe38e80008e39e38eULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c727fff71c7ULL, 0x1c727fff71c71c72ULL, },
+        { 0x38e47fffe38e38e4ULL, 0x7fffe38e38e47fffULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e93e94e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0xb05b05b08000b05bULL, 0x05b08000b05b05b0ULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x6667666766676667ULL, 0x6667666766676667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa5fa507fff4fa5ULL, 0xfa507fff4fa5fa50ULL, },
+        { 0x16c26c17c16c16c2ULL, 0x6c17c16c16c26c17ULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e47fffe38e38e4ULL, 0x7fffe38e38e47fffULL, },
+        { 0x8e39e38e80008e39ULL, 0xe38e80008e39e38eULL, },
+        { 0x16c26c17c16c16c2ULL, 0x6c17c16c16c26c17ULL, },
+        { 0xb05b05b08000b05bULL, 0x05b08000b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71d71c78000c71dULL, 0x71c78000c71d71c7ULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c727fff71c7ULL, 0x1c727fff71c71c72ULL, },
+        { 0xc71c80001c72c71cULL, 0x80001c72c71c8000ULL, },
+        { 0x4fa5fa507fff4fa5ULL, 0xfa507fff4fa5fa50ULL, },
+        { 0xe93e93e93e94e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0x38e38e397fff38e3ULL, 0x8e397fff38e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace669dacf7fffULL, 0x38705044e93c8000ULL, },
+        { 0xdc1038226e937fffULL, 0x238f445f53508af8ULL, },
+        { 0x8000d07fca3172f2ULL, 0x7fff7fff5539cd6cULL, },
+        { 0x7354199725318000ULL, 0xc790afbc16c47fffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6451b97fff3b88ULL, 0xeb1ff41b6a142de8ULL, },
+        { 0x8b6fea16ef62e4baULL, 0x7fff32426bfd705cULL, },
+        { 0x23f0c7de916d8000ULL, 0xdc71bba1acb07508ULL, },    /*  72  */
+        { 0xb09cae478000c478ULL, 0x14e10be595ecd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000985d8000a932ULL, 0x7fff3e2701e94274ULL, },
+        { 0x7fff2f8135cf8d0eULL, 0x80008000aac73294ULL, },
+        { 0x749115ea109e1b46ULL, 0x8000cdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_w.c
new file mode 100644
index 0000000..1cded65
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_s_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_S.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_S.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0xc71c71c71c71c71cULL, 0x80000000c71c71c7ULL, },
+        { 0x8e38e38e80000000ULL, 0xe38e38e38e38e38eULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c727fffffffULL, 0x1c71c71d71c71c72ULL, },
+        { 0x38e38e39e38e38e4ULL, 0x7fffffff38e38e39ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0xb05b05b080000000ULL, 0x05b05b05b05b05b0ULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x6666666766666667ULL, 0x6666666766666667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa4fa507fffffffULL, 0xfa4fa4fb4fa4fa50ULL, },
+        { 0x16c16c17c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e38e39e38e38e4ULL, 0x7fffffff38e38e39ULL, },
+        { 0x8e38e38e80000000ULL, 0xe38e38e38e38e38eULL, },
+        { 0x16c16c17c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xb05b05b080000000ULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c780000000ULL, 0x71c71c71c71c71c7ULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c727fffffffULL, 0x1c71c71d71c71c72ULL, },
+        { 0xc71c71c71c71c71cULL, 0x80000000c71c71c7ULL, },
+        { 0x4fa4fa507fffffffULL, 0xfa4fa4fb4fa4fa50ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0x38e38e397fffffffULL, 0x8e38e38f38e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace669dace8e38ULL, 0x386f5044e93c5d10ULL, },
+        { 0xdc1038226e92c9c0ULL, 0x238e445f53508af8ULL, },
+        { 0x80000000ca3072f2ULL, 0x7fffffff5538cd6cULL, },
+        { 0x73531997253171c8ULL, 0xc790afbc16c3a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b97fffffffULL, 0xeb1ef41b6a142de8ULL, },
+        { 0x8b6eea16ef61e4baULL, 0x7fffffff6bfc705cULL, },
+        { 0x23efc7de916d3640ULL, 0xdc71bba1acaf7508ULL, },    /*  72  */
+        { 0xb09cae4780000000ULL, 0x14e10be595ebd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000000080000000ULL, 0x7fffffff01e84274ULL, },
+        { 0x7fffffff35cf8d0eULL, 0x80000000aac73294ULL, },
+        { 0x749115ea109e1b46ULL, 0x8000000094038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_S_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_b.c
new file mode 100644
index 0000000..cb38f03
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_U.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_U.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x001c72001c72001cULL, 0x72001c72001c7200ULL, },
+        { 0x8e39008e39008e39ULL, 0x008e39008e39008eULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x00001d00001d0000ULL, 0x1d00001d00001d00ULL, },
+        { 0x3900003900003900ULL, 0x0039000039000039ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0x003e94003e94003eULL, 0x94003e94003e9400ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1700001700001700ULL, 0x0017000017000017ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x3900003900003900ULL, 0x0039000039000039ULL, },
+        { 0x8e39008e39008e39ULL, 0x008e39008e39008eULL, },
+        { 0x1700001700001700ULL, 0x0017000017000017ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71d00c71d00c71dULL, 0x00c71d00c71d00c7ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x00001d00001d0000ULL, 0x1d00001d00001d00ULL, },
+        { 0x001c72001c72001cULL, 0x72001c72001c7200ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x003e94003e94003eULL, 0x94003e94003e9400ULL, },
+        { 0x00008f00008f0000ULL, 0x8f00008f00008f00ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x0000e66900000038ULL, 0x39000044e93c5e00ULL, },
+        { 0x0010382200000000ULL, 0x2400000053508b00ULL, },
+        { 0x181bd07f00310000ULL, 0x0000000055390000ULL, },
+        { 0x7354000025317200ULL, 0x0090b000000000f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f64000000003c00ULL, 0x001f000000142de8ULL, },
+        { 0x8b6f001600620000ULL, 0x000633000000005cULL, },
+        { 0x24000000916d3640ULL, 0x0071bba100000008ULL, },    /*  72  */
+        { 0x0000ae476c3c0078ULL, 0x15000be596000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9e0032ULL, 0x00003e2702000000ULL, },
+        { 0x0000000036008d0eULL, 0x428a7d7a00003294ULL, },
+        { 0x0000160011001b46ULL, 0x7b0000be94039000ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_d.c
new file mode 100644
index 0000000..2685b2f
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_U.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_U.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x71c71c71c71c71c7ULL, },
+        { 0x8e38e38e38e38e39ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x0000000000000000ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0x0000000000000000ULL, 0x93e93e93e93e93e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x16c16c16c16c16c2ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x0000000000000000ULL, },
+        { 0x8e38e38e38e38e39ULL, 0x0000000000000000ULL, },
+        { 0x16c16c16c16c16c2ULL, 0x0000000000000000ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c71c71c71dULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x0000000000000000ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x0000000000000000ULL, 0x71c71c71c71c71c7ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x93e93e93e93e93e9ULL, },
+        { 0x0000000000000000ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x0000000000000000ULL, 0x386f5044e93c5d10ULL, },
+        { 0x0000000000000000ULL, 0x238e445f53508af8ULL, },
+        { 0x181bd07eca3072f2ULL, 0x0000000000000000ULL, },
+        { 0x73531997253171c8ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b893c43b88ULL, 0x0000000000000000ULL, },
+        { 0x8b6eea15ef61e4baULL, 0x0000000000000000ULL, },
+        { 0x23efc7de916d3640ULL, 0x0000000000000000ULL, },    /*  72  */
+        { 0x0000000000000000ULL, 0x14e10be595ebd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9da932ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x428a7d79aac73294ULL, },
+        { 0x0000000000000000ULL, 0x7af9cdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_h.c
new file mode 100644
index 0000000..ca6dd38
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_U.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_U.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x000071c71c720000ULL, 0x71c71c72000071c7ULL, },
+        { 0x8e39000038e38e39ULL, 0x000038e38e390000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x00001c7200000000ULL, 0x1c72000000001c72ULL, },
+        { 0x38e40000000038e4ULL, 0x0000000038e40000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0x000093e93e940000ULL, 0x93e93e94000093e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x16c20000000016c2ULL, 0x0000000016c20000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e40000000038e4ULL, 0x0000000038e40000ULL, },
+        { 0x8e39000038e38e39ULL, 0x000038e38e390000ULL, },
+        { 0x16c20000000016c2ULL, 0x0000000016c20000ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71d00001c71c71dULL, 0x00001c71c71d0000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x00001c7200000000ULL, 0x1c72000000001c72ULL, },
+        { 0x000071c71c720000ULL, 0x71c71c72000071c7ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x000093e93e940000ULL, 0x93e93e94000093e9ULL, },
+        { 0x00008e3900000000ULL, 0x8e39000000008e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x0000e66900000000ULL, 0x38700000e93c5d10ULL, },
+        { 0x0000382200000000ULL, 0x238f000053508af8ULL, },
+        { 0x181bd07f00000000ULL, 0x0000000055390000ULL, },
+        { 0x73540000253171c8ULL, 0x0000afbc00000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f64000000003b88ULL, 0x0000000000002de8ULL, },
+        { 0x8b6f000000000000ULL, 0x0000324200000000ULL, },
+        { 0x23f00000916d3640ULL, 0x0000bba100000000ULL, },    /*  72  */
+        { 0x0000ae476c3c0000ULL, 0x14e10be595ec0000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9e0000ULL, 0x00003e2701e90000ULL, },
+        { 0x0000000035cf8d0eULL, 0x428a7d7a00003294ULL, },
+        { 0x000015ea109e1b46ULL, 0x7afa000094038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_w.c
new file mode 100644
index 0000000..42ebddb
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subs_u_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBS_U.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBS_U.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x000000001c71c71cULL, 0x71c71c7200000000ULL, },
+        { 0x8e38e38e38e38e39ULL, 0x000000008e38e38eULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x0000000000000000ULL, 0x1c71c71d00000000ULL, },
+        { 0x38e38e3900000000ULL, 0x0000000038e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0x000000003e93e93eULL, 0x93e93e9400000000ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x16c16c1700000000ULL, 0x0000000016c16c17ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e38e3900000000ULL, 0x0000000038e38e39ULL, },
+        { 0x8e38e38e38e38e39ULL, 0x000000008e38e38eULL, },
+        { 0x16c16c1700000000ULL, 0x0000000016c16c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c71c71c71dULL, 0x00000000c71c71c7ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x0000000000000000ULL, 0x1c71c71d00000000ULL, },
+        { 0x000000001c71c71cULL, 0x71c71c7200000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x000000003e93e93eULL, 0x93e93e9400000000ULL, },
+        { 0x0000000000000000ULL, 0x8e38e38f00000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x0000000000000000ULL, 0x386f5044e93c5d10ULL, },
+        { 0x0000000000000000ULL, 0x238e445f53508af8ULL, },
+        { 0x181bd07f00000000ULL, 0x000000005538cd6cULL, },
+        { 0x73531997253171c8ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b900000000ULL, 0x0000000000000000ULL, },
+        { 0x8b6eea1600000000ULL, 0x0000000000000000ULL, },
+        { 0x23efc7de916d3640ULL, 0x0000000000000000ULL, },    /*  72  */
+        { 0x000000006c3bc478ULL, 0x14e10be595ebd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9da932ULL, 0x0000000001e84274ULL, },
+        { 0x0000000035cf8d0eULL, 0x428a7d7a00000000ULL, },
+        { 0x00000000109e1b46ULL, 0x7af9cdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBS_U_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_b.c
new file mode 100644
index 0000000..dac20cc
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUS_U.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUS_U.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffc7ffffc7ffffULL, 0xc7ffffc7ffffc7ffULL, },
+        { 0xe38effe38effe38eULL, 0xffe38effe38effe3ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1d72001d72001d72ULL, 0x001d72001d72001dULL, },
+        { 0x0000390000390000ULL, 0x3900003900003900ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc7ff72c7ff72c7ffULL, 0x72c7ff72c7ff72c7ULL, },
+        { 0x8e39e38e39e38e39ULL, 0xe38e39e38e39e38eULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x72c71d72c71d72c7ULL, 0x1d72c71d72c71d72ULL, },
+        { 0x39008e39008e3900ULL, 0x8e39008e39008e39ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe9ff94e9ff94e9ffULL, 0x94e9ff94e9ff94e9ULL, },
+        { 0xb05bffb05bffb05bULL, 0xffb05bffb05bffb0ULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x6767676767676767ULL, 0x6767676767676767ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x50a50050a50050a5ULL, 0x0050a50050a50050ULL, },
+        { 0x17006c17006c1700ULL, 0x6c17006c17006c17ULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffe48effe48effe4ULL, 0x8effe48effe48effULL, },
+        { 0x8e39008e39008e39ULL, 0x008e39008e39008eULL, },
+        { 0xffc26cffc26cffc2ULL, 0x6cffc26cffc26cffULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0xffff00ffff00ffffULL, 0x00ffff00ffff00ffULL, },
+        { 0xc71d71c71d71c71dULL, 0x71c71d71c71d71c7ULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x72c7ff72c7ff72c7ULL, 0xff72c7ff72c7ff72ULL, },
+        { 0x001c72001c72001cULL, 0x72001c72001c7200ULL, },
+        { 0x50a5fb50a5fb50a5ULL, 0xfb50a5fb50a5fb50ULL, },
+        { 0x003e94003e94003eULL, 0x94003e94003e9400ULL, },
+        { 0x39e38f39e38f39e3ULL, 0x8f39e38f39e38f39ULL, },
+        { 0x0000ff0000ff0000ULL, 0xff0000ff0000ff00ULL, },
+        { 0xff00ffff00000000ULL, 0x00000000ff00ff00ULL, },    /*  64  */
+        { 0x8dace66900cf8e38ULL, 0x39705044e93c5e10ULL, },
+        { 0xdc10ffff6f93cac0ULL, 0x248f455fff508b00ULL, },
+        { 0x181bd07f00317300ULL, 0xbe768386ff39ce6cULL, },
+        { 0xff541a9725317200ULL, 0x0090b0001700a2f0ULL, },
+        { 0xffff000000ffff00ULL, 0x00ffff00000000ffULL, },
+        { 0xff6452b994c4ff88ULL, 0x00fff51b6a142de8ULL, },
+        { 0x8b6f00160062e500ULL, 0x85ffff426c0070ffULL, },
+        { 0xff00c8de916d3640ULL, 0x0071bba1ad007508ULL, },    /*  72  */
+        { 0xb19cae476cffc478ULL, 0x15e1ffe596000018ULL, },
+        { 0xff00ffffffffffffULL, 0x00ffffffff000000ULL, },
+        { 0x3c0b985d5b9ea932ULL, 0x9ae7ffffff004374ULL, },
+        { 0xe800308136008d0eULL, 0x428a7d7aab00ff94ULL, },
+        { 0x75911600119eff46ULL, 0x7bfacdbe940390a4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_d.c
new file mode 100644
index 0000000..4485502
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUS_U.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUS_U.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71c71c71c72ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x38e38e38e38e38e4ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e93e93e93e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0xffffffffffffffffULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x6666666666666667ULL, 0x6666666666666667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa4fa4fa4fa4fa5ULL, 0x0000000000000000ULL, },
+        { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffffffffffffffffULL, 0x8e38e38e38e38e39ULL, },
+        { 0x8e38e38e38e38e39ULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0x6c16c16c16c16c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0xc71c71c71c71c71dULL, 0x71c71c71c71c71c7ULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c71c71c71c7ULL, 0xffffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x71c71c71c71c71c7ULL, },
+        { 0x4fa4fa4fa4fa4fa5ULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0x0000000000000000ULL, 0x93e93e93e93e93e9ULL, },
+        { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x0000000000000000ULL, 0xffffffffffffffffULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace668dace8e38ULL, 0x386f5044e93c5d10ULL, },
+        { 0xdc1038216e92c9c0ULL, 0x238e445f53508af8ULL, },
+        { 0x181bd07eca3072f2ULL, 0xbd7582865538cd6cULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0x8b6eea15ef61e4baULL, 0x850632416bfc705cULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },    /*  72  */
+        { 0xb09cae476c3bc478ULL, 0x14e10be595ebd218ULL, },
+        { 0xffffffffffffffffULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, },
+        { 0xe7e42f8135cf8d0eULL, 0x428a7d79aac73294ULL, },
+        { 0x749115ea109e1b46ULL, 0x7af9cdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_h.c
new file mode 100644
index 0000000..9e99aee
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUS_U.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUS_U.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffc71cffffffffULL, 0xc71cffffffffc71cULL, },
+        { 0xe38effff8e38e38eULL, 0xffff8e38e38effffULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c72000071c81c72ULL, 0x000071c81c720000ULL, },
+        { 0x000038e400000000ULL, 0x38e40000000038e4ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c7ffffc71cULL, 0x71c7ffffc71c71c7ULL, },
+        { 0x8e39e38e38e38e39ULL, 0xe38e38e38e39e38eULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c72c71d71c7ULL, 0x1c72c71d71c71c72ULL, },
+        { 0x38e48e39000038e4ULL, 0x8e39000038e48e39ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e9ffffe93eULL, 0x93e9ffffe93e93e9ULL, },
+        { 0xb05bffff5b05b05bULL, 0xffff5b05b05bffffULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x6667666766676667ULL, 0x6667666766676667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa50000a4fb4fa5ULL, 0x0000a4fb4fa50000ULL, },
+        { 0x16c26c17000016c2ULL, 0x6c17000016c26c17ULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffff8e39e38effffULL, 0x8e39e38effff8e39ULL, },
+        { 0x8e39000038e38e39ULL, 0x000038e38e390000ULL, },
+        { 0xffff6c17c16cffffULL, 0x6c17c16cffff6c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0xffff0000ffffffffULL, 0x0000ffffffff0000ULL, },
+        { 0xc71d71c71c71c71dULL, 0x71c71c71c71d71c7ULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c7ffffc71d71c7ULL, 0xffffc71d71c7ffffULL, },
+        { 0x000071c71c720000ULL, 0x71c71c72000071c7ULL, },
+        { 0x4fa5fa50a4fb4fa5ULL, 0xfa50a4fb4fa5fa50ULL, },
+        { 0x000093e93e940000ULL, 0x93e93e94000093e9ULL, },
+        { 0x38e38e39e38f38e3ULL, 0x8e39e38f38e38e39ULL, },
+        { 0x0000ffff00000000ULL, 0xffff00000000ffffULL, },
+        { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },    /*  64  */
+        { 0x8cace66900008e38ULL, 0x38705044e93c5d10ULL, },
+        { 0xdc10ffff6e93c9c0ULL, 0x238f445fffff8af8ULL, },
+        { 0x181bd07f000072f2ULL, 0xbd768286ffffcd6cULL, },
+        { 0xffff1997253171c8ULL, 0x0000afbc16c4a2f0ULL, },
+        { 0xffff00000000ffffULL, 0x0000ffff00000000ULL, },
+        { 0xffff51b993c4ffffULL, 0x0000f41b6a142de8ULL, },
+        { 0x8b6f00000000e4baULL, 0x8506ffff6bfd705cULL, },
+        { 0xffffc7de916d3640ULL, 0x0000bba1acb07508ULL, },    /*  72  */
+        { 0xb09cae476c3cc478ULL, 0x14e1ffff95ec0000ULL, },
+        { 0xffffffffffffffffULL, 0x0000ffffffff0000ULL, },
+        { 0x3c0b985d5b9ea932ULL, 0x99e7ffffffff4274ULL, },
+        { 0xe7e52f8135cf8d0eULL, 0x428a7d7aaac7ffffULL, },
+        { 0x749115ea109effffULL, 0x7afacdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_w.c
new file mode 100644
index 0000000..53a9aca
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsus_u_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUS_U.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUS_U.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xc71c71c7ffffffffULL, },
+        { 0xe38e38e38e38e38eULL, 0xffffffffe38e38e3ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x1c71c71d71c71c72ULL, 0x000000001c71c71dULL, },
+        { 0x0000000000000000ULL, 0x38e38e3900000000ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c7ffffffffULL, 0x71c71c72c71c71c7ULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c72c71c71c7ULL, 0x1c71c71d71c71c72ULL, },
+        { 0x38e38e3900000000ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e9ffffffffULL, 0x93e93e94e93e93e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0xffffffffb05b05b0ULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x6666666766666667ULL, 0x6666666766666667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa4fa50a4fa4fa5ULL, 0x000000004fa4fa50ULL, },
+        { 0x16c16c1700000000ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0xffffffffe38e38e4ULL, 0x8e38e38effffffffULL, },
+        { 0x8e38e38e38e38e39ULL, 0x000000008e38e38eULL, },
+        { 0xffffffffc16c16c2ULL, 0x6c16c16cffffffffULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+        { 0xc71c71c71c71c71dULL, 0x71c71c71c71c71c7ULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c72c71c71c7ULL, 0xffffffff71c71c72ULL, },
+        { 0x000000001c71c71cULL, 0x71c71c7200000000ULL, },
+        { 0x4fa4fa50a4fa4fa5ULL, 0xfa4fa4fb4fa4fa50ULL, },
+        { 0x000000003e93e93eULL, 0x93e93e9400000000ULL, },
+        { 0x38e38e39e38e38e3ULL, 0x8e38e38f38e38e39ULL, },
+        { 0x0000000000000000ULL, 0xffffffff00000000ULL, },
+        { 0xffffffff00000000ULL, 0x00000000ffffffffULL, },    /*  64  */
+        { 0x8cace66900000000ULL, 0x386f5044e93c5d10ULL, },
+        { 0xdc1038226e92c9c0ULL, 0x238e445fffffffffULL, },
+        { 0x181bd07f00000000ULL, 0xbd758286ffffffffULL, },
+        { 0xffffffff253171c8ULL, 0x0000000016c3a2f0ULL, },
+        { 0xffffffff00000000ULL, 0x0000000000000000ULL, },
+        { 0xffffffff93c43b88ULL, 0x000000006a142de8ULL, },
+        { 0x8b6eea1600000000ULL, 0x850632426bfc705cULL, },
+        { 0xffffffff916d3640ULL, 0x00000000acaf7508ULL, },    /*  72  */
+        { 0xb09cae476c3bc478ULL, 0x14e10be595ebd218ULL, },
+        { 0xffffffffffffffffULL, 0x00000000ffffffffULL, },
+        { 0x3c0b985d5b9da932ULL, 0x99e73e27ffffffffULL, },
+        { 0xe7e42f8135cf8d0eULL, 0x428a7d7aaac73294ULL, },
+        { 0x749115ea109e1b46ULL, 0x7af9cdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUS_U_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_b.c
new file mode 100644
index 0000000..86fb4f3
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUU_S.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUU_S.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x1c717f1c717f1c71ULL, 0x7f1c717f1c717f1cULL, },
+        { 0x7f7f387f7f387f7fULL, 0x387f7f387f7f387fULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },
+        { 0x8080c88080c88080ULL, 0xc88080c88080c880ULL, },
+        { 0xe48f80e48f80e48fULL, 0x80e48f80e48f80e4ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },    /*  16  */
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c72c71c72c71cULL, 0x72c71c72c71c72c7ULL, },
+        { 0x7f39e37f39e37f39ULL, 0xe37f39e37f39e37fULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x80c71d80c71d80c7ULL, 0x1d80c71d80c71d80ULL, },
+        { 0x39e48e39e48e39e4ULL, 0x8e39e48e39e48e39ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },    /*  32  */
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7f7f7f7f7f7f7f7fULL, 0x7f7f7f7f7f7f7f7fULL, },
+        { 0xe93e7fe93e7fe93eULL, 0x7fe93e7fe93e7fe9ULL, },
+        { 0x7f5b057f5b057f5bULL, 0x057f5b057f5b057fULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0x8080808080808080ULL, 0x8080808080808080ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x80a5fb80a5fb80a5ULL, 0xfb80a5fb80a5fb80ULL, },
+        { 0x17c28017c28017c2ULL, 0x8017c28017c28017ULL, },
+        { 0xe48f80e48f80e48fULL, 0x80e48f80e48f80e4ULL, },    /*  48  */
+        { 0x7f7f387f7f387f7fULL, 0x387f7f387f7f387fULL, },
+        { 0x39e48e39e48e39e4ULL, 0x8e39e48e39e48e39ULL, },
+        { 0x7f39e37f39e37f39ULL, 0xe37f39e37f39e37fULL, },
+        { 0x17c28017c28017c2ULL, 0x8017c28017c28017ULL, },
+        { 0x7f5b057f5b057f5bULL, 0x057f5b057f5b057fULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7f1d807f1d807f1dULL, 0x807f1d807f1d807fULL, },
+        { 0x8080c88080c88080ULL, 0xc88080c88080c880ULL, },    /*  56  */
+        { 0x1c717f1c717f1c71ULL, 0x7f1c717f1c717f1cULL, },
+        { 0x80c71d80c71d80c7ULL, 0x1d80c71d80c71d80ULL, },
+        { 0xc71c72c71c72c71cULL, 0x72c71c72c71c72c7ULL, },
+        { 0x80a5fb80a5fb80a5ULL, 0xfb80a5fb80a5fb80ULL, },
+        { 0xe93e7fe93e7fe93eULL, 0x7fe93e7fe93e7fe9ULL, },
+        { 0x80e37f80e37f80e3ULL, 0x7f80e37f80e37f80ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8dac7f69dbcf8e38ULL, 0x398080447f3c5e80ULL, },
+        { 0xdc1038228093cac0ULL, 0x248f808053507ff8ULL, },
+        { 0x181b7f7fca3180f2ULL, 0xbe8083865539ce80ULL, },
+        { 0x73548097253172c8ULL, 0xc77f7fbc80c4a27fULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6480b994c43c88ULL, 0xeb1ff58080142d7fULL, },
+        { 0x7f6fea16ef62e5baULL, 0x8506338080fd805cULL, },
+        { 0x24f0c8de7f6d3640ULL, 0xdc717f7fadb08008ULL, },    /*  72  */
+        { 0xb19c7f476c3cc478ULL, 0x15e10b7f7fecd380ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b7f5d5b7fa932ULL, 0x9ae73e2702e98080ULL, },
+        { 0xe8e5808136cf7f0eULL, 0x427f7d7aabc7327fULL, },
+        { 0x809116ea119e1b46ULL, 0x7bfacd7f7f037fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_d.c
new file mode 100644
index 0000000..45a1eb3
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUU_S.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUU_S.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0x7fffffffffffffffULL, },
+        { 0x7fffffffffffffffULL, 0x38e38e38e38e38e3ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },
+        { 0x8000000000000000ULL, 0xc71c71c71c71c71dULL, },
+        { 0xe38e38e38e38e38fULL, 0x8000000000000000ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },    /*  16  */
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x7fffffffffffffffULL, 0xe38e38e38e38e38eULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x8000000000000000ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },    /*  32  */
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, },
+        { 0xe93e93e93e93e93eULL, 0x7fffffffffffffffULL, },
+        { 0x7fffffffffffffffULL, 0x05b05b05b05b05b0ULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x8000000000000000ULL, 0x8000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000000000000000ULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0x16c16c16c16c16c2ULL, 0x8000000000000000ULL, },
+        { 0xe38e38e38e38e38fULL, 0x8000000000000000ULL, },    /*  48  */
+        { 0x7fffffffffffffffULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x7fffffffffffffffULL, 0xe38e38e38e38e38eULL, },
+        { 0x16c16c16c16c16c2ULL, 0x8000000000000000ULL, },
+        { 0x7fffffffffffffffULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fffffffffffffffULL, 0x8000000000000000ULL, },
+        { 0x8000000000000000ULL, 0xc71c71c71c71c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0x7fffffffffffffffULL, },
+        { 0x8000000000000000ULL, 0x1c71c71c71c71c72ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x8000000000000000ULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0xe93e93e93e93e93eULL, 0x7fffffffffffffffULL, },
+        { 0x8000000000000000ULL, 0x7fffffffffffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace668dace8e38ULL, 0x386f5044e93c5d10ULL, },
+        { 0xdc1038216e92c9c0ULL, 0x238e445f53508af8ULL, },
+        { 0x181bd07eca3072f2ULL, 0xbd7582865538cd6cULL, },
+        { 0x73531997253171c8ULL, 0xc790afbb16c3a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b893c43b88ULL, 0xeb1ef41a6a142de8ULL, },
+        { 0x7fffffffffffffffULL, 0x850632416bfc705cULL, },
+        { 0x23efc7de916d3640ULL, 0xdc71bba0acaf7508ULL, },    /*  72  */
+        { 0xb09cae476c3bc478ULL, 0x14e10be595ebd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, },
+        { 0xe7e42f8135cf8d0eULL, 0x428a7d79aac73294ULL, },
+        { 0x8000000000000000ULL, 0x7af9cdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_h.c
new file mode 100644
index 0000000..14ac7de
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUU_S.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUU_S.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x1c717fff71c71c71ULL, 0x7fff71c71c717fffULL, },
+        { 0x7fff38e37fff7fffULL, 0x38e37fff7fff38e3ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },
+        { 0x8000c71d80008000ULL, 0xc71d80008000c71dULL, },
+        { 0xe38f80008e39e38fULL, 0x80008e39e38f8000ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },    /*  16  */
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c71c72c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x7fffe38e38e37fffULL, 0xe38e38e37fffe38eULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x80001c72c71d8000ULL, 0x1c72c71d80001c72ULL, },
+        { 0x38e48e39e38e38e4ULL, 0x8e39e38e38e48e39ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },    /*  32  */
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fff7fff7fff7fffULL, 0x7fff7fff7fff7fffULL, },
+        { 0xe93e7fff3e94e93eULL, 0x7fff3e94e93e7fffULL, },
+        { 0x7fff05b05b057fffULL, 0x05b05b057fff05b0ULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x8000800080008000ULL, 0x8000800080008000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000fa50a4fb8000ULL, 0xfa50a4fb8000fa50ULL, },
+        { 0x16c28000c16c16c2ULL, 0x8000c16c16c28000ULL, },
+        { 0xe38f80008e39e38fULL, 0x80008e39e38f8000ULL, },    /*  48  */
+        { 0x7fff38e37fff7fffULL, 0x38e37fff7fff38e3ULL, },
+        { 0x38e48e39e38e38e4ULL, 0x8e39e38e38e48e39ULL, },
+        { 0x7fffe38e38e37fffULL, 0xe38e38e37fffe38eULL, },
+        { 0x16c28000c16c16c2ULL, 0x8000c16c16c28000ULL, },
+        { 0x7fff05b05b057fffULL, 0x05b05b057fff05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fff80001c717fffULL, 0x80001c717fff8000ULL, },
+        { 0x8000c71d80008000ULL, 0xc71d80008000c71dULL, },    /*  56  */
+        { 0x1c717fff71c71c71ULL, 0x7fff71c71c717fffULL, },
+        { 0x80001c72c71d8000ULL, 0x1c72c71d80001c72ULL, },
+        { 0xc71c71c71c72c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x8000fa50a4fb8000ULL, 0xfa50a4fb8000fa50ULL, },
+        { 0xe93e7fff3e94e93eULL, 0x7fff3e94e93e7fffULL, },
+        { 0x80007fffe38f8000ULL, 0x7fffe38f80007fffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cac7fffdacf8e38ULL, 0x387080007fff5d10ULL, },
+        { 0xdc1038228000c9c0ULL, 0x238f800053507fffULL, },
+        { 0x181b7fffca318000ULL, 0xbd7682865539cd6cULL, },
+        { 0x73548000253171c8ULL, 0xc7907fff8000a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f64800093c43b88ULL, 0xeb1ff41b80002de8ULL, },
+        { 0x7fffea16ef62e4baULL, 0x8506324280008000ULL, },
+        { 0x23f0c7de7fff3640ULL, 0xdc717fffacb08000ULL, },    /*  72  */
+        { 0xb09c7fff6c3cc478ULL, 0x14e10be57fffd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b7fff5b9ea932ULL, 0x99e73e2701e98000ULL, },
+        { 0xe7e5800035cf7fffULL, 0x428a7d7aaac73294ULL, },
+        { 0x800015ea109e1b46ULL, 0x7afacdbe7fff7fffULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_w.c
new file mode 100644
index 0000000..688f469
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subsuu_s_w.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBSUU_S.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBSUU_S.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x1c71c71c71c71c71ULL, 0x7fffffff1c71c71cULL, },
+        { 0x7fffffff7fffffffULL, 0x38e38e387fffffffULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },
+        { 0x8000000080000000ULL, 0xc71c71c880000000ULL, },
+        { 0xe38e38e48e38e38fULL, 0x80000000e38e38e4ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },    /*  16  */
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x7fffffff38e38e39ULL, 0xe38e38e37fffffffULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x80000000c71c71c7ULL, 0x1c71c71d80000000ULL, },
+        { 0x38e38e39e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },    /*  32  */
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fffffff7fffffffULL, 0x7fffffff7fffffffULL, },
+        { 0xe93e93e93e93e93eULL, 0x7fffffffe93e93e9ULL, },
+        { 0x7fffffff5b05b05bULL, 0x05b05b057fffffffULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x8000000080000000ULL, 0x8000000080000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x80000000a4fa4fa5ULL, 0xfa4fa4fb80000000ULL, },
+        { 0x16c16c17c16c16c2ULL, 0x8000000016c16c17ULL, },
+        { 0xe38e38e48e38e38fULL, 0x80000000e38e38e4ULL, },    /*  48  */
+        { 0x7fffffff7fffffffULL, 0x38e38e387fffffffULL, },
+        { 0x38e38e39e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x7fffffff38e38e39ULL, 0xe38e38e37fffffffULL, },
+        { 0x16c16c17c16c16c2ULL, 0x8000000016c16c17ULL, },
+        { 0x7fffffff5b05b05bULL, 0x05b05b057fffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x7fffffff1c71c71dULL, 0x800000007fffffffULL, },
+        { 0x8000000080000000ULL, 0xc71c71c880000000ULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0x7fffffff1c71c71cULL, },
+        { 0x80000000c71c71c7ULL, 0x1c71c71d80000000ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x80000000a4fa4fa5ULL, 0xfa4fa4fb80000000ULL, },
+        { 0xe93e93e93e93e93eULL, 0x7fffffffe93e93e9ULL, },
+        { 0x80000000e38e38e3ULL, 0x7fffffff80000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace669dace8e38ULL, 0x386f50447fffffffULL, },
+        { 0xdc10382280000000ULL, 0x238e445f53508af8ULL, },
+        { 0x181bd07fca3072f2ULL, 0xbd7582865538cd6cULL, },
+        { 0x73531997253171c8ULL, 0xc790afbc80000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b993c43b88ULL, 0xeb1ef41b80000000ULL, },
+        { 0x7fffffffef61e4baULL, 0x8506324280000000ULL, },
+        { 0x23efc7de7fffffffULL, 0xdc71bba1acaf7508ULL, },    /*  72  */
+        { 0xb09cae476c3bc478ULL, 0x14e10be57fffffffULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, },
+        { 0xe7e42f8135cf8d0eULL, 0x428a7d7aaac73294ULL, },
+        { 0x80000000109e1b46ULL, 0x7af9cdbe7fffffffULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBSUU_S_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_b.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_b.c
new file mode 100644
index 0000000..d0964dc
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_b.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBV.B
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBV.B";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0101010101010101ULL, 0x0101010101010101ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c72c71c72c71cULL, 0x72c71c72c71c72c7ULL, },
+        { 0x8e39e38e39e38e39ULL, 0xe38e39e38e39e38eULL, },
+        { 0x5656565656565656ULL, 0x5656565656565656ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xababababababababULL, 0xababababababababULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x72c71d72c71d72c7ULL, 0x1d72c71d72c71d72ULL, },
+        { 0x39e48e39e48e39e4ULL, 0x8e39e48e39e48e39ULL, },
+        { 0xcdcdcdcdcdcdcdcdULL, 0xcdcdcdcdcdcdcdcdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e94e93e94e93eULL, 0x94e93e94e93e94e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x3434343434343434ULL, 0x3434343434343434ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8989898989898989ULL, 0x8989898989898989ULL, },
+        { 0xdedededededededeULL, 0xdedededededededeULL, },
+        { 0x6767676767676767ULL, 0x6767676767676767ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x50a5fb50a5fb50a5ULL, 0xfb50a5fb50a5fb50ULL, },
+        { 0x17c26c17c26c17c2ULL, 0x6c17c26c17c26c17ULL, },
+        { 0xe48f39e48f39e48fULL, 0x39e48f39e48f39e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x39e48e39e48e39e4ULL, 0x8e39e48e39e48e39ULL, },
+        { 0x8e39e38e39e38e39ULL, 0xe38e39e38e39e38eULL, },
+        { 0x17c26c17c26c17c2ULL, 0x6c17c26c17c26c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71d71c71d71c71dULL, 0x71c71d71c71d71c7ULL, },
+        { 0x1d72c81d72c81d72ULL, 0xc81d72c81d72c81dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x72c71d72c71d72c7ULL, 0x1d72c71d72c71d72ULL, },
+        { 0xc71c72c71c72c71cULL, 0x72c71c72c71c72c7ULL, },
+        { 0x50a5fb50a5fb50a5ULL, 0xfb50a5fb50a5fb50ULL, },
+        { 0xe93e94e93e94e93eULL, 0x94e93e94e93e94e9ULL, },
+        { 0x39e38f39e38f39e3ULL, 0x8f39e38f39e38f39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8dace669dbcf8e38ULL, 0x39705044e93c5e10ULL, },
+        { 0xdc1038226f93cac0ULL, 0x248f455f53508bf8ULL, },
+        { 0x181bd07fca3173f2ULL, 0xbe7683865539ce6cULL, },
+        { 0x73541a97253172c8ULL, 0xc790b0bc17c4a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6452b994c43c88ULL, 0xeb1ff51b6a142de8ULL, },
+        { 0x8b6fea16ef62e5baULL, 0x850633426cfd705cULL, },
+        { 0x24f0c8de916d3640ULL, 0xdc71bba1adb07508ULL, },    /*  72  */
+        { 0xb19cae476c3cc478ULL, 0x15e10be596ecd318ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9ea932ULL, 0x9ae73e2702e94374ULL, },
+        { 0xe8e5308136cf8d0eULL, 0x428a7d7aabc73294ULL, },
+        { 0x759116ea119e1b46ULL, 0x7bfacdbe940390a4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_B(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_B(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_d.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_d.c
new file mode 100644
index 0000000..ec26a8e
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_d.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBV.D
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBV.D";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000000000001ULL, 0x0000000000000001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x5555555555555556ULL, 0x5555555555555556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaabULL, 0xaaaaaaaaaaaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xcccccccccccccccdULL, 0xcccccccccccccccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e93e93e93e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x3333333333333334ULL, 0x3333333333333334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8888888888888889ULL, 0x8888888888888889ULL, },
+        { 0xdddddddddddddddeULL, 0xdddddddddddddddeULL, },
+        { 0x6666666666666667ULL, 0x6666666666666667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa4fa4fa4fa4fa5ULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xe38e38e38e38e38fULL, 0x38e38e38e38e38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e38e38e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x16c16c16c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c71c71c71dULL, 0x71c71c71c71c71c7ULL, },
+        { 0x1c71c71c71c71c72ULL, 0xc71c71c71c71c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c71c71c71c7ULL, 0x1c71c71c71c71c72ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c71c71c71c7ULL, },
+        { 0x4fa4fa4fa4fa4fa5ULL, 0xfa4fa4fa4fa4fa50ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e93e93e93e9ULL, },
+        { 0x38e38e38e38e38e3ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace668dace8e38ULL, 0x386f5044e93c5d10ULL, },
+        { 0xdc1038216e92c9c0ULL, 0x238e445f53508af8ULL, },
+        { 0x181bd07eca3072f2ULL, 0xbd7582865538cd6cULL, },
+        { 0x73531997253171c8ULL, 0xc790afbb16c3a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b893c43b88ULL, 0xeb1ef41a6a142de8ULL, },
+        { 0x8b6eea15ef61e4baULL, 0x850632416bfc705cULL, },
+        { 0x23efc7de916d3640ULL, 0xdc71bba0acaf7508ULL, },    /*  72  */
+        { 0xb09cae476c3bc478ULL, 0x14e10be595ebd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, },
+        { 0xe7e42f8135cf8d0eULL, 0x428a7d79aac73294ULL, },
+        { 0x749115ea109e1b46ULL, 0x7af9cdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_D(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_D(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_h.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_h.c
new file mode 100644
index 0000000..420422e
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_h.c
@@ -0,0 +1,151 @@
+/*
+ *  Test program for MSA instruction SUBV.H
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBV.H";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0001000100010001ULL, 0x0001000100010001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c71c72c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x8e39e38e38e38e39ULL, 0xe38e38e38e39e38eULL, },
+        { 0x5556555655565556ULL, 0x5556555655565556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaabaaabaaabaaabULL, 0xaaabaaabaaabaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c72c71d71c7ULL, 0x1c72c71d71c71c72ULL, },
+        { 0x38e48e39e38e38e4ULL, 0x8e39e38e38e48e39ULL, },
+        { 0xcccdcccdcccdcccdULL, 0xcccdcccdcccdcccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e93e94e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x3334333433343334ULL, 0x3334333433343334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8889888988898889ULL, 0x8889888988898889ULL, },
+        { 0xdddedddedddedddeULL, 0xdddedddedddedddeULL, },
+        { 0x6667666766676667ULL, 0x6667666766676667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa5fa50a4fb4fa5ULL, 0xfa50a4fb4fa5fa50ULL, },
+        { 0x16c26c17c16c16c2ULL, 0x6c17c16c16c26c17ULL, },
+        { 0xe38f38e48e39e38fULL, 0x38e48e39e38f38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e48e39e38e38e4ULL, 0x8e39e38e38e48e39ULL, },
+        { 0x8e39e38e38e38e39ULL, 0xe38e38e38e39e38eULL, },
+        { 0x16c26c17c16c16c2ULL, 0x6c17c16c16c26c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71d71c71c71c71dULL, 0x71c71c71c71d71c7ULL, },
+        { 0x1c72c71d71c81c72ULL, 0xc71d71c81c72c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c72c71d71c7ULL, 0x1c72c71d71c71c72ULL, },
+        { 0xc71c71c71c72c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x4fa5fa50a4fb4fa5ULL, 0xfa50a4fb4fa5fa50ULL, },
+        { 0xe93e93e93e94e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0x38e38e39e38f38e3ULL, 0x8e39e38f38e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace669dacf8e38ULL, 0x38705044e93c5d10ULL, },
+        { 0xdc1038226e93c9c0ULL, 0x238f445f53508af8ULL, },
+        { 0x181bd07fca3172f2ULL, 0xbd7682865539cd6cULL, },
+        { 0x73541997253171c8ULL, 0xc790afbc16c4a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6451b993c43b88ULL, 0xeb1ff41b6a142de8ULL, },
+        { 0x8b6fea16ef62e4baULL, 0x850632426bfd705cULL, },
+        { 0x23f0c7de916d3640ULL, 0xdc71bba1acb07508ULL, },    /*  72  */
+        { 0xb09cae476c3cc478ULL, 0x14e10be595ecd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9ea932ULL, 0x99e73e2701e94274ULL, },
+        { 0xe7e52f8135cf8d0eULL, 0x428a7d7aaac73294ULL, },
+        { 0x749115ea109e1b46ULL, 0x7afacdbe94038fa4ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_H(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_H(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_w.c b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_w.c
new file mode 100644
index 0000000..3e97005
--- /dev/null
+++ b/tests/tcg/mips/user/ase/msa/int-subtract/test_msa_subv_w.c
@@ -0,0 +1,153 @@
+/*
+ *  Test program for MSA instruction SUBV.W
+ *
+ *  Copyright (C) 2018  Wave Computing, Inc.
+ *  Copyright (C) 2018  Mateja Marjanovic <mateja.marjanovic@rt-rk.com>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/wrappers_msa.h"
+#include "../../../../include/test_inputs.h"
+#include "../../../../include/test_utils.h"
+
+#define TEST_COUNT_TOTAL (                                                \
+            (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
+            (RANDOM_INPUTS_SHORT_COUNT) * (RANDOM_INPUTS_SHORT_COUNT))
+
+
+int32_t main(void)
+{
+    char *instruction_name = "SUBV.W";
+    int32_t ret;
+    uint32_t i, j;
+    struct timeval start, end;
+    double elapsed_time;
+
+    uint64_t b128_result[TEST_COUNT_TOTAL][2];
+    uint64_t b128_expect[TEST_COUNT_TOTAL][2] = {
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*   0  */
+        { 0xffffffffffffffffULL, 0xffffffffffffffffULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x0000000100000001ULL, 0x0000000100000001ULL, },    /*   8  */
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },    /*  16  */
+        { 0xaaaaaaaaaaaaaaaaULL, 0xaaaaaaaaaaaaaaaaULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x5555555655555556ULL, 0x5555555655555556ULL, },    /*  24  */
+        { 0x5555555555555555ULL, 0x5555555555555555ULL, },
+        { 0xaaaaaaabaaaaaaabULL, 0xaaaaaaabaaaaaaabULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x71c71c72c71c71c7ULL, 0x1c71c71d71c71c72ULL, },
+        { 0x38e38e39e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0xcccccccdcccccccdULL, 0xcccccccdcccccccdULL, },    /*  32  */
+        { 0xccccccccccccccccULL, 0xccccccccccccccccULL, },
+        { 0x2222222222222222ULL, 0x2222222222222222ULL, },
+        { 0x7777777777777777ULL, 0x7777777777777777ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x9999999999999999ULL, 0x9999999999999999ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x3333333433333334ULL, 0x3333333433333334ULL, },    /*  40  */
+        { 0x3333333333333333ULL, 0x3333333333333333ULL, },
+        { 0x8888888988888889ULL, 0x8888888988888889ULL, },
+        { 0xdddddddedddddddeULL, 0xdddddddedddddddeULL, },
+        { 0x6666666766666667ULL, 0x6666666766666667ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4fa4fa50a4fa4fa5ULL, 0xfa4fa4fb4fa4fa50ULL, },
+        { 0x16c16c17c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xe38e38e48e38e38fULL, 0x38e38e39e38e38e4ULL, },    /*  48  */
+        { 0xe38e38e38e38e38eULL, 0x38e38e38e38e38e3ULL, },
+        { 0x38e38e39e38e38e4ULL, 0x8e38e38e38e38e39ULL, },
+        { 0x8e38e38e38e38e39ULL, 0xe38e38e38e38e38eULL, },
+        { 0x16c16c17c16c16c2ULL, 0x6c16c16c16c16c17ULL, },
+        { 0xb05b05b05b05b05bULL, 0x05b05b05b05b05b0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0xc71c71c71c71c71dULL, 0x71c71c71c71c71c7ULL, },
+        { 0x1c71c71d71c71c72ULL, 0xc71c71c81c71c71dULL, },    /*  56  */
+        { 0x1c71c71c71c71c71ULL, 0xc71c71c71c71c71cULL, },
+        { 0x71c71c72c71c71c7ULL, 0x1c71c71d71c71c72ULL, },
+        { 0xc71c71c71c71c71cULL, 0x71c71c72c71c71c7ULL, },
+        { 0x4fa4fa50a4fa4fa5ULL, 0xfa4fa4fb4fa4fa50ULL, },
+        { 0xe93e93e93e93e93eULL, 0x93e93e94e93e93e9ULL, },
+        { 0x38e38e39e38e38e3ULL, 0x8e38e38f38e38e39ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },    /*  64  */
+        { 0x8cace669dace8e38ULL, 0x386f5044e93c5d10ULL, },
+        { 0xdc1038226e92c9c0ULL, 0x238e445f53508af8ULL, },
+        { 0x181bd07fca3072f2ULL, 0xbd7582865538cd6cULL, },
+        { 0x73531997253171c8ULL, 0xc790afbc16c3a2f0ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x4f6351b993c43b88ULL, 0xeb1ef41b6a142de8ULL, },
+        { 0x8b6eea16ef61e4baULL, 0x850632426bfc705cULL, },
+        { 0x23efc7de916d3640ULL, 0xdc71bba1acaf7508ULL, },    /*  72  */
+        { 0xb09cae476c3bc478ULL, 0x14e10be595ebd218ULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+        { 0x3c0b985d5b9da932ULL, 0x99e73e2701e84274ULL, },
+        { 0xe7e42f8135cf8d0eULL, 0x428a7d7aaac73294ULL, },
+        { 0x749115ea109e1b46ULL, 0x7af9cdbe94038fa4ULL, },
+        { 0xc3f467a3a46256ceULL, 0x6618c1d9fe17bd8cULL, },
+        { 0x0000000000000000ULL, 0x0000000000000000ULL, },
+};
+
+    gettimeofday(&start, NULL);
+
+    for (i = 0; i < PATTERN_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < PATTERN_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_W(b128_pattern[i], b128_pattern[j],
+                           b128_result[PATTERN_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    for (i = 0; i < RANDOM_INPUTS_SHORT_COUNT; i++) {
+        for (j = 0; j < RANDOM_INPUTS_SHORT_COUNT; j++) {
+            do_msa_SUBV_W(b128_random[i], b128_random[j],
+                           b128_result[((PATTERN_INPUTS_SHORT_COUNT) *
+                                        (PATTERN_INPUTS_SHORT_COUNT)) +
+                                       RANDOM_INPUTS_SHORT_COUNT * i + j]);
+        }
+    }
+
+    gettimeofday(&end, NULL);
+
+    elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0;
+    elapsed_time += (end.tv_usec - start.tv_usec) / 1000.0;
+
+    ret = check_results(instruction_name, TEST_COUNT_TOTAL, elapsed_time,
+                        &b128_result[0][0], &b128_expect[0][0]);
+
+    return ret;
+}
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c
index 5cf8627..d720dc3 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVEV.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c
index d3600e9..8323994 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVEV.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c
index 9a80fac..3f6fc26 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVEV.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c
index 8f62d47..30d2e38 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvev_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVEV.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c
index f7e6dc0..c771287 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVL.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c
index 0f4c048..b7d5fcd 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVL.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c
index 6c1c6d9..af72876 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVL.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c
index d22d965..e06c9d9 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvl_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVL.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c
index c55f3a4..8e7f1c4 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVOD.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c
index d03e7b4..acbd94a 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVOD.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c
index f64d8b5..8a82def4 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVOD.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c
index 4ae75f8..e19170c 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvod_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVOD.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c
index f2cc7bf..1e519e6 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVR.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c
index f5ff947..be76043 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVR.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c
index 5a2986d..cbd4685 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVR.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c
index fa0d6ea..5f4cfd0 100644
--- a/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c
+++ b/tests/tcg/mips/user/ase/msa/interleave/test_msa_ilvr_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction ILVR.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c
index 51b256f..534c420 100644
--- a/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c
+++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_and_v.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction AND.V
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c
index 90ca198..f781a8b 100644
--- a/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c
+++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_nor_v.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction NOR.V
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c
index 4ad5366..924f216 100644
--- a/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c
+++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_or_v.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction OR.V
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c b/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c
index 54effed..f0442e6 100644
--- a/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c
+++ b/tests/tcg/mips/user/ase/msa/logic/test_msa_xor_v.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction XOR.V
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c
index d98dd22..409773d 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKEV.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c
index 543fb6a..8e89716 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKEV.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c
index 64a18c0..b389587 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKEV.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c
index a0acacd..d393ad50 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckev_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKEV.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c
index 7bf86fc..ab363a0 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKOD.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c
index 3c4d55b..09a6140 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKOD.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c
index 5c3c529..d7a8c5b 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKOD.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c
index 9275890..4b732d0 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_pckod_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction PCKOD.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c
index fcf857a..d9ccf57 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_b.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction VSHF.B
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c
index 700c159..6c555fb 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_d.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction VSHF.D
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c
index 3d6c1dc..9dfcb51 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_h.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction VSHF.H
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c
index 6030762..97074c0 100644
--- a/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c
+++ b/tests/tcg/mips/user/ase/msa/pack/test_msa_vshf_w.c
@@ -1,8 +1,8 @@
 /*
  *  Test program for MSA instruction VSHF.W
  *
- *  Copyright (C) 2018  Wave Computing, Inc.
- *  Copyright (C) 2018  Aleksandar Markovic <amarkovic@wavecomp.com>
+ *  Copyright (C) 2019  Wave Computing, Inc.
+ *  Copyright (C) 2019  Aleksandar Markovic <amarkovic@wavecomp.com>
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
 #include <stdint.h>
 
 #include "../../../../include/wrappers_msa.h"
-#include "../../../../include/test_inputs.h"
-#include "../../../../include/test_utils.h"
+#include "../../../../include/test_inputs_128.h"
+#include "../../../../include/test_utils_128.h"
 
 #define TEST_COUNT_TOTAL (                                                \
             (PATTERN_INPUTS_SHORT_COUNT) * (PATTERN_INPUTS_SHORT_COUNT) + \
diff --git a/tests/test-qgraph.c b/tests/test-qgraph.c
index f6a6565..5c7e457 100644
--- a/tests/test-qgraph.c
+++ b/tests/test-qgraph.c
@@ -122,7 +122,7 @@
 static void check_test(const char *test, const char *interface)
 {
     QOSGraphEdge *edge;
-    const char *full_name = g_strdup_printf("%s-tests/%s", interface, test);
+    char *full_name = g_strdup_printf("%s-tests/%s", interface, test);
 
     qos_add_test(test, interface, testfunct, NULL);
     g_assert_cmpint(qos_graph_has_machine(test), ==, FALSE);
@@ -138,6 +138,7 @@
     g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, TRUE);
     qos_graph_node_set_availability(full_name, FALSE);
     g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, FALSE);
+    g_free(full_name);
 }
 
 static void count_each_test(QOSGraphNode *path, int len)
diff --git a/thunk.c b/thunk.c
index 17f3d32..7f31cff 100644
--- a/thunk.c
+++ b/thunk.c
@@ -86,7 +86,7 @@
 #endif
     /* now we can alloc the data */
 
-    for(i = 0;i < 2; i++) {
+    for (i = 0; i < ARRAY_SIZE(se->field_offsets); i++) {
         offset = 0;
         max_align = 1;
         se->field_offsets[i] = g_new(int, nb_fields);
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index afd571c..c544509 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -36,7 +36,7 @@
 
 $(obj)/generated-helpers.o: $(obj)/generated-helpers.c
 
-target-obj-y += generated-helpers.o
+obj-y += generated-helpers.o
 
 
 $(obj)/generated-tcg-tracers.h: $(obj)/generated-tcg-tracers.h-timestamp
@@ -55,5 +55,5 @@
 util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o
 util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
 util-obj-y += control.o
-target-obj-y += control-target.o
+obj-y += control-target.o
 util-obj-y += qmp.o
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 37c5854..326d92d 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -244,7 +244,19 @@
     f = fcntl(fd, F_GETFL);
     assert(f != -1);
     f = fcntl(fd, F_SETFL, f | O_NONBLOCK);
+#ifdef __OpenBSD__
+    if (f == -1) {
+        /*
+         * Previous to OpenBSD 6.3, fcntl(F_SETFL) is not permitted on
+         * memory devices and sets errno to ENODEV.
+         * It's OK if we fail to set O_NONBLOCK on devices like /dev/null,
+         * because they will never block anyway.
+         */
+        assert(errno == ENODEV);
+    }
+#else
     assert(f != -1);
+#endif
 }
 
 int socket_set_fast_reuse(int fd)
diff --git a/vl.c b/vl.c
index f46f8d7..5616208 100644
--- a/vl.c
+++ b/vl.c
@@ -185,7 +185,6 @@
 int boot_menu;
 bool boot_strict;
 uint8_t *boot_splash_filedata;
-size_t boot_splash_filedata_size;
 bool wakeup_suspend_enabled;
 
 int icount_align_option;
@@ -1191,6 +1190,55 @@
 
 }
 
+typedef struct BlockdevOptionsQueueEntry {
+    BlockdevOptions *bdo;
+    Location loc;
+    QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry;
+} BlockdevOptionsQueueEntry;
+
+typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue;
+
+static void configure_blockdev(BlockdevOptionsQueue *bdo_queue,
+                               MachineClass *machine_class, int snapshot)
+{
+    /*
+     * If the currently selected machine wishes to override the
+     * units-per-bus property of its default HBA interface type, do so
+     * now.
+     */
+    if (machine_class->units_per_default_bus) {
+        override_max_devs(machine_class->block_default_type,
+                          machine_class->units_per_default_bus);
+    }
+
+    /* open the virtual block devices */
+    while (!QSIMPLEQ_EMPTY(bdo_queue)) {
+        BlockdevOptionsQueueEntry *bdo = QSIMPLEQ_FIRST(bdo_queue);
+
+        QSIMPLEQ_REMOVE_HEAD(bdo_queue, entry);
+        loc_push_restore(&bdo->loc);
+        qmp_blockdev_add(bdo->bdo, &error_fatal);
+        loc_pop(&bdo->loc);
+        qapi_free_BlockdevOptions(bdo->bdo);
+        g_free(bdo);
+    }
+    if (snapshot || replay_mode != REPLAY_MODE_NONE) {
+        qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot,
+                          NULL, NULL);
+    }
+    if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func,
+                          &machine_class->block_default_type, &error_fatal)) {
+        /* We printed help */
+        exit(0);
+    }
+
+    default_drive(default_cdrom, snapshot, machine_class->block_default_type, 2,
+                  CDROM_OPTS);
+    default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS);
+    default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS);
+
+}
+
 static QemuOptsList qemu_smp_opts = {
     .name = "smp-opts",
     .implied_opt_name = "cpus",
@@ -2937,17 +2985,6 @@
                       global_init_func, NULL, NULL);
 }
 
-/*
- * Note: we should see that these properties are actually having a
- * priority: accel < machine < user. This means e.g. when user
- * specifies something in "-global", it'll always be used with highest
- * priority than either machine/accelerator compat properties.
- */
-static void register_global_properties(MachineState *ms)
-{
-    user_register_global_props();
-}
-
 int main(int argc, char **argv, char **envp)
 {
     int i;
@@ -2982,13 +3019,7 @@
     Error *err = NULL;
     bool list_data_dirs = false;
     char *dir, **dirs;
-    typedef struct BlockdevOptions_queue {
-        BlockdevOptions *bdo;
-        Location loc;
-        QSIMPLEQ_ENTRY(BlockdevOptions_queue) entry;
-    } BlockdevOptions_queue;
-    QSIMPLEQ_HEAD(, BlockdevOptions_queue) bdo_queue
-        = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
+    BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
 
     module_call_init(MODULE_INIT_TRACE);
 
@@ -3112,12 +3143,12 @@
             case QEMU_OPTION_blockdev:
                 {
                     Visitor *v;
-                    BlockdevOptions_queue *bdo;
+                    BlockdevOptionsQueueEntry *bdo;
 
                     v = qobject_input_visitor_new_str(optarg, "driver",
                                                       &error_fatal);
 
-                    bdo = g_new(BlockdevOptions_queue, 1);
+                    bdo = g_new(BlockdevOptionsQueueEntry, 1);
                     visit_type_BlockdevOptions(v, NULL, &bdo->bdo,
                                                &error_fatal);
                     visit_free(v);
@@ -3942,6 +3973,8 @@
      */
     loc_set_none();
 
+    user_register_global_props();
+
     replay_configure(icount_opts);
 
     if (incoming && !preconfig_exit_requested) {
@@ -3953,6 +3986,7 @@
     configure_rtc(qemu_find_opts_singleton("rtc"));
 
     machine_class = select_machine();
+    object_set_machine_compat_props(machine_class->compat_props);
 
     set_memory_options(&ram_slots, &maxram_size, machine_class);
 
@@ -3997,6 +4031,10 @@
     }
     object_property_add_child(object_get_root(), "machine",
                               OBJECT(current_machine), &error_abort);
+    object_property_add_child(container_get(OBJECT(current_machine),
+                                            "/unattached"),
+                              "sysbus", OBJECT(sysbus_get_default()),
+                              NULL);
 
     if (machine_class->minimum_page_bits) {
         if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) {
@@ -4235,6 +4273,13 @@
         exit(0);
     }
 
+    /*
+     * Note: we need to create block backends before
+     * machine_set_property(), so machine properties can refer to
+     * them.
+     */
+    configure_blockdev(&bdo_queue, machine_class, snapshot);
+
     machine_opts = qemu_get_machine_opts();
     qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
                      &error_fatal);
@@ -4250,12 +4295,6 @@
     }
 
     /*
-     * Register all the global properties, including accel properties,
-     * machine properties, and user-specified ones.
-     */
-    register_global_properties(current_machine);
-
-    /*
      * Migration object can only be created after global properties
      * are applied correctly.
      */
@@ -4367,39 +4406,6 @@
     ram_mig_init();
     dirty_bitmap_mig_init();
 
-    /* If the currently selected machine wishes to override the units-per-bus
-     * property of its default HBA interface type, do so now. */
-    if (machine_class->units_per_default_bus) {
-        override_max_devs(machine_class->block_default_type,
-                          machine_class->units_per_default_bus);
-    }
-
-    /* open the virtual block devices */
-    while (!QSIMPLEQ_EMPTY(&bdo_queue)) {
-        BlockdevOptions_queue *bdo = QSIMPLEQ_FIRST(&bdo_queue);
-
-        QSIMPLEQ_REMOVE_HEAD(&bdo_queue, entry);
-        loc_push_restore(&bdo->loc);
-        qmp_blockdev_add(bdo->bdo, &error_fatal);
-        loc_pop(&bdo->loc);
-        qapi_free_BlockdevOptions(bdo->bdo);
-        g_free(bdo);
-    }
-    if (snapshot || replay_mode != REPLAY_MODE_NONE) {
-        qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot,
-                          NULL, NULL);
-    }
-    if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func,
-                          &machine_class->block_default_type, &error_fatal)) {
-        /* We printed help */
-        exit(0);
-    }
-
-    default_drive(default_cdrom, snapshot, machine_class->block_default_type, 2,
-                  CDROM_OPTS);
-    default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS);
-    default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS);
-
     qemu_opts_foreach(qemu_find_opts("mon"),
                       mon_init_func, NULL, &error_fatal);