summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--chardev/char-socket.c16
-rwxr-xr-xconfigure12
-rw-r--r--crypto/afsplit.c28
-rw-r--r--crypto/block-luks.c74
-rw-r--r--crypto/block.c15
-rw-r--r--crypto/hmac-glib.c5
-rw-r--r--crypto/pbkdf.c5
-rw-r--r--crypto/secret.c39
-rw-r--r--crypto/tlscredsanon.c16
-rw-r--r--crypto/tlscredspsk.c5
-rw-r--r--crypto/tlscredsx509.c16
-rw-r--r--hw/display/ati.c112
-rw-r--r--hw/display/ati_dbg.c10
-rw-r--r--hw/display/ati_int.h5
-rw-r--r--hw/display/ati_regs.h17
-rw-r--r--hw/usb/hcd-ehci.c3
-rw-r--r--hw/usb/hcd-xhci.c3
-rw-r--r--hw/usb/redirect.c74
-rw-r--r--include/crypto/block.h2
-rw-r--r--include/crypto/cipher.h2
-rw-r--r--include/crypto/hmac.h2
-rw-r--r--include/crypto/ivgen.h2
-rw-r--r--include/crypto/tlssession.h2
-rw-r--r--include/glib-compat.h42
-rw-r--r--include/qemu/module.h2
-rw-r--r--io/task.c1
-rw-r--r--memory.c99
-rw-r--r--qapi/ui.json3
-rw-r--r--qemu-options.hx7
-rw-r--r--qtest.c9
-rw-r--r--scripts/minikconf.py4
-rw-r--r--target/tricore/helper.h1
-rw-r--r--target/tricore/op_helper.c7
-rw-r--r--target/tricore/translate.c577
-rw-r--r--tests/Makefile.include3
-rw-r--r--tests/docker/Makefile.include10
-rwxr-xr-xtests/docker/docker.py53
-rw-r--r--tests/libqtest.c6
-rw-r--r--tests/libqtest.h2
-rw-r--r--tests/modules-test.c68
-rw-r--r--tests/socket-helpers.c17
-rw-r--r--tests/socket-helpers.h11
-rw-r--r--tests/test-char.c19
-rw-r--r--tests/test-io-channel-socket.c4
-rw-r--r--tests/test-util-sockets.c4
-rw-r--r--ui/curses.c2
-rw-r--r--ui/input-linux.c4
-rw-r--r--util/module.c17
49 files changed, 866 insertions, 582 deletions
diff --git a/Makefile b/Makefile
index 85862fb81a..ae17a83067 100644
--- a/Makefile
+++ b/Makefile
@@ -84,8 +84,7 @@ endif
 
 include $(SRC_PATH)/rules.mak
 
-# notempy and lor are defined in rules.mak
-CONFIG_TOOLS := $(call notempty,$(TOOLS))
+# lor is defined in rules.mak
 CONFIG_BLOCK := $(call lor,$(CONFIG_SOFTMMU),$(CONFIG_TOOLS))
 
 # Create QEMU_PKGVERSION and FULL_VERSION strings
@@ -681,7 +680,7 @@ clean: recurse-clean
 		! -path ./roms/edk2/BaseTools/Source/Python/UPT/Dll/sqlite3.dll \
 		-exec rm {} +
 	rm -f $(edk2-decompressed)
-	rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga$(EXESUF) TAGS cscope.* *.pod *~ */*~
+	rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) TAGS cscope.* *.pod *~ */*~
 	rm -f fsdev/*.pod scsi/*.pod
 	rm -f qemu-img-cmds.h
 	rm -f ui/shader/*-vert.h ui/shader/*-frag.h
@@ -809,7 +808,7 @@ ifdef CONFIG_POSIX
 	$(INSTALL_DATA) docs/interop/qemu-qmp-ref.7 "$(DESTDIR)$(mandir)/man7"
 	$(INSTALL_DATA) docs/qemu-block-drivers.7 "$(DESTDIR)$(mandir)/man7"
 	$(INSTALL_DATA) docs/qemu-cpu-models.7 "$(DESTDIR)$(mandir)/man7"
-ifneq ($(TOOLS),)
+ifeq ($(CONFIG_TOOLS),y)
 	$(INSTALL_DATA) qemu-img.1 "$(DESTDIR)$(mandir)/man1"
 	$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
 	$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
@@ -845,7 +844,7 @@ install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-localstated
 	$(if $(INSTALL_BLOBS),$(edk2-decompressed)) \
 	recurse-install
 ifneq ($(TOOLS),)
-	$(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir))
+	$(call install-prog,$(TOOLS),$(DESTDIR)$(bindir))
 endif
 ifneq ($(CONFIG_MODULES),)
 	$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
@@ -1158,7 +1157,7 @@ endif
 	@echo  ''
 	@echo  'Test targets:'
 	@echo  '  check           - Run all tests (check-help for details)'
-	@echo  '  docker          - Help about targets running tests inside Docker containers'
+	@echo  '  docker          - Help about targets running tests inside containers'
 	@echo  '  vm-help         - Help about targets running tests inside VM'
 	@echo  ''
 	@echo  'Documentation targets:'
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 7ca5d97af3..03f03407b0 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -150,7 +150,7 @@ static void tcp_chr_accept(QIONetListener *listener,
                            void *opaque);
 
 static int tcp_chr_read_poll(void *opaque);
-static void tcp_chr_disconnect(Chardev *chr);
+static void tcp_chr_disconnect_locked(Chardev *chr);
 
 /* Called with chr_write_lock held.  */
 static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
@@ -174,7 +174,7 @@ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
 
         if (ret < 0 && errno != EAGAIN) {
             if (tcp_chr_read_poll(chr) <= 0) {
-                tcp_chr_disconnect(chr);
+                tcp_chr_disconnect_locked(chr);
                 return len;
             } /* else let the read handler finish it properly */
         }
@@ -469,8 +469,9 @@ static void update_disconnected_filename(SocketChardev *s)
 /* NB may be called even if tcp_chr_connect has not been
  * reached, due to TLS or telnet initialization failure,
  * so can *not* assume s->state == TCP_CHARDEV_STATE_CONNECTED
+ * This must be called with chr->chr_write_lock held.
  */
-static void tcp_chr_disconnect(Chardev *chr)
+static void tcp_chr_disconnect_locked(Chardev *chr)
 {
     SocketChardev *s = SOCKET_CHARDEV(chr);
     bool emit_close = s->state == TCP_CHARDEV_STATE_CONNECTED;
@@ -490,6 +491,13 @@ static void tcp_chr_disconnect(Chardev *chr)
     }
 }
 
+static void tcp_chr_disconnect(Chardev *chr)
+{
+    qemu_mutex_lock(&chr->chr_write_lock);
+    tcp_chr_disconnect_locked(chr);
+    qemu_mutex_unlock(&chr->chr_write_lock);
+}
+
 static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
 {
     Chardev *chr = CHARDEV(opaque);
@@ -1131,8 +1139,10 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
     Chardev *chr = CHARDEV(opaque);
     SocketChardev *s = SOCKET_CHARDEV(opaque);
 
+    qemu_mutex_lock(&chr->chr_write_lock);
     g_source_unref(s->reconnect_timer);
     s->reconnect_timer = NULL;
+    qemu_mutex_unlock(&chr->chr_write_lock);
 
     if (chr->be_open) {
         return false;
diff --git a/configure b/configure
index 0173db5d9f..e44e454c43 100755
--- a/configure
+++ b/configure
@@ -3636,7 +3636,7 @@ fi
 ##########################################
 # glib support probe
 
-glib_req_ver=2.40
+glib_req_ver=2.48
 glib_modules=gthread-2.0
 if test "$modules" = yes; then
     glib_modules="$glib_modules gmodule-export-2.0"
@@ -6129,7 +6129,7 @@ if [ "$guest_agent" != "no" ]; then
   if [ "$softmmu" = no -a "$want_tools" = no ] ; then
       guest_agent=no
   elif [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then
-      tools="qemu-ga $tools"
+      tools="qemu-ga\$(EXESUF) $tools"
       guest_agent=yes
   elif [ "$guest_agent" != yes ]; then
       guest_agent=no
@@ -6614,6 +6614,9 @@ fi
 if test "$profiler" = "yes" ; then
   echo "CONFIG_PROFILER=y" >> $config_host_mak
 fi
+if test "$want_tools" = "yes" ; then
+  echo "CONFIG_TOOLS=y" >> $config_host_mak
+fi
 if test "$slirp" != "no"; then
   echo "CONFIG_SLIRP=y" >> $config_host_mak
   echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak
@@ -7360,11 +7363,6 @@ if test "$sparse" = "yes" ; then
   echo "HOST_CC      := REAL_CC=\"\$(HOST_CC)\" cgcc"  >> $config_host_mak
   echo "QEMU_CFLAGS  += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak
 fi
-if test "$cross_prefix" != ""; then
-  echo "AUTOCONF_HOST := --host=${cross_prefix%-}"     >> $config_host_mak
-else
-  echo "AUTOCONF_HOST := "                             >> $config_host_mak
-fi
 echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
 echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak
 echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
diff --git a/crypto/afsplit.c b/crypto/afsplit.c
index 328d68c96b..b1a5a20899 100644
--- a/crypto/afsplit.c
+++ b/crypto/afsplit.c
@@ -58,7 +58,7 @@ static int qcrypto_afsplit_hash(QCryptoHashAlgorithm hash,
     }
 
     for (i = 0; i < hashcount; i++) {
-        uint8_t *out = NULL;
+        g_autofree uint8_t *out = NULL;
         size_t outlen = 0;
         uint32_t iv = cpu_to_be32(i);
         struct iovec in[] = {
@@ -79,7 +79,6 @@ static int qcrypto_afsplit_hash(QCryptoHashAlgorithm hash,
         assert(outlen == digestlen);
         memcpy(block + (i * digestlen), out,
                (i == (hashcount - 1)) ? finallen : digestlen);
-        g_free(out);
     }
 
     return 0;
@@ -93,13 +92,12 @@ int qcrypto_afsplit_encode(QCryptoHashAlgorithm hash,
                            uint8_t *out,
                            Error **errp)
 {
-    uint8_t *block = g_new0(uint8_t, blocklen);
+    g_autofree uint8_t *block = g_new0(uint8_t, blocklen);
     size_t i;
-    int ret = -1;
 
     for (i = 0; i < (stripes - 1); i++) {
         if (qcrypto_random_bytes(out + (i * blocklen), blocklen, errp) < 0) {
-            goto cleanup;
+            return -1;
         }
 
         qcrypto_afsplit_xor(blocklen,
@@ -108,18 +106,14 @@ int qcrypto_afsplit_encode(QCryptoHashAlgorithm hash,
                             block);
         if (qcrypto_afsplit_hash(hash, blocklen, block,
                                  errp) < 0) {
-            goto cleanup;
+            return -1;
         }
     }
     qcrypto_afsplit_xor(blocklen,
                         in,
                         block,
                         out + (i * blocklen));
-    ret = 0;
-
- cleanup:
-    g_free(block);
-    return ret;
+    return 0;
 }
 
 
@@ -130,9 +124,8 @@ int qcrypto_afsplit_decode(QCryptoHashAlgorithm hash,
                            uint8_t *out,
                            Error **errp)
 {
-    uint8_t *block = g_new0(uint8_t, blocklen);
+    g_autofree uint8_t *block = g_new0(uint8_t, blocklen);
     size_t i;
-    int ret = -1;
 
     for (i = 0; i < (stripes - 1); i++) {
         qcrypto_afsplit_xor(blocklen,
@@ -141,7 +134,7 @@ int qcrypto_afsplit_decode(QCryptoHashAlgorithm hash,
                             block);
         if (qcrypto_afsplit_hash(hash, blocklen, block,
                                  errp) < 0) {
-            goto cleanup;
+            return -1;
         }
     }
 
@@ -149,10 +142,5 @@ int qcrypto_afsplit_decode(QCryptoHashAlgorithm hash,
                         in + (i * blocklen),
                         block,
                         out);
-
-    ret = 0;
-
- cleanup:
-    g_free(block);
-    return ret;
+    return 0;
 }
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 409ab50f20..743949adbf 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -425,14 +425,13 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                             Error **errp)
 {
     QCryptoBlockLUKS *luks = block->opaque;
-    uint8_t *splitkey;
+    g_autofree uint8_t *splitkey = NULL;
     size_t splitkeylen;
-    uint8_t *possiblekey;
-    int ret = -1;
+    g_autofree uint8_t *possiblekey = NULL;
     ssize_t rv;
-    QCryptoCipher *cipher = NULL;
+    g_autoptr(QCryptoCipher) cipher = NULL;
     uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN];
-    QCryptoIVGen *ivgen = NULL;
+    g_autoptr(QCryptoIVGen) ivgen = NULL;
     size_t niv;
 
     if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
@@ -456,7 +455,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                        slot->iterations,
                        possiblekey, masterkeylen,
                        errp) < 0) {
-        goto cleanup;
+        return -1;
     }
 
     /*
@@ -472,7 +471,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                   opaque,
                   errp);
     if (rv < 0) {
-        goto cleanup;
+        return -1;
     }
 
 
@@ -482,7 +481,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                                 possiblekey, masterkeylen,
                                 errp);
     if (!cipher) {
-        goto cleanup;
+        return -1;
     }
 
     niv = qcrypto_cipher_get_iv_len(cipheralg,
@@ -493,7 +492,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                               possiblekey, masterkeylen,
                               errp);
     if (!ivgen) {
-        goto cleanup;
+        return -1;
     }
 
 
@@ -512,7 +511,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                                             splitkey,
                                             splitkeylen,
                                             errp) < 0) {
-        goto cleanup;
+        return -1;
     }
 
     /*
@@ -525,7 +524,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                                splitkey,
                                masterkey,
                                errp) < 0) {
-        goto cleanup;
+        return -1;
     }
 
 
@@ -544,26 +543,18 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
                        luks->header.master_key_iterations,
                        keydigest, G_N_ELEMENTS(keydigest),
                        errp) < 0) {
-        goto cleanup;
+        return -1;
     }
 
     if (memcmp(keydigest, luks->header.master_key_digest,
                QCRYPTO_BLOCK_LUKS_DIGEST_LEN) == 0) {
         /* Success, we got the right master key */
-        ret = 1;
-        goto cleanup;
+        return 1;
     }
 
     /* Fail, user's password was not valid for this key slot,
      * tell caller to try another slot */
-    ret = 0;
-
- cleanup:
-    qcrypto_ivgen_free(ivgen);
-    qcrypto_cipher_free(cipher);
-    g_free(splitkey);
-    g_free(possiblekey);
-    return ret;
+    return 0;
 }
 
 
@@ -644,7 +635,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
     int ret = 0;
     size_t i;
     ssize_t rv;
-    uint8_t *masterkey = NULL;
+    g_autofree uint8_t *masterkey = NULL;
     size_t masterkeylen;
     char *ivgen_name, *ivhash_name;
     QCryptoCipherMode ciphermode;
@@ -653,7 +644,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
     QCryptoCipherAlgorithm ivcipheralg;
     QCryptoHashAlgorithm hash;
     QCryptoHashAlgorithm ivhash;
-    char *password = NULL;
+    g_autofree char *password = NULL;
 
     if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
         if (!options->u.luks.key_secret) {
@@ -856,17 +847,12 @@ qcrypto_block_luks_open(QCryptoBlock *block,
     luks->ivgen_hash_alg = ivhash;
     luks->hash_alg = hash;
 
-    g_free(masterkey);
-    g_free(password);
-
     return 0;
 
  fail:
-    g_free(masterkey);
     qcrypto_block_free_cipher(block);
     qcrypto_ivgen_free(block->ivgen);
     g_free(luks);
-    g_free(password);
     return ret;
 }
 
@@ -891,20 +877,20 @@ qcrypto_block_luks_create(QCryptoBlock *block,
     QCryptoBlockLUKS *luks;
     QCryptoBlockCreateOptionsLUKS luks_opts;
     Error *local_err = NULL;
-    uint8_t *masterkey = NULL;
-    uint8_t *slotkey = NULL;
-    uint8_t *splitkey = NULL;
+    g_autofree uint8_t *masterkey = NULL;
+    g_autofree uint8_t *slotkey = NULL;
+    g_autofree uint8_t *splitkey = NULL;
     size_t splitkeylen = 0;
     size_t i;
-    QCryptoCipher *cipher = NULL;
-    QCryptoIVGen *ivgen = NULL;
-    char *password;
+    g_autoptr(QCryptoCipher) cipher = NULL;
+    g_autoptr(QCryptoIVGen) ivgen = NULL;
+    g_autofree char *password = NULL;
     const char *cipher_alg;
     const char *cipher_mode;
     const char *ivgen_alg;
     const char *ivgen_hash_alg = NULL;
     const char *hash_alg;
-    char *cipher_mode_spec = NULL;
+    g_autofree char *cipher_mode_spec = NULL;
     QCryptoCipherAlgorithm ivcipheralg = 0;
     uint64_t iters;
 
@@ -1311,15 +1297,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
     luks->hash_alg = luks_opts.hash_alg;
 
     memset(masterkey, 0, luks->header.key_bytes);
-    g_free(masterkey);
     memset(slotkey, 0, luks->header.key_bytes);
-    g_free(slotkey);
-    g_free(splitkey);
-    g_free(password);
-    g_free(cipher_mode_spec);
-
-    qcrypto_ivgen_free(ivgen);
-    qcrypto_cipher_free(cipher);
 
     return 0;
 
@@ -1327,17 +1305,9 @@ qcrypto_block_luks_create(QCryptoBlock *block,
     if (masterkey) {
         memset(masterkey, 0, luks->header.key_bytes);
     }
-    g_free(masterkey);
     if (slotkey) {
         memset(slotkey, 0, luks->header.key_bytes);
     }
-    g_free(slotkey);
-    g_free(splitkey);
-    g_free(password);
-    g_free(cipher_mode_spec);
-
-    qcrypto_ivgen_free(ivgen);
-    qcrypto_cipher_free(cipher);
 
     qcrypto_block_free_cipher(block);
     qcrypto_ivgen_free(block->ivgen);
diff --git a/crypto/block.c b/crypto/block.c
index ee96759f7d..325752871c 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -299,15 +299,13 @@ static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
                                           QCryptoCipherEncDecFunc func,
                                           Error **errp)
 {
-    uint8_t *iv;
+    g_autofree uint8_t *iv = niv ? g_new0(uint8_t, niv) : NULL;
     int ret = -1;
     uint64_t startsector = offset / sectorsize;
 
     assert(QEMU_IS_ALIGNED(offset, sectorsize));
     assert(QEMU_IS_ALIGNED(len, sectorsize));
 
-    iv = niv ? g_new0(uint8_t, niv) : NULL;
-
     while (len > 0) {
         size_t nbytes;
         if (niv) {
@@ -320,19 +318,19 @@ static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
             }
 
             if (ret < 0) {
-                goto cleanup;
+                return -1;
             }
 
             if (qcrypto_cipher_setiv(cipher,
                                      iv, niv,
                                      errp) < 0) {
-                goto cleanup;
+                return -1;
             }
         }
 
         nbytes = len > sectorsize ? sectorsize : len;
         if (func(cipher, buf, buf, nbytes, errp) < 0) {
-            goto cleanup;
+            return -1;
         }
 
         startsector++;
@@ -340,10 +338,7 @@ static int do_qcrypto_block_cipher_encdec(QCryptoCipher *cipher,
         len -= nbytes;
     }
 
-    ret = 0;
- cleanup:
-    g_free(iv);
-    return ret;
+    return 0;
 }
 
 
diff --git a/crypto/hmac-glib.c b/crypto/hmac-glib.c
index 7df627329d..509bbc74c2 100644
--- a/crypto/hmac-glib.c
+++ b/crypto/hmac-glib.c
@@ -21,12 +21,7 @@ static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
     [QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5,
     [QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1,
     [QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256,
-/* Support for HMAC SHA-512 in GLib 2.42 */
-#if GLIB_CHECK_VERSION(2, 42, 0)
     [QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512,
-#else
-    [QCRYPTO_HASH_ALG_SHA512] = -1,
-#endif
     [QCRYPTO_HASH_ALG_SHA224] = -1,
     [QCRYPTO_HASH_ALG_SHA384] = -1,
     [QCRYPTO_HASH_ALG_RIPEMD160] = -1,
diff --git a/crypto/pbkdf.c b/crypto/pbkdf.c
index b7c7c4a59b..3775ddc6c5 100644
--- a/crypto/pbkdf.c
+++ b/crypto/pbkdf.c
@@ -69,12 +69,10 @@ uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
                                     Error **errp)
 {
     uint64_t ret = -1;
-    uint8_t *out;
+    g_autofree uint8_t *out = g_new(uint8_t, nout);
     uint64_t iterations = (1 << 15);
     unsigned long long delta_ms, start_ms, end_ms;
 
-    out = g_new(uint8_t, nout);
-
     while (1) {
         if (qcrypto_pbkdf2_get_thread_cpu(&start_ms, errp) < 0) {
             goto cleanup;
@@ -108,6 +106,5 @@ uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
 
  cleanup:
     memset(out, 0, nout);
-    g_free(out);
     return ret;
 }
diff --git a/crypto/secret.c b/crypto/secret.c
index a75d50ae0c..1cf0ad0ce8 100644
--- a/crypto/secret.c
+++ b/crypto/secret.c
@@ -72,10 +72,12 @@ static void qcrypto_secret_decrypt(QCryptoSecret *secret,
                                    size_t *outputlen,
                                    Error **errp)
 {
-    uint8_t *key = NULL, *ciphertext = NULL, *iv = NULL;
+    g_autofree uint8_t *key = NULL;
+    g_autofree uint8_t *ciphertext = NULL;
+    g_autofree uint8_t *iv = NULL;
     size_t keylen, ciphertextlen, ivlen;
-    QCryptoCipher *aes = NULL;
-    uint8_t *plaintext = NULL;
+    g_autoptr(QCryptoCipher) aes = NULL;
+    g_autofree uint8_t *plaintext = NULL;
 
     *output = NULL;
     *outputlen = 0;
@@ -83,27 +85,27 @@ static void qcrypto_secret_decrypt(QCryptoSecret *secret,
     if (qcrypto_secret_lookup(secret->keyid,
                               &key, &keylen,
                               errp) < 0) {
-        goto cleanup;
+        return;
     }
 
     if (keylen != 32) {
         error_setg(errp, "Key should be 32 bytes in length");
-        goto cleanup;
+        return;
     }
 
     if (!secret->iv) {
         error_setg(errp, "IV is required to decrypt secret");
-        goto cleanup;
+        return;
     }
 
     iv = qbase64_decode(secret->iv, -1, &ivlen, errp);
     if (!iv) {
-        goto cleanup;
+        return;
     }
     if (ivlen != 16) {
         error_setg(errp, "IV should be 16 bytes in length not %zu",
                    ivlen);
-        goto cleanup;
+        return;
     }
 
     aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256,
@@ -111,11 +113,11 @@ static void qcrypto_secret_decrypt(QCryptoSecret *secret,
                              key, keylen,
                              errp);
     if (!aes) {
-        goto cleanup;
+        return;
     }
 
     if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) {
-        goto cleanup;
+        return;
     }
 
     if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) {
@@ -124,7 +126,7 @@ static void qcrypto_secret_decrypt(QCryptoSecret *secret,
                                     &ciphertextlen,
                                     errp);
         if (!ciphertext) {
-            goto cleanup;
+            return;
         }
         plaintext = g_new0(uint8_t, ciphertextlen + 1);
     } else {
@@ -136,8 +138,7 @@ static void qcrypto_secret_decrypt(QCryptoSecret *secret,
                                plaintext,
                                ciphertextlen,
                                errp) < 0) {
-        plaintext = NULL;
-        goto cleanup;
+        return;
     }
 
     if (plaintext[ciphertextlen - 1] > 16 ||
@@ -145,9 +146,7 @@ static void qcrypto_secret_decrypt(QCryptoSecret *secret,
         error_setg(errp, "Incorrect number of padding bytes (%d) "
                    "found on decrypted data",
                    (int)plaintext[ciphertextlen - 1]);
-        g_free(plaintext);
-        plaintext = NULL;
-        goto cleanup;
+        return;
     }
 
     /* Even though plaintext may contain arbitrary NUL
@@ -156,14 +155,8 @@ static void qcrypto_secret_decrypt(QCryptoSecret *secret,
     ciphertextlen -= plaintext[ciphertextlen - 1];
     plaintext[ciphertextlen] = '\0';
 
-    *output = plaintext;
+    *output = g_steal_pointer(&plaintext);
     *outputlen = ciphertextlen;
-
- cleanup:
-    g_free(ciphertext);
-    g_free(iv);
-    g_free(key);
-    qcrypto_cipher_free(aes);
 }
 
 
diff --git a/crypto/tlscredsanon.c b/crypto/tlscredsanon.c
index d2adc7c131..a235f60146 100644
--- a/crypto/tlscredsanon.c
+++ b/crypto/tlscredsanon.c
@@ -34,9 +34,8 @@ static int
 qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
                             Error **errp)
 {
-    char *dhparams = NULL;
+    g_autofree char *dhparams = NULL;
     int ret;
-    int rv = -1;
 
     trace_qcrypto_tls_creds_anon_load(creds,
             creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
@@ -45,20 +44,20 @@ qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
         if (qcrypto_tls_creds_get_path(&creds->parent_obj,
                                        QCRYPTO_TLS_CREDS_DH_PARAMS,
                                        false, &dhparams, errp) < 0) {
-            goto cleanup;
+            return -1;
         }
 
         ret = gnutls_anon_allocate_server_credentials(&creds->data.server);
         if (ret < 0) {
             error_setg(errp, "Cannot allocate credentials: %s",
                        gnutls_strerror(ret));
-            goto cleanup;
+            return -1;
         }
 
         if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
                                                  &creds->parent_obj.dh_params,
                                                  errp) < 0) {
-            goto cleanup;
+            return -1;
         }
 
         gnutls_anon_set_server_dh_params(creds->data.server,
@@ -68,14 +67,11 @@ qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
         if (ret < 0) {
             error_setg(errp, "Cannot allocate credentials: %s",
                        gnutls_strerror(ret));
-            goto cleanup;
+            return -1;
         }
     }
 
-    rv = 0;
- cleanup:
-    g_free(dhparams);
-    return rv;
+    return 0;
 }
 
 
diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c
index 4b6cf636ce..15d12e2448 100644
--- a/crypto/tlscredspsk.c
+++ b/crypto/tlscredspsk.c
@@ -69,7 +69,8 @@ static int
 qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
                            Error **errp)
 {
-    char *pskfile = NULL, *dhparams = NULL;
+    g_autofree char *pskfile = NULL;
+    g_autofree char *dhparams = NULL;
     const char *username;
     int ret;
     int rv = -1;
@@ -139,8 +140,6 @@ qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
     rv = 0;
  cleanup:
     g_free(key.data);
-    g_free(pskfile);
-    g_free(dhparams);
     return rv;
 }
 
diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c
index 56dcef3673..01fc304e5d 100644
--- a/crypto/tlscredsx509.c
+++ b/crypto/tlscredsx509.c
@@ -378,7 +378,7 @@ qcrypto_tls_creds_load_cert(QCryptoTLSCredsX509 *creds,
 {
     gnutls_datum_t data;
     gnutls_x509_crt_t cert = NULL;
-    char *buf = NULL;
+    g_autofree char *buf = NULL;
     gsize buflen;
     GError *gerr;
     int ret = -1;
@@ -420,7 +420,6 @@ qcrypto_tls_creds_load_cert(QCryptoTLSCredsX509 *creds,
         gnutls_x509_crt_deinit(cert);
         cert = NULL;
     }
-    g_free(buf);
     return cert;
 }
 
@@ -434,9 +433,8 @@ qcrypto_tls_creds_load_ca_cert_list(QCryptoTLSCredsX509 *creds,
                                     Error **errp)
 {
     gnutls_datum_t data;
-    char *buf = NULL;
+    g_autofree char *buf = NULL;
     gsize buflen;
-    int ret = -1;
     GError *gerr = NULL;
 
     *ncerts = 0;
@@ -446,7 +444,7 @@ qcrypto_tls_creds_load_ca_cert_list(QCryptoTLSCredsX509 *creds,
         error_setg(errp, "Cannot load CA cert list %s: %s",
                    certFile, gerr->message);
         g_error_free(gerr);
-        goto cleanup;
+        return -1;
     }
 
     data.data = (unsigned char *)buf;
@@ -457,15 +455,11 @@ qcrypto_tls_creds_load_ca_cert_list(QCryptoTLSCredsX509 *creds,
         error_setg(errp,
                    "Unable to import CA certificate list %s",
                    certFile);
-        goto cleanup;
+        return -1;
     }
     *ncerts = certMax;
 
-    ret = 0;
-
- cleanup:
-    g_free(buf);
-    return ret;
+    return 0;
 }
 
 
diff --git a/hw/display/ati.c b/hw/display/ati.c
index 35f49a591b..8f940eee22 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -50,6 +50,7 @@ static void ati_vga_switch_mode(ATIVGAState *s)
         s->mode = EXT_MODE;
         if (s->regs.crtc_gen_cntl & CRTC2_EN) {
             /* CRT controller enabled, use CRTC values */
+            /* FIXME Should these be the same as VGA CRTC regs? */
             uint32_t offs = s->regs.crtc_offset & 0x07ffffff;
             int stride = (s->regs.crtc_pitch & 0x7ff) * 8;
             int bpp = 0;
@@ -89,7 +90,9 @@ static void ati_vga_switch_mode(ATIVGAState *s)
             DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs);
             vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
             vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
-            s->vga.big_endian_fb = false;
+            s->vga.big_endian_fb = (s->regs.config_cntl & APER_0_ENDIAN ||
+                                    s->regs.config_cntl & APER_1_ENDIAN ?
+                                    true : false);
             /* reset VBE regs then set up mode */
             s->vga.vbe_regs[VBE_DISPI_INDEX_XRES] = h;
             s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] = v;
@@ -101,16 +104,23 @@ static void ati_vga_switch_mode(ATIVGAState *s)
                 (s->regs.dac_cntl & DAC_8BIT_EN ? VBE_DISPI_8BIT_DAC : 0));
             /* now set offset and stride after enable as that resets these */
             if (stride) {
+                int bypp = DIV_ROUND_UP(bpp, BITS_PER_BYTE);
+
                 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_VIRT_WIDTH);
                 vbe_ioport_write_data(&s->vga, 0, stride);
-                if (offs % stride == 0) {
-                    vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_Y_OFFSET);
-                    vbe_ioport_write_data(&s->vga, 0, offs / stride);
-                } else {
-                    /* FIXME what to do with this? */
-                    error_report("VGA offset is not multiple of pitch, "
-                                 "expect bad picture");
+                stride *= bypp;
+                if (offs % stride) {
+                    DPRINTF("CRTC offset is not multiple of pitch\n");
+                    vbe_ioport_write_index(&s->vga, 0,
+                                           VBE_DISPI_INDEX_X_OFFSET);
+                    vbe_ioport_write_data(&s->vga, 0, offs % stride / bypp);
                 }
+                vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_Y_OFFSET);
+                vbe_ioport_write_data(&s->vga, 0, offs / stride);
+                DPRINTF("VBE offset (%d,%d), vbe_start_addr=%x\n",
+                        s->vga.vbe_regs[VBE_DISPI_INDEX_X_OFFSET],
+                        s->vga.vbe_regs[VBE_DISPI_INDEX_Y_OFFSET],
+                        s->vga.vbe_start_addr);
             }
         }
     } else {
@@ -132,9 +142,8 @@ static void ati_cursor_define(ATIVGAState *s)
         return; /* Do not update cursor if locked or rendered by guest */
     }
     /* FIXME handle cur_hv_offs correctly */
-    src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
-          s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
-          (s->regs.cur_hv_offs & 0xffff) * 16;
+    src = s->vga.vram_ptr + s->regs.cur_offset -
+          (s->regs.cur_hv_offs >> 16) - (s->regs.cur_hv_offs & 0xffff) * 16;
     for (i = 0; i < 64; i++) {
         for (j = 0; j < 8; j++, idx++) {
             data[idx] = src[i * 16 + j];
@@ -190,8 +199,7 @@ static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
         return;
     }
     /* FIXME handle cur_hv_offs correctly */
-    src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
-          s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
+    src = s->vga.vram_ptr + s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
     dp = &dp[vga->hw_cursor_x];
     h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
     for (i = 0; i < 8; i++) {
@@ -207,7 +215,7 @@ static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
                 }
             } else {
                 color = (xbits & BIT(7) ? s->regs.cur_color1 :
-                                          s->regs.cur_color0) << 8 | 0xff;
+                                          s->regs.cur_color0) | 0xff000000;
             }
             if (vga->hw_cursor_x + i * 8 + j >= h) {
                 return; /* end of screen, don't span to next line */
@@ -235,6 +243,21 @@ static uint64_t ati_i2c(bitbang_i2c_interface *i2c, uint64_t data, int base)
     return data;
 }
 
+static void ati_vga_update_irq(ATIVGAState *s)
+{
+    pci_set_irq(&s->dev, !!(s->regs.gen_int_status & s->regs.gen_int_cntl));
+}
+
+static void ati_vga_vblank_irq(void *opaque)
+{
+    ATIVGAState *s = opaque;
+
+    timer_mod(&s->vblank_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+              NANOSECONDS_PER_SECOND / 60);
+    s->regs.gen_int_status |= CRTC_VBLANK_INT;
+    ati_vga_update_irq(s);
+}
+
 static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
                                          unsigned int size)
 {
@@ -275,6 +298,12 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
                                 addr - (BIOS_0_SCRATCH + i * 4), size);
         break;
     }
+    case GEN_INT_CNTL:
+        val = s->regs.gen_int_cntl;
+        break;
+    case GEN_INT_STATUS:
+        val = s->regs.gen_int_status;
+        break;
     case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
         val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
                                 addr - CRTC_GEN_CNTL, size);
@@ -304,9 +333,27 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
     case PALETTE_DATA:
         val = vga_ioport_read(&s->vga, VGA_PEL_D);
         break;
+    case CNFG_CNTL:
+        val = s->regs.config_cntl;
+        break;
     case CNFG_MEMSIZE:
         val = s->vga.vram_size;
         break;
+    case CONFIG_APER_0_BASE:
+    case CONFIG_APER_1_BASE:
+        val = pci_default_read_config(&s->dev,
+                                      PCI_BASE_ADDRESS_0, size) & 0xfffffff0;
+        break;
+    case CONFIG_APER_SIZE:
+        val = s->vga.vram_size;
+        break;
+    case CONFIG_REG_1_BASE:
+        val = pci_default_read_config(&s->dev,
+                                      PCI_BASE_ADDRESS_2, size) & 0xfffffff0;
+        break;
+    case CONFIG_REG_APER_SIZE:
+        val = memory_region_size(&s->mm);
+        break;
     case MC_STATUS:
         val = 5;
         break;
@@ -486,6 +533,21 @@ static void ati_mm_write(void *opaque, hwaddr addr,
                            addr - (BIOS_0_SCRATCH + i * 4), data, size);
         break;
     }
+    case GEN_INT_CNTL:
+        s->regs.gen_int_cntl = data;
+        if (data & CRTC_VBLANK_INT) {
+            ati_vga_vblank_irq(s);
+        } else {
+            timer_del(&s->vblank_timer);
+            ati_vga_update_irq(s);
+        }
+        break;
+    case GEN_INT_STATUS:
+        data &= (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF ?
+                 0x000f040fUL : 0xfc080effUL);
+        s->regs.gen_int_status &= ~data;
+        ati_vga_update_irq(s);
+        break;
     case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
     {
         uint32_t val = s->regs.crtc_gen_cntl;
@@ -549,12 +611,15 @@ static void ati_mm_write(void *opaque, hwaddr addr,
                                addr - GPIO_MONID, data, size);
             /*
              * Rage128p accesses DDC used to get EDID via these bits.
-             * Only touch i2c when write overlaps 3rd byte because some
-             * drivers access this reg via multiple partial writes and
-             * without this spurious bits would be sent.
+             * Because some drivers access this via multiple byte writes
+             * we have to be careful when we send bits to avoid spurious
+             * changes in bitbang_i2c state. So only do it when mask is set
+             * and either the enable bits are changed or output bits changed
+             * while enabled.
              */
             if ((s->regs.gpio_monid & BIT(25)) &&
-                addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) {
+                ((addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) ||
+                 (addr == GPIO_MONID && (s->regs.gpio_monid & 0x60000)))) {
                 s->regs.gpio_monid = ati_i2c(&s->bbi2c, s->regs.gpio_monid, 1);
             }
         }
@@ -580,6 +645,9 @@ static void ati_mm_write(void *opaque, hwaddr addr,
         data >>= 8;
         vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
         break;
+    case CNFG_CNTL:
+        s->regs.config_cntl = data;
+        break;
     case CRTC_H_TOTAL_DISP:
         s->regs.crtc_h_total_disp = data & 0x07ff07ff;
         break;
@@ -870,12 +938,19 @@ static void ati_vga_realize(PCIDevice *dev, Error **errp)
     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
     pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
     pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
+
+    /* most interrupts are not yet emulated but MacOS needs at least VBlank */
+    dev->config[PCI_INTERRUPT_PIN] = 1;
+    timer_init_ns(&s->vblank_timer, QEMU_CLOCK_VIRTUAL, ati_vga_vblank_irq, s);
 }
 
 static void ati_vga_reset(DeviceState *dev)
 {
     ATIVGAState *s = ATI_VGA(dev);
 
+    timer_del(&s->vblank_timer);
+    ati_vga_update_irq(s);
+
     /* reset vga */
     vga_common_reset(&s->vga);
     s->mode = VGA_MODE;
@@ -885,6 +960,7 @@ static void ati_vga_exit(PCIDevice *dev)
 {
     ATIVGAState *s = ATI_VGA(dev);
 
+    timer_del(&s->vblank_timer);
     graphic_console_close(s->vga.con);
 }
 
diff --git a/hw/display/ati_dbg.c b/hw/display/ati_dbg.c
index 88b3a11315..0ebbd36f14 100644
--- a/hw/display/ati_dbg.c
+++ b/hw/display/ati_dbg.c
@@ -16,6 +16,7 @@ static struct ati_regdesc ati_reg_names[] = {
     {"BUS_CNTL", 0x0030},
     {"BUS_CNTL1", 0x0034},
     {"GEN_INT_CNTL", 0x0040},
+    {"GEN_INT_STATUS", 0x0044},
     {"CRTC_GEN_CNTL", 0x0050},
     {"CRTC_EXT_CNTL", 0x0054},
     {"DAC_CNTL", 0x0058},
@@ -23,11 +24,20 @@ static struct ati_regdesc ati_reg_names[] = {
     {"GPIO_DVI_DDC", 0x0064},
     {"GPIO_MONID", 0x0068},
     {"I2C_CNTL_1", 0x0094},
+    {"AMCGPIO_MASK_MIR", 0x009c},
+    {"AMCGPIO_A_MIR", 0x00a0},
+    {"AMCGPIO_Y_MIR", 0x00a4},
+    {"AMCGPIO_EN_MIR", 0x00a8},
     {"PALETTE_INDEX", 0x00b0},
     {"PALETTE_DATA", 0x00b4},
     {"CNFG_CNTL", 0x00e0},
     {"GEN_RESET_CNTL", 0x00f0},
     {"CNFG_MEMSIZE", 0x00f8},
+    {"CONFIG_APER_0_BASE", 0x0100},
+    {"CONFIG_APER_1_BASE", 0x0104},
+    {"CONFIG_APER_SIZE", 0x0108},
+    {"CONFIG_REG_1_BASE", 0x010c},
+    {"CONFIG_REG_APER_SIZE", 0x0110},
     {"MEM_CNTL", 0x0140},
     {"MC_FB_LOCATION", 0x0148},
     {"MC_AGP_LOCATION", 0x014C},
diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h
index 31a1927b3e..2a16708e4f 100644
--- a/hw/display/ati_int.h
+++ b/hw/display/ati_int.h
@@ -9,6 +9,7 @@
 #ifndef ATI_INT_H
 #define ATI_INT_H
 
+#include "qemu/timer.h"
 #include "hw/pci/pci.h"
 #include "hw/i2c/bitbang_i2c.h"
 #include "vga_int.h"
@@ -33,12 +34,15 @@
 typedef struct ATIVGARegs {
     uint32_t mm_index;
     uint32_t bios_scratch[8];
+    uint32_t gen_int_cntl;
+    uint32_t gen_int_status;
     uint32_t crtc_gen_cntl;
     uint32_t crtc_ext_cntl;
     uint32_t dac_cntl;
     uint32_t gpio_vga_ddc;
     uint32_t gpio_dvi_ddc;
     uint32_t gpio_monid;
+    uint32_t config_cntl;
     uint32_t crtc_h_total_disp;
     uint32_t crtc_h_sync_strt_wid;
     uint32_t crtc_v_total_disp;
@@ -88,6 +92,7 @@ typedef struct ATIVGAState {
     uint16_t cursor_size;
     uint32_t cursor_offset;
     QEMUCursor *cursor;
+    QEMUTimer vblank_timer;
     bitbang_i2c_interface bbi2c;
     MemoryRegion io;
     MemoryRegion mm;
diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h
index d7155c93d5..ebd37ee30d 100644
--- a/hw/display/ati_regs.h
+++ b/hw/display/ati_regs.h
@@ -34,6 +34,7 @@
 #define BUS_CNTL                                0x0030
 #define BUS_CNTL1                               0x0034
 #define GEN_INT_CNTL                            0x0040
+#define GEN_INT_STATUS                          0x0044
 #define CRTC_GEN_CNTL                           0x0050
 #define CRTC_EXT_CNTL                           0x0054
 #define DAC_CNTL                                0x0058
@@ -41,11 +42,20 @@
 #define GPIO_DVI_DDC                            0x0064
 #define GPIO_MONID                              0x0068
 #define I2C_CNTL_1                              0x0094
+#define AMCGPIO_MASK_MIR                        0x009c
+#define AMCGPIO_A_MIR                           0x00a0
+#define AMCGPIO_Y_MIR                           0x00a4
+#define AMCGPIO_EN_MIR                          0x00a8
 #define PALETTE_INDEX                           0x00b0
 #define PALETTE_DATA                            0x00b4
 #define CNFG_CNTL                               0x00e0
 #define GEN_RESET_CNTL                          0x00f0
 #define CNFG_MEMSIZE                            0x00f8
+#define CONFIG_APER_0_BASE                      0x0100
+#define CONFIG_APER_1_BASE                      0x0104
+#define CONFIG_APER_SIZE                        0x0108
+#define CONFIG_REG_1_BASE                       0x010c
+#define CONFIG_REG_APER_SIZE                    0x0110
 #define MEM_CNTL                                0x0140
 #define MC_FB_LOCATION                          0x0148
 #define MC_AGP_LOCATION                         0x014C
@@ -307,7 +317,14 @@
 #define XPLL_FB_DIV_MASK                        0x0000FF00
 #define X_MPLL_REF_DIV_MASK                     0x000000FF
 
+/* GEN_INT_CNTL) */
+#define CRTC_VBLANK_INT                         0x00000001
+#define CRTC_VLINE_INT                          0x00000002
+#define CRTC_VSYNC_INT                          0x00000004
+
 /* Config control values (CONFIG_CNTL) */
+#define APER_0_ENDIAN                           0x00000003
+#define APER_1_ENDIAN                           0x0000000c
 #define CFG_VGA_IO_DIS                          0x00000400
 
 /* CRTC control values (CRTC_GEN_CNTL) */
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 9ca7b87a80..56ab2f457f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1838,6 +1838,9 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
             ehci_set_state(q->ehci, q->async, EST_EXECUTING);
             break;
         }
+    } else if (q->dev == NULL) {
+        ehci_trace_guest_bug(q->ehci, "no device attached to queue");
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
     } else {
         p = ehci_alloc_packet(q);
         p->qtdaddr = q->qtdaddr;
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index f698224c8a..f578264948 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2543,6 +2543,9 @@ static void xhci_process_commands(XHCIState *xhci)
         case CR_GET_PORT_BANDWIDTH:
             event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter);
             break;
+        case CR_NOOP:
+            event.ccode = CC_SUCCESS;
+            break;
         case CR_VENDOR_NEC_FIRMWARE_REVISION:
             if (xhci->nec_quirks) {
                 event.type = 48; /* NEC reply */
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index fc9fe0c00f..e0f5ca6f81 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -819,8 +819,8 @@ static void usbredir_handle_interrupt_in_data(USBRedirDevice *dev,
                                               USBPacket *p, uint8_t ep)
 {
     /* Input interrupt endpoint, buffered packet input */
-    struct buf_packet *intp;
-    int status, len;
+    struct buf_packet *intp, *intp_to_free;
+    int status, len, sum;
 
     if (!dev->endpoint[EP2I(ep)].interrupt_started &&
             !dev->endpoint[EP2I(ep)].interrupt_error) {
@@ -839,9 +839,17 @@ static void usbredir_handle_interrupt_in_data(USBRedirDevice *dev,
         dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
     }
 
-    intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
+    /* check for completed interrupt message (with all fragments) */
+    sum = 0;
+    QTAILQ_FOREACH(intp, &dev->endpoint[EP2I(ep)].bufpq, next) {
+        sum += intp->len;
+        if (intp->len < dev->endpoint[EP2I(ep)].max_packet_size ||
+            sum >= p->iov.size)
+            break;
+    }
+
     if (intp == NULL) {
-        DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
+        DPRINTF2("interrupt-token-in ep %02X, no intp, buffered %d\n", ep, sum);
         /* Check interrupt_error for stream errors */
         status = dev->endpoint[EP2I(ep)].interrupt_error;
         dev->endpoint[EP2I(ep)].interrupt_error = 0;
@@ -852,18 +860,42 @@ static void usbredir_handle_interrupt_in_data(USBRedirDevice *dev,
         }
         return;
     }
-    DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
-            intp->status, intp->len);
 
-    status = intp->status;
-    len = intp->len;
-    if (len > p->iov.size) {
-        ERROR("received int data is larger then packet ep %02X\n", ep);
-        len = p->iov.size;
-        status = usb_redir_babble;
+    /* copy of completed interrupt message */
+    sum = 0;
+    status = usb_redir_success;
+    intp_to_free = NULL;
+    QTAILQ_FOREACH(intp, &dev->endpoint[EP2I(ep)].bufpq, next) {
+        if (intp_to_free) {
+            bufp_free(dev, intp_to_free, ep);
+        }
+        DPRINTF("interrupt-token-in ep %02X fragment status %d len %d\n", ep,
+                intp->status, intp->len);
+
+        sum += intp->len;
+        len = intp->len;
+        if (status == usb_redir_success) {
+            status = intp->status;
+        }
+        if (sum > p->iov.size) {
+            ERROR("received int data is larger then packet ep %02X\n", ep);
+            len -= (sum - p->iov.size);
+            sum = p->iov.size;
+            status = usb_redir_babble;
+        }
+
+        usb_packet_copy(p, intp->data, len);
+
+        intp_to_free = intp;
+        if (intp->len < dev->endpoint[EP2I(ep)].max_packet_size ||
+            sum >= p->iov.size)
+            break;
+    }
+    if (intp_to_free) {
+        bufp_free(dev, intp_to_free, ep);
     }
-    usb_packet_copy(p, intp->data, len);
-    bufp_free(dev, intp, ep);
+    DPRINTF("interrupt-token-in ep %02X summary status %d len %d\n", ep,
+            status, sum);
     usbredir_handle_status(dev, p, status);
 }
 
@@ -1499,6 +1531,11 @@ static void usbredir_check_bulk_receiving(USBRedirDevice *dev)
     for (i = EP2I(USB_DIR_IN); i < MAX_ENDPOINTS; i++) {
         dev->endpoint[i].bulk_receiving_enabled = 0;
     }
+
+    if (dev->interface_info.interface_count == NO_INTERFACE_INFO) {
+        return;
+    }
+
     for (i = 0; i < dev->interface_info.interface_count; i++) {
         quirks = usb_get_quirks(dev->device_info.vendor_id,
                                 dev->device_info.product_id,
@@ -2036,22 +2073,17 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
     }
 
     if (ep & USB_DIR_IN) {
-        bool q_was_empty;
-
         if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
             DPRINTF("received int packet while not started ep %02X\n", ep);
             free(data);
             return;
         }
 
-        q_was_empty = QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq);
-
         /* bufp_alloc also adds the packet to the ep queue */
         bufp_alloc(dev, data, data_len, interrupt_packet->status, ep, data);
 
-        if (q_was_empty) {
-            usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f), 0);
-        }
+        /* insufficient data solved with USB_RET_NAK */
+        usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f), 0);
     } else {
         /*
          * We report output interrupt packets as completed directly upon
diff --git a/include/crypto/block.h b/include/crypto/block.h
index fe12899831..d49d2c2da9 100644
--- a/include/crypto/block.h
+++ b/include/crypto/block.h
@@ -268,4 +268,6 @@ uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block);
  */
 void qcrypto_block_free(QCryptoBlock *block);
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlock, qcrypto_block_free)
+
 #endif /* QCRYPTO_BLOCK_H */
diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h
index cac90b410c..5928e5ecc7 100644
--- a/include/crypto/cipher.h
+++ b/include/crypto/cipher.h
@@ -170,6 +170,8 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
  */
 void qcrypto_cipher_free(QCryptoCipher *cipher);
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoCipher, qcrypto_cipher_free)
+
 /**
  * qcrypto_cipher_encrypt:
  * @cipher: the cipher object
diff --git a/include/crypto/hmac.h b/include/crypto/hmac.h
index aa3c97a2ff..ad4d778416 100644
--- a/include/crypto/hmac.h
+++ b/include/crypto/hmac.h
@@ -65,6 +65,8 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
  */
 void qcrypto_hmac_free(QCryptoHmac *hmac);
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoHmac, qcrypto_hmac_free)
+
 /**
  * qcrypto_hmac_bytesv:
  * @hmac: the hmac object
diff --git a/include/crypto/ivgen.h b/include/crypto/ivgen.h
index 9b4a62f7bb..e41521519c 100644
--- a/include/crypto/ivgen.h
+++ b/include/crypto/ivgen.h
@@ -203,4 +203,6 @@ QCryptoHashAlgorithm qcrypto_ivgen_get_hash(QCryptoIVGen *ivgen);
  */
 void qcrypto_ivgen_free(QCryptoIVGen *ivgen);
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoIVGen, qcrypto_ivgen_free)
+
 #endif /* QCRYPTO_IVGEN_H */
diff --git a/include/crypto/tlssession.h b/include/crypto/tlssession.h
index 816300cdcc..e01e1a9dc2 100644
--- a/include/crypto/tlssession.h
+++ b/include/crypto/tlssession.h
@@ -160,6 +160,8 @@ QCryptoTLSSession *qcrypto_tls_session_new(QCryptoTLSCreds *creds,
  */
 void qcrypto_tls_session_free(QCryptoTLSSession *sess);
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSSession, qcrypto_tls_session_free)
+
 /**
  * qcrypto_tls_session_check_credentials:
  * @sess: the TLS session object
diff --git a/include/glib-compat.h b/include/glib-compat.h
index 1291628e09..0b0ec76299 100644
--- a/include/glib-compat.h
+++ b/include/glib-compat.h
@@ -19,12 +19,12 @@
 /* Ask for warnings for anything that was marked deprecated in
  * the defined version, or before. It is a candidate for rewrite.
  */
-#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_40
+#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_48
 
 /* Ask for warnings if code tries to use function that did not
  * exist in the defined version. These risk breaking builds
  */
-#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_40
+#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_48
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -63,26 +63,6 @@
  * without generating warnings.
  */
 
-static inline gboolean g_strv_contains_qemu(const gchar *const *strv,
-                                            const gchar *str)
-{
-#if GLIB_CHECK_VERSION(2, 44, 0)
-    return g_strv_contains(strv, str);
-#else
-    g_return_val_if_fail(strv != NULL, FALSE);
-    g_return_val_if_fail(str != NULL, FALSE);
-
-    for (; *strv != NULL; strv++) {
-        if (g_str_equal(str, *strv)) {
-            return TRUE;
-        }
-    }
-
-    return FALSE;
-#endif
-}
-#define g_strv_contains(a, b) g_strv_contains_qemu(a, b)
-
 #if defined(_WIN32) && !GLIB_CHECK_VERSION(2, 50, 0)
 /*
  * g_poll has a problem on Windows when using
@@ -92,24 +72,6 @@ static inline gboolean g_strv_contains_qemu(const gchar *const *strv,
 gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout);
 #endif
 
-
-#ifndef g_assert_cmpmem
-#define g_assert_cmpmem(m1, l1, m2, l2)                                        \
-    do {                                                                       \
-        gconstpointer __m1 = m1, __m2 = m2;                                    \
-        int __l1 = l1, __l2 = l2;                                              \
-        if (__l1 != __l2) {                                                    \
-            g_assertion_message_cmpnum(                                        \
-                G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC,                   \
-                #l1 " (len(" #m1 ")) == " #l2 " (len(" #m2 "))", __l1, "==",   \
-                __l2, 'i');                                                    \
-        } else if (memcmp(__m1, __m2, __l1) != 0) {                            \
-            g_assertion_message(G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC,   \
-                                "assertion failed (" #m1 " == " #m2 ")");      \
-        }                                                                      \
-    } while (0)
-#endif
-
 #pragma GCC diagnostic pop
 
 #endif
diff --git a/include/qemu/module.h b/include/qemu/module.h
index db3065381d..65ba596e46 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -65,6 +65,6 @@ void register_module_init(void (*fn)(void), module_init_type type);
 void register_dso_module_init(void (*fn)(void), module_init_type type);
 
 void module_call_init(module_init_type type);
-void module_load_one(const char *prefix, const char *lib_name);
+bool module_load_one(const char *prefix, const char *lib_name);
 
 #endif
diff --git a/io/task.c b/io/task.c
index 64c4c7126a..1ae7b86488 100644
--- a/io/task.c
+++ b/io/task.c
@@ -136,6 +136,7 @@ static gpointer qio_task_thread_worker(gpointer opaque)
                           qio_task_thread_result, task, NULL);
     g_source_attach(task->thread->completion,
                     task->thread->context);
+    g_source_unref(task->thread->completion);
     trace_qio_task_thread_source_attach(task, task->thread->completion);
 
     qemu_cond_signal(&task->thread_cond);
diff --git a/memory.c b/memory.c
index 4aa38eb5b1..7fd93b1d42 100644
--- a/memory.c
+++ b/memory.c
@@ -217,7 +217,6 @@ struct FlatRange {
     bool romd_mode;
     bool readonly;
     bool nonvolatile;
-    int has_coalesced_range;
 };
 
 #define FOR_EACH_FLAT_RANGE(var, view)          \
@@ -654,7 +653,6 @@ static void render_memory_region(FlatView *view,
     fr.romd_mode = mr->romd_mode;
     fr.readonly = readonly;
     fr.nonvolatile = nonvolatile;
-    fr.has_coalesced_range = 0;
 
     /* Render the region itself into any gaps left by the current view. */
     for (i = 0; i < view->nr && int128_nz(remain); ++i) {
@@ -855,46 +853,55 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     flatview_unref(view);
 }
 
-static void flat_range_coalesced_io_del(FlatRange *fr, AddressSpace *as)
+/*
+ * Notify the memory listeners about the coalesced IO change events of
+ * range `cmr'.  Only the part that has intersection of the specified
+ * FlatRange will be sent.
+ */
+static void flat_range_coalesced_io_notify(FlatRange *fr, AddressSpace *as,
+                                           CoalescedMemoryRange *cmr, bool add)
 {
-    if (!fr->has_coalesced_range) {
+    AddrRange tmp;
+
+    tmp = addrrange_shift(cmr->addr,
+                          int128_sub(fr->addr.start,
+                                     int128_make64(fr->offset_in_region)));
+    if (!addrrange_intersects(tmp, fr->addr)) {
         return;
     }
+    tmp = addrrange_intersection(tmp, fr->addr);
 
-    if (--fr->has_coalesced_range > 0) {
-        return;
+    if (add) {
+        MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, coalesced_io_add,
+                                      int128_get64(tmp.start),
+                                      int128_get64(tmp.size));
+    } else {
+        MEMORY_LISTENER_UPDATE_REGION(fr, as, Reverse, coalesced_io_del,
+                                      int128_get64(tmp.start),
+                                      int128_get64(tmp.size));
     }
+}
 
-    MEMORY_LISTENER_UPDATE_REGION(fr, as, Reverse, coalesced_io_del,
-                                  int128_get64(fr->addr.start),
-                                  int128_get64(fr->addr.size));
+static void flat_range_coalesced_io_del(FlatRange *fr, AddressSpace *as)
+{
+    CoalescedMemoryRange *cmr;
+
+    QTAILQ_FOREACH(cmr, &fr->mr->coalesced, link) {
+        flat_range_coalesced_io_notify(fr, as, cmr, false);
+    }
 }
 
 static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as)
 {
     MemoryRegion *mr = fr->mr;
     CoalescedMemoryRange *cmr;
-    AddrRange tmp;
 
     if (QTAILQ_EMPTY(&mr->coalesced)) {
         return;
     }
 
-    if (fr->has_coalesced_range++) {
-        return;
-    }
-
     QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
-        tmp = addrrange_shift(cmr->addr,
-                              int128_sub(fr->addr.start,
-                                         int128_make64(fr->offset_in_region)));
-        if (!addrrange_intersects(tmp, fr->addr)) {
-            continue;
-        }
-        tmp = addrrange_intersection(tmp, fr->addr);
-        MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, coalesced_io_add,
-                                      int128_get64(tmp.start),
-                                      int128_get64(tmp.size));
+        flat_range_coalesced_io_notify(fr, as, cmr, true);
     }
 }
 
@@ -2236,27 +2243,26 @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp
     qemu_ram_resize(mr->ram_block, newsize, errp);
 }
 
-static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as)
+/*
+ * Call proper memory listeners about the change on the newly
+ * added/removed CoalescedMemoryRange.
+ */
+static void memory_region_update_coalesced_range(MemoryRegion *mr,
+                                                 CoalescedMemoryRange *cmr,
+                                                 bool add)
 {
+    AddressSpace *as;
     FlatView *view;
     FlatRange *fr;
 
-    view = address_space_get_flatview(as);
-    FOR_EACH_FLAT_RANGE(fr, view) {
-        if (fr->mr == mr) {
-            flat_range_coalesced_io_del(fr, as);
-            flat_range_coalesced_io_add(fr, as);
-        }
-    }
-    flatview_unref(view);
-}
-
-static void memory_region_update_coalesced_range(MemoryRegion *mr)
-{
-    AddressSpace *as;
-
     QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
-        memory_region_update_coalesced_range_as(mr, as);
+        view = address_space_get_flatview(as);
+        FOR_EACH_FLAT_RANGE(fr, view) {
+            if (fr->mr == mr) {
+                flat_range_coalesced_io_notify(fr, as, cmr, add);
+            }
+        }
+        flatview_unref(view);
     }
 }
 
@@ -2274,14 +2280,17 @@ void memory_region_add_coalescing(MemoryRegion *mr,
 
     cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size));
     QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
-    memory_region_update_coalesced_range(mr);
+    memory_region_update_coalesced_range(mr, cmr, true);
     memory_region_set_flush_coalesced(mr);
 }
 
 void memory_region_clear_coalescing(MemoryRegion *mr)
 {
     CoalescedMemoryRange *cmr;
-    bool updated = false;
+
+    if (QTAILQ_EMPTY(&mr->coalesced)) {
+        return;
+    }
 
     qemu_flush_coalesced_mmio_buffer();
     mr->flush_coalesced_mmio = false;
@@ -2289,12 +2298,8 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
     while (!QTAILQ_EMPTY(&mr->coalesced)) {
         cmr = QTAILQ_FIRST(&mr->coalesced);
         QTAILQ_REMOVE(&mr->coalesced, cmr, link);
+        memory_region_update_coalesced_range(mr, cmr, false);
         g_free(cmr);
-        updated = true;
-    }
-
-    if (updated) {
-        memory_region_update_coalesced_range(mr);
     }
 }
 
diff --git a/qapi/ui.json b/qapi/ui.json
index 59e412139a..e04525d8b4 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1025,7 +1025,8 @@
 #
 ##
 { 'enum': 'GrabToggleKeys',
-  'data': [ 'ctrl-ctrl', 'alt-alt', 'meta-meta', 'scrolllock', 'ctrl-scrolllock' ] }
+  'data': [ 'ctrl-ctrl', 'alt-alt', 'shift-shift','meta-meta', 'scrolllock',
+            'ctrl-scrolllock' ] }
 
 ##
 # @DisplayGTK:
diff --git a/qemu-options.hx b/qemu-options.hx
index a308e5f5aa..ea0638e92d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1436,12 +1436,15 @@ STEXI
 ETEXI
 
 DEF("usb", 0, QEMU_OPTION_usb,
-    "-usb            enable the USB driver (if it is not used by default yet)\n",
+    "-usb            enable on-board USB host controller (if not enabled by default)\n",
     QEMU_ARCH_ALL)
 STEXI
 @item -usb
 @findex -usb
-Enable the USB driver (if it is not used by default yet).
+Enable USB emulation on machine types with an on-board USB host controller (if
+not enabled by default).  Note that on-board USB host controllers may not
+support USB 3.0.  In this case @option{-device qemu-xhci} can be used instead
+on machines with PCI.
 ETEXI
 
 DEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice,
diff --git a/qtest.c b/qtest.c
index d8b4857c74..8b50e2783e 100644
--- a/qtest.c
+++ b/qtest.c
@@ -661,6 +661,15 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         qtest_send_prefix(chr);
         qtest_sendf(chr, "OK %"PRIi64"\n",
                     (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+    } else if (strcmp(words[0], "module_load") == 0) {
+        g_assert(words[1] && words[2]);
+
+        qtest_send_prefix(chr);
+        if (module_load_one(words[1], words[2])) {
+            qtest_sendf(chr, "OK\n");
+        } else {
+            qtest_sendf(chr, "FAIL\n");
+        }
     } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
         int64_t ns;
         int ret;
diff --git a/scripts/minikconf.py b/scripts/minikconf.py
index 3109a81db7..40ae1989e1 100644
--- a/scripts/minikconf.py
+++ b/scripts/minikconf.py
@@ -702,8 +702,8 @@ if __name__ == '__main__':
 
     config = data.compute_config()
     for key in sorted(config.keys()):
-        if key not in external_vars:
-            print ('CONFIG_%s=%s' % (key, ('y' if config[key] else 'n')))
+        if key not in external_vars and config[key]:
+            print ('CONFIG_%s=y' % key)
 
     deps = open(argv[2], 'w')
     for fname in data.previously_included:
diff --git a/target/tricore/helper.h b/target/tricore/helper.h
index b64780c37d..78176aa17a 100644
--- a/target/tricore/helper.h
+++ b/target/tricore/helper.h
@@ -153,3 +153,4 @@ DEF_HELPER_2(psw_write, void, env, i32)
 DEF_HELPER_1(psw_read, i32, env)
 /* Exceptions */
 DEF_HELPER_3(raise_exception_sync, noreturn, env, i32, i32)
+DEF_HELPER_2(qemu_excp, noreturn, env, i32)
diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
index 9476d10d00..32c2bc1699 100644
--- a/target/tricore/op_helper.c
+++ b/target/tricore/op_helper.c
@@ -107,6 +107,13 @@ static void raise_exception_sync_helper(CPUTriCoreState *env, uint32_t class,
     raise_exception_sync_internal(env, class, tin, pc, 0);
 }
 
+void helper_qemu_excp(CPUTriCoreState *env, uint32_t excp)
+{
+    CPUState *cs = env_cpu(env);
+    cs->exception_index = excp;
+    cpu_loop_exit(cs);
+}
+
 /* Addressing mode helper */
 
 static uint16_t reverse16(uint16_t val)
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index dc2a65f3f9..4f10407477 100644
--- a/target/tricore/translate.c
+++ b/target/tricore/translate.c
@@ -30,6 +30,7 @@
 #include "exec/helper-gen.h"
 
 #include "tricore-opcodes.h"
+#include "exec/translator.h"
 #include "exec/log.h"
 
 /*
@@ -64,25 +65,16 @@ static const char *regnames_d[] = {
     };
 
 typedef struct DisasContext {
-    struct TranslationBlock *tb;
-    target_ulong pc, saved_pc, next_pc;
+    DisasContextBase base;
+    CPUTriCoreState *env;
+    target_ulong pc_succ_insn;
     uint32_t opcode;
-    int singlestep_enabled;
     /* Routine used to access memory */
     int mem_idx;
     uint32_t hflags, saved_hflags;
-    int bstate;
 } DisasContext;
 
 enum {
-
-    BS_NONE   = 0,
-    BS_STOP   = 1,
-    BS_BRANCH = 2,
-    BS_EXCP   = 3,
-};
-
-enum {
     MODE_LL = 0,
     MODE_LU = 1,
     MODE_UL = 2,
@@ -378,13 +370,13 @@ static void gen_swapmsk(DisasContext *ctx, int reg, TCGv ea)
    These makros also specify in which ISA version the csfr was introduced. */
 #define R(ADDRESS, REG, FEATURE)                                         \
     case ADDRESS:                                                        \
-        if (tricore_feature(env, FEATURE)) {                             \
+        if (tricore_feature(ctx->env, FEATURE)) {                        \
             tcg_gen_ld_tl(ret, cpu_env, offsetof(CPUTriCoreState, REG)); \
         }                                                                \
         break;
 #define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE)
 #define E(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE)
-static inline void gen_mfcr(CPUTriCoreState *env, TCGv ret, int32_t offset)
+static inline void gen_mfcr(DisasContext *ctx, TCGv ret, int32_t offset)
 {
     /* since we're caching PSW make this a special case */
     if (offset == 0xfe04) {
@@ -403,7 +395,7 @@ static inline void gen_mfcr(CPUTriCoreState *env, TCGv ret, int32_t offset)
                                     since no execption occurs */
 #define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE)                \
     case ADDRESS:                                                        \
-        if (tricore_feature(env, FEATURE)) {                             \
+        if (tricore_feature(ctx->env, FEATURE)) {                        \
             tcg_gen_st_tl(r1, cpu_env, offsetof(CPUTriCoreState, REG));  \
         }                                                                \
         break;
@@ -412,7 +404,7 @@ static inline void gen_mfcr(CPUTriCoreState *env, TCGv ret, int32_t offset)
          watchdog device, we handle endinit protected registers like
          all-access registers for now. */
 #define E(ADDRESS, REG, FEATURE) A(ADDRESS, REG, FEATURE)
-static inline void gen_mtcr(CPUTriCoreState *env, DisasContext *ctx, TCGv r1,
+static inline void gen_mtcr(DisasContext *ctx, TCGv r1,
                             int32_t offset)
 {
     if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM) {
@@ -1102,7 +1094,7 @@ gen_maddrs_q(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n)
 
 static inline void
 gen_madd32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n,
-             uint32_t up_shift, CPUTriCoreState *env)
+             uint32_t up_shift)
 {
     TCGv temp = tcg_temp_new();
     TCGv temp2 = tcg_temp_new();
@@ -1263,7 +1255,7 @@ gen_m16adds64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
 
 static inline void
 gen_madd64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
-             TCGv arg3, uint32_t n, CPUTriCoreState *env)
+             TCGv arg3, uint32_t n)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
     TCGv_i64 t2 = tcg_temp_new_i64();
@@ -1961,7 +1953,7 @@ gen_msubrs_q(TCGv ret, TCGv r1, TCGv r2, TCGv r3, uint32_t n)
 
 static inline void
 gen_msub32_q(TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, uint32_t n,
-             uint32_t up_shift, CPUTriCoreState *env)
+             uint32_t up_shift)
 {
     TCGv temp = tcg_temp_new();
     TCGv temp2 = tcg_temp_new();
@@ -2116,7 +2108,7 @@ gen_m16subs64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
 
 static inline void
 gen_msub64_q(TCGv rl, TCGv rh, TCGv arg1_low, TCGv arg1_high, TCGv arg2,
-             TCGv arg3, uint32_t n, CPUTriCoreState *env)
+             TCGv arg3, uint32_t n)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
     TCGv_i64 t2 = tcg_temp_new_i64();
@@ -3162,11 +3154,11 @@ static inline void gen_unpack(TCGv rl, TCGv rh, TCGv r1)
 }
 
 static inline void
-gen_dvinit_b(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+gen_dvinit_b(DisasContext *ctx, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
 {
     TCGv_i64 ret = tcg_temp_new_i64();
 
-    if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+    if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
         gen_helper_dvinit_b_13(ret, cpu_env, r1, r2);
     } else {
         gen_helper_dvinit_b_131(ret, cpu_env, r1, r2);
@@ -3177,11 +3169,11 @@ gen_dvinit_b(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
 }
 
 static inline void
-gen_dvinit_h(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+gen_dvinit_h(DisasContext *ctx, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
 {
     TCGv_i64 ret = tcg_temp_new_i64();
 
-    if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+    if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
         gen_helper_dvinit_h_13(ret, cpu_env, r1, r2);
     } else {
         gen_helper_dvinit_h_131(ret, cpu_env, r1, r2);
@@ -3230,12 +3222,12 @@ static inline void gen_save_pc(target_ulong pc)
 
 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
 {
-    if (unlikely(ctx->singlestep_enabled)) {
+    if (unlikely(ctx->base.singlestep_enabled)) {
         return false;
     }
 
 #ifndef CONFIG_USER_ONLY
-    return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
+    return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
 #else
     return true;
 #endif
@@ -3246,10 +3238,10 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
     if (use_goto_tb(ctx, dest)) {
         tcg_gen_goto_tb(n);
         gen_save_pc(dest);
-        tcg_gen_exit_tb(ctx->tb, n);
+        tcg_gen_exit_tb(ctx->base.tb, n);
     } else {
         gen_save_pc(dest);
-        if (ctx->singlestep_enabled) {
+        if (ctx->base.singlestep_enabled) {
             /* raise exception debug */
         }
         tcg_gen_exit_tb(NULL, 0);
@@ -3261,24 +3253,33 @@ static void generate_trap(DisasContext *ctx, int class, int tin)
     TCGv_i32 classtemp = tcg_const_i32(class);
     TCGv_i32 tintemp = tcg_const_i32(tin);
 
-    gen_save_pc(ctx->pc);
+    gen_save_pc(ctx->base.pc_next);
     gen_helper_raise_exception_sync(cpu_env, classtemp, tintemp);
-    ctx->bstate = BS_EXCP;
+    ctx->base.is_jmp = DISAS_NORETURN;
 
     tcg_temp_free(classtemp);
     tcg_temp_free(tintemp);
 }
 
+static void generate_qemu_excp(DisasContext *ctx, int excp)
+{
+    TCGv_i32 tmp = tcg_const_i32(excp);
+    gen_save_pc(ctx->base.pc_next);
+    gen_helper_qemu_excp(cpu_env, tmp);
+    ctx->base.is_jmp = DISAS_NORETURN;
+    tcg_temp_free(tmp);
+}
+
 static inline void gen_branch_cond(DisasContext *ctx, TCGCond cond, TCGv r1,
                                    TCGv r2, int16_t address)
 {
     TCGLabel *jumpLabel = gen_new_label();
     tcg_gen_brcond_tl(cond, r1, r2, jumpLabel);
 
-    gen_goto_tb(ctx, 1, ctx->next_pc);
+    gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
 
     gen_set_label(jumpLabel);
-    gen_goto_tb(ctx, 0, ctx->pc + address * 2);
+    gen_goto_tb(ctx, 0, ctx->base.pc_next + address * 2);
 }
 
 static inline void gen_branch_condi(DisasContext *ctx, TCGCond cond, TCGv r1,
@@ -3295,9 +3296,9 @@ static void gen_loop(DisasContext *ctx, int r1, int32_t offset)
 
     tcg_gen_subi_tl(cpu_gpr_a[r1], cpu_gpr_a[r1], 1);
     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr_a[r1], -1, l1);
-    gen_goto_tb(ctx, 1, ctx->pc + offset);
+    gen_goto_tb(ctx, 1, ctx->base.pc_next + offset);
     gen_set_label(l1);
-    gen_goto_tb(ctx, 0, ctx->next_pc);
+    gen_goto_tb(ctx, 0, ctx->pc_succ_insn);
 }
 
 static void gen_fcall_save_ctx(DisasContext *ctx)
@@ -3306,7 +3307,7 @@ static void gen_fcall_save_ctx(DisasContext *ctx)
 
     tcg_gen_addi_tl(temp, cpu_gpr_a[10], -4);
     tcg_gen_qemu_st_tl(cpu_gpr_a[11], temp, ctx->mem_idx, MO_LESL);
-    tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
+    tcg_gen_movi_tl(cpu_gpr_a[11], ctx->pc_succ_insn);
     tcg_gen_mov_tl(cpu_gpr_a[10], temp);
 
     tcg_temp_free(temp);
@@ -3321,7 +3322,7 @@ static void gen_fret(DisasContext *ctx)
     tcg_gen_addi_tl(cpu_gpr_a[10], cpu_gpr_a[10], 4);
     tcg_gen_mov_tl(cpu_PC, temp);
     tcg_gen_exit_tb(NULL, 0);
-    ctx->bstate = BS_BRANCH;
+    ctx->base.is_jmp = DISAS_NORETURN;
 
     tcg_temp_free(temp);
 }
@@ -3336,12 +3337,12 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
 /* SB-format jumps */
     case OPC1_16_SB_J:
     case OPC1_32_B_J:
-        gen_goto_tb(ctx, 0, ctx->pc + offset * 2);
+        gen_goto_tb(ctx, 0, ctx->base.pc_next + offset * 2);
         break;
     case OPC1_32_B_CALL:
     case OPC1_16_SB_CALL:
-        gen_helper_1arg(call, ctx->next_pc);
-        gen_goto_tb(ctx, 0, ctx->pc + offset * 2);
+        gen_helper_1arg(call, ctx->pc_succ_insn);
+        gen_goto_tb(ctx, 0, ctx->base.pc_next + offset * 2);
         break;
     case OPC1_16_SB_JZ:
         gen_branch_condi(ctx, TCG_COND_EQ, cpu_gpr_d[15], 0, offset);
@@ -3433,26 +3434,26 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
         break;
 /* B-format */
     case OPC1_32_B_CALLA:
-        gen_helper_1arg(call, ctx->next_pc);
+        gen_helper_1arg(call, ctx->pc_succ_insn);
         gen_goto_tb(ctx, 0, EA_B_ABSOLUT(offset));
         break;
     case OPC1_32_B_FCALL:
         gen_fcall_save_ctx(ctx);
-        gen_goto_tb(ctx, 0, ctx->pc + offset * 2);
+        gen_goto_tb(ctx, 0, ctx->base.pc_next + offset * 2);
         break;
     case OPC1_32_B_FCALLA:
         gen_fcall_save_ctx(ctx);
         gen_goto_tb(ctx, 0, EA_B_ABSOLUT(offset));
         break;
     case OPC1_32_B_JLA:
-        tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
+        tcg_gen_movi_tl(cpu_gpr_a[11], ctx->pc_succ_insn);
         /* fall through */
     case OPC1_32_B_JA:
         gen_goto_tb(ctx, 0, EA_B_ABSOLUT(offset));
         break;
     case OPC1_32_B_JL:
-        tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
-        gen_goto_tb(ctx, 0, ctx->pc + offset * 2);
+        tcg_gen_movi_tl(cpu_gpr_a[11], ctx->pc_succ_insn);
+        gen_goto_tb(ctx, 0, ctx->base.pc_next + offset * 2);
         break;
 /* BOL format */
     case OPCM_32_BRC_EQ_NEQ:
@@ -3551,7 +3552,7 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
             gen_loop(ctx, r2, offset * 2);
         } else {
             /* OPC2_32_BRR_LOOPU */
-            gen_goto_tb(ctx, 0, ctx->pc + offset * 2);
+            gen_goto_tb(ctx, 0, ctx->base.pc_next + offset * 2);
         }
         break;
     case OPCM_32_BRR_JNE:
@@ -3585,7 +3586,7 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
     default:
         generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
     }
-    ctx->bstate = BS_BRANCH;
+    ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 
@@ -3593,7 +3594,7 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
  * Functions for decoding instructions
  */
 
-static void decode_src_opc(CPUTriCoreState *env, DisasContext *ctx, int op1)
+static void decode_src_opc(DisasContext *ctx, int op1)
 {
     int r1;
     int32_t const4;
@@ -3655,7 +3656,7 @@ static void decode_src_opc(CPUTriCoreState *env, DisasContext *ctx, int op1)
         tcg_gen_movi_tl(cpu_gpr_a[r1], const4);
         break;
     case OPC1_16_SRC_MOV_E:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             tcg_gen_movi_tl(cpu_gpr_d[r1], const4);
             tcg_gen_sari_tl(cpu_gpr_d[r1+1], cpu_gpr_d[r1], 31);
         } else {
@@ -3919,7 +3920,7 @@ static void decode_sro_opc(DisasContext *ctx, int op1)
     }
 }
 
-static void decode_sr_system(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_sr_system(DisasContext *ctx)
 {
     uint32_t op2;
     op2 = MASK_OP_SR_OP2(ctx->opcode);
@@ -3933,7 +3934,7 @@ static void decode_sr_system(CPUTriCoreState *env, DisasContext *ctx)
     case OPC2_16_SR_RFE:
         gen_helper_rfe(cpu_env);
         tcg_gen_exit_tb(NULL, 0);
-        ctx->bstate = BS_BRANCH;
+        ctx->base.is_jmp = DISAS_NORETURN;
         break;
     case OPC2_16_SR_DEBUG:
         /* raise EXCP_DEBUG */
@@ -3946,7 +3947,7 @@ static void decode_sr_system(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_sr_accu(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_sr_accu(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1;
@@ -3990,7 +3991,7 @@ static void decode_sr_accu(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_16Bit_opc(DisasContext *ctx)
 {
     int op1;
     int r1, r2;
@@ -4021,7 +4022,7 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPC1_16_SRC_MOV_E:
     case OPC1_16_SRC_SH:
     case OPC1_16_SRC_SHA:
-        decode_src_opc(env, ctx, op1);
+        decode_src_opc(ctx, op1);
         break;
 /* SRR-format */
     case OPC1_16_SRR_ADD:
@@ -4106,7 +4107,7 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
         break;
     case OPC1_16_SBC_JEQ2:
     case OPC1_16_SBC_JNE2:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             address = MASK_OP_SBC_DISP4(ctx->opcode);
             const16 = MASK_OP_SBC_CONST4_SEXT(ctx->opcode);
             gen_compute_branch(ctx, op1, 0, 0, const16, address);
@@ -4124,7 +4125,7 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
 /* SBR-format */
     case OPC1_16_SBR_JEQ2:
     case OPC1_16_SBR_JNE2:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             r1 = MASK_OP_SBR_S2(ctx->opcode);
             address = MASK_OP_SBR_DISP4(ctx->opcode);
             gen_compute_branch(ctx, op1, r1, 0, 0, address);
@@ -4204,10 +4205,10 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
         break;
 /* SR-format */
     case OPCM_16_SR_SYSTEM:
-        decode_sr_system(env, ctx);
+        decode_sr_system(ctx);
         break;
     case OPCM_16_SR_ACCU:
-        decode_sr_accu(env, ctx);
+        decode_sr_accu(ctx);
         break;
     case OPC1_16_SR_JI:
         r1 = MASK_OP_SR_S1D(ctx->opcode);
@@ -4227,7 +4228,7 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
  */
 
 /* ABS-format */
-static void decode_abs_ldw(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_abs_ldw(DisasContext *ctx)
 {
     int32_t op2;
     int32_t r1;
@@ -4262,7 +4263,7 @@ static void decode_abs_ldw(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_abs_ldb(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_abs_ldb(DisasContext *ctx)
 {
     int32_t op2;
     int32_t r1;
@@ -4295,7 +4296,7 @@ static void decode_abs_ldb(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_abs_ldst_swap(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_abs_ldst_swap(DisasContext *ctx)
 {
     int32_t op2;
     int32_t r1;
@@ -4322,7 +4323,7 @@ static void decode_abs_ldst_swap(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_abs_ldst_context(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_abs_ldst_context(DisasContext *ctx)
 {
     uint32_t op2;
     int32_t off18;
@@ -4348,7 +4349,7 @@ static void decode_abs_ldst_context(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_abs_store(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_abs_store(DisasContext *ctx)
 {
     int32_t op2;
     int32_t r1;
@@ -4382,7 +4383,7 @@ static void decode_abs_store(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_abs_storeb_h(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_abs_storeb_h(DisasContext *ctx)
 {
     int32_t op2;
     int32_t r1;
@@ -4410,7 +4411,7 @@ static void decode_abs_storeb_h(CPUTriCoreState *env, DisasContext *ctx)
 
 /* Bit-format */
 
-static void decode_bit_andacc(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_bit_andacc(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -4451,7 +4452,7 @@ static void decode_bit_andacc(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_bit_logical_t(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_bit_logical_t(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -4485,7 +4486,7 @@ static void decode_bit_logical_t(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_bit_insert(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_bit_insert(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -4508,7 +4509,7 @@ static void decode_bit_insert(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_bit_logical_t2(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_bit_logical_t2(DisasContext *ctx)
 {
     uint32_t op2;
 
@@ -4544,7 +4545,7 @@ static void decode_bit_logical_t2(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_bit_orand(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_bit_orand(DisasContext *ctx)
 {
     uint32_t op2;
 
@@ -4585,7 +4586,7 @@ static void decode_bit_orand(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_bit_sh_logic1(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_bit_sh_logic1(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -4626,7 +4627,7 @@ static void decode_bit_sh_logic1(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_bit_sh_logic2(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_bit_sh_logic2(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -4670,8 +4671,7 @@ static void decode_bit_sh_logic2(CPUTriCoreState *env, DisasContext *ctx)
 /* BO-format */
 
 
-static void decode_bo_addrmode_post_pre_base(CPUTriCoreState *env,
-                                             DisasContext *ctx)
+static void decode_bo_addrmode_post_pre_base(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t off10;
@@ -4705,13 +4705,13 @@ static void decode_bo_addrmode_post_pre_base(CPUTriCoreState *env,
         break;
     case OPC2_32_BO_CACHEI_WI_SHORTOFF:
     case OPC2_32_BO_CACHEI_W_SHORTOFF:
-        if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+        if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
         }
         break;
     case OPC2_32_BO_CACHEI_W_POSTINC:
     case OPC2_32_BO_CACHEI_WI_POSTINC:
-        if (tricore_feature(env, TRICORE_FEATURE_131)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
             tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -4719,7 +4719,7 @@ static void decode_bo_addrmode_post_pre_base(CPUTriCoreState *env,
         break;
     case OPC2_32_BO_CACHEI_W_PREINC:
     case OPC2_32_BO_CACHEI_WI_PREINC:
-        if (tricore_feature(env, TRICORE_FEATURE_131)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
             tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -4830,8 +4830,7 @@ static void decode_bo_addrmode_post_pre_base(CPUTriCoreState *env,
     }
 }
 
-static void decode_bo_addrmode_bitreverse_circular(CPUTriCoreState *env,
-                                                   DisasContext *ctx)
+static void decode_bo_addrmode_bitreverse_circular(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t off10;
@@ -4941,8 +4940,7 @@ static void decode_bo_addrmode_bitreverse_circular(CPUTriCoreState *env,
     tcg_temp_free(temp3);
 }
 
-static void decode_bo_addrmode_ld_post_pre_base(CPUTriCoreState *env,
-                                                DisasContext *ctx)
+static void decode_bo_addrmode_ld_post_pre_base(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t off10;
@@ -5076,8 +5074,7 @@ static void decode_bo_addrmode_ld_post_pre_base(CPUTriCoreState *env,
     }
 }
 
-static void decode_bo_addrmode_ld_bitreverse_circular(CPUTriCoreState *env,
-                                                DisasContext *ctx)
+static void decode_bo_addrmode_ld_bitreverse_circular(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t off10;
@@ -5195,8 +5192,7 @@ static void decode_bo_addrmode_ld_bitreverse_circular(CPUTriCoreState *env,
     tcg_temp_free(temp3);
 }
 
-static void decode_bo_addrmode_stctx_post_pre_base(CPUTriCoreState *env,
-                                                   DisasContext *ctx)
+static void decode_bo_addrmode_stctx_post_pre_base(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t off10;
@@ -5288,8 +5284,7 @@ static void decode_bo_addrmode_stctx_post_pre_base(CPUTriCoreState *env,
     tcg_temp_free(temp2);
 }
 
-static void decode_bo_addrmode_ldmst_bitreverse_circular(CPUTriCoreState *env,
-                                                         DisasContext *ctx)
+static void decode_bo_addrmode_ldmst_bitreverse_circular(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t off10;
@@ -5351,7 +5346,7 @@ static void decode_bo_addrmode_ldmst_bitreverse_circular(CPUTriCoreState *env,
     tcg_temp_free(temp3);
 }
 
-static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
+static void decode_bol_opc(DisasContext *ctx, int32_t op1)
 {
     int r1, r2;
     int32_t address;
@@ -5378,7 +5373,7 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
         tcg_gen_addi_tl(cpu_gpr_a[r1], cpu_gpr_a[r2], address);
         break;
     case OPC1_32_BOL_ST_A_LONGOFF:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             gen_offset_st(ctx, cpu_gpr_a[r1], cpu_gpr_a[r2], address, MO_LEUL);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -5388,42 +5383,42 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
         gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL);
         break;
     case OPC1_32_BOL_LD_B_LONGOFF:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
         }
         break;
     case OPC1_32_BOL_LD_BU_LONGOFF:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_UB);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
         }
         break;
     case OPC1_32_BOL_LD_H_LONGOFF:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
         }
         break;
     case OPC1_32_BOL_LD_HU_LONGOFF:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUW);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
         }
         break;
     case OPC1_32_BOL_ST_B_LONGOFF:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
         }
         break;
     case OPC1_32_BOL_ST_H_LONGOFF:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -5435,7 +5430,7 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
 }
 
 /* RC format */
-static void decode_rc_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rc_logical_shift(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2;
@@ -5502,7 +5497,7 @@ static void decode_rc_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_rc_accumulator(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rc_accumulator(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2;
@@ -5702,7 +5697,7 @@ static void decode_rc_accumulator(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_rc_serviceroutine(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rc_serviceroutine(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t const9;
@@ -5722,7 +5717,7 @@ static void decode_rc_serviceroutine(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rc_mul(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rc_mul(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2;
@@ -5760,7 +5755,7 @@ static void decode_rc_mul(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RCPW format */
-static void decode_rcpw_insert(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rcpw_insert(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2;
@@ -5799,7 +5794,7 @@ static void decode_rcpw_insert(CPUTriCoreState *env, DisasContext *ctx)
 
 /* RCRW format */
 
-static void decode_rcrw_insert(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rcrw_insert(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r3, r4;
@@ -5844,7 +5839,7 @@ static void decode_rcrw_insert(CPUTriCoreState *env, DisasContext *ctx)
 
 /* RCR format */
 
-static void decode_rcr_cond_select(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rcr_cond_select(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r3, r4;
@@ -5888,7 +5883,7 @@ static void decode_rcr_cond_select(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rcr_madd(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rcr_madd(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r3, r4;
@@ -5943,7 +5938,7 @@ static void decode_rcr_madd(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rcr_msub(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rcr_msub(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r3, r4;
@@ -6000,7 +5995,7 @@ static void decode_rcr_msub(CPUTriCoreState *env, DisasContext *ctx)
 
 /* RLC format */
 
-static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
+static void decode_rlc_opc(DisasContext *ctx,
                            uint32_t op1)
 {
     int32_t const16;
@@ -6022,13 +6017,13 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
         break;
     case OPC1_32_RLC_MFCR:
         const16 = MASK_OP_RLC_CONST16(ctx->opcode);
-        gen_mfcr(env, cpu_gpr_d[r2], const16);
+        gen_mfcr(ctx, cpu_gpr_d[r2], const16);
         break;
     case OPC1_32_RLC_MOV:
         tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
         break;
     case OPC1_32_RLC_MOV_64:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             CHECK_REG_PAIR(r2);
             tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
             tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15);
@@ -6048,7 +6043,7 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
         break;
     case OPC1_32_RLC_MTCR:
         const16 = MASK_OP_RLC_CONST16(ctx->opcode);
-        gen_mtcr(env, ctx, cpu_gpr_d[r1], const16);
+        gen_mtcr(ctx, cpu_gpr_d[r1], const16);
         break;
     default:
         generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -6056,7 +6051,7 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
 }
 
 /* RR format */
-static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr_accumulator(DisasContext *ctx)
 {
     uint32_t op2;
     int r3, r2, r1;
@@ -6254,7 +6249,7 @@ static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]);
         break;
     case OPC2_32_RR_MOV_64:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             temp = tcg_temp_new();
 
             CHECK_REG_PAIR(r3);
@@ -6268,7 +6263,7 @@ static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
         }
         break;
     case OPC2_32_RR_MOVS_64:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             CHECK_REG_PAIR(r3);
             tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]);
             tcg_gen_sari_tl(cpu_gpr_d[r3 + 1], cpu_gpr_d[r2], 31);
@@ -6398,7 +6393,7 @@ static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr_logical_shift(DisasContext *ctx)
 {
     uint32_t op2;
     int r3, r2, r1;
@@ -6476,7 +6471,7 @@ static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp);
 }
 
-static void decode_rr_address(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr_address(DisasContext *ctx)
 {
     uint32_t op2, n;
     int r1, r2, r3;
@@ -6544,7 +6539,7 @@ static void decode_rr_address(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr_idirect(DisasContext *ctx)
 {
     uint32_t op2;
     int r1;
@@ -6557,11 +6552,11 @@ static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
         break;
     case OPC2_32_RR_JLI:
-        tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
+        tcg_gen_movi_tl(cpu_gpr_a[11], ctx->pc_succ_insn);
         tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
         break;
     case OPC2_32_RR_CALLI:
-        gen_helper_1arg(call, ctx->next_pc);
+        gen_helper_1arg(call, ctx->pc_succ_insn);
         tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
         break;
     case OPC2_32_RR_FCALLI:
@@ -6572,10 +6567,10 @@ static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx)
         generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
     }
     tcg_gen_exit_tb(NULL, 0);
-    ctx->bstate = BS_BRANCH;
+    ctx->base.is_jmp = DISAS_NORETURN;
 }
 
-static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr_divide(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -6597,7 +6592,7 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
         break;
     case OPC2_32_RR_DVINIT_B:
         CHECK_REG_PAIR(r3);
-        gen_dvinit_b(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+        gen_dvinit_b(ctx, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
                      cpu_gpr_d[r2]);
         break;
     case OPC2_32_RR_DVINIT_BU:
@@ -6608,7 +6603,7 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 8);
         /* reset av */
         tcg_gen_movi_tl(cpu_PSW_AV, 0);
-        if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+        if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
             /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
             tcg_gen_abs_tl(temp, temp3);
             tcg_gen_abs_tl(temp2, cpu_gpr_d[r2]);
@@ -6630,7 +6625,7 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
         break;
     case OPC2_32_RR_DVINIT_H:
         CHECK_REG_PAIR(r3);
-        gen_dvinit_h(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+        gen_dvinit_h(ctx, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
                      cpu_gpr_d[r2]);
         break;
     case OPC2_32_RR_DVINIT_HU:
@@ -6641,7 +6636,7 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 16);
         /* reset av */
         tcg_gen_movi_tl(cpu_PSW_AV, 0);
-        if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+        if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
             /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
             tcg_gen_abs_tl(temp, temp3);
             tcg_gen_abs_tl(temp2, cpu_gpr_d[r2]);
@@ -6704,14 +6699,14 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
         gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
         break;
     case OPC2_32_RR_CRC32:
-        if (tricore_feature(env, TRICORE_FEATURE_161)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_161)) {
             gen_helper_crc32(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
         } else {
             generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
         }
         break;
     case OPC2_32_RR_DIV:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             GEN_HELPER_RR(divide, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
                           cpu_gpr_d[r2]);
         } else {
@@ -6719,7 +6714,7 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
         }
         break;
     case OPC2_32_RR_DIV_U:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             GEN_HELPER_RR(divide_u, cpu_gpr_d[r3], cpu_gpr_d[r3+1],
                           cpu_gpr_d[r1], cpu_gpr_d[r2]);
         } else {
@@ -6762,7 +6757,7 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RR1 Format */
-static void decode_rr1_mul(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr1_mul(DisasContext *ctx)
 {
     uint32_t op2;
 
@@ -6876,7 +6871,7 @@ static void decode_rr1_mul(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(n);
 }
 
-static void decode_rr1_mulq(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr1_mulq(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -6948,7 +6943,7 @@ static void decode_rr1_mulq(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RR2 format */
-static void decode_rr2_mul(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rr2_mul(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -6985,7 +6980,7 @@ static void decode_rr2_mul(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RRPW format */
-static void decode_rrpw_extract_insert(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrpw_extract_insert(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3;
@@ -7039,7 +7034,7 @@ static void decode_rrpw_extract_insert(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RRR format */
-static void decode_rrr_cond_select(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr_cond_select(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3, r4;
@@ -7085,7 +7080,7 @@ static void decode_rrr_cond_select(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rrr_divide(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr_divide(DisasContext *ctx)
 {
     uint32_t op2;
 
@@ -7165,7 +7160,7 @@ static void decode_rrr_divide(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RRR2 format */
-static void decode_rrr2_madd(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr2_madd(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4;
@@ -7217,7 +7212,7 @@ static void decode_rrr2_madd(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rrr2_msub(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr2_msub(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4;
@@ -7269,7 +7264,7 @@ static void decode_rrr2_msub(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RRR1 format */
-static void decode_rrr1_madd(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr1_madd(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4, n;
@@ -7415,7 +7410,7 @@ static void decode_rrr1_madd(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rrr1_maddq_h(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr1_maddq_h(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4, n;
@@ -7434,19 +7429,19 @@ static void decode_rrr1_maddq_h(CPUTriCoreState *env, DisasContext *ctx)
     switch (op2) {
     case OPC2_32_RRR1_MADD_Q_32:
         gen_madd32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
-                     cpu_gpr_d[r2], n, 32, env);
+                     cpu_gpr_d[r2], n, 32);
         break;
     case OPC2_32_RRR1_MADD_Q_64:
         CHECK_REG_PAIR(r4);
         CHECK_REG_PAIR(r3);
         gen_madd64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
                      cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
-                     n, env);
+                     n);
         break;
     case OPC2_32_RRR1_MADD_Q_32_L:
         tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
         gen_madd32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
-                     temp, n, 16, env);
+                     temp, n, 16);
         break;
     case OPC2_32_RRR1_MADD_Q_64_L:
         CHECK_REG_PAIR(r4);
@@ -7454,12 +7449,12 @@ static void decode_rrr1_maddq_h(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
         gen_madd64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
                      cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
-                     n, env);
+                     n);
         break;
     case OPC2_32_RRR1_MADD_Q_32_U:
         tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
         gen_madd32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
-                     temp, n, 16, env);
+                     temp, n, 16);
         break;
     case OPC2_32_RRR1_MADD_Q_64_U:
         CHECK_REG_PAIR(r4);
@@ -7467,7 +7462,7 @@ static void decode_rrr1_maddq_h(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
         gen_madd64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
                      cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
-                     n, env);
+                     n);
         break;
     case OPC2_32_RRR1_MADD_Q_32_LL:
         tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
@@ -7595,7 +7590,7 @@ static void decode_rrr1_maddq_h(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp2);
 }
 
-static void decode_rrr1_maddsu_h(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr1_maddsu_h(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4, n;
@@ -7753,7 +7748,7 @@ static void decode_rrr1_maddsu_h(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rrr1_msub(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr1_msub(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4, n;
@@ -7899,7 +7894,7 @@ static void decode_rrr1_msub(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_rrr1_msubq_h(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr1_msubq_h(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4, n;
@@ -7918,19 +7913,19 @@ static void decode_rrr1_msubq_h(CPUTriCoreState *env, DisasContext *ctx)
     switch (op2) {
     case OPC2_32_RRR1_MSUB_Q_32:
         gen_msub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
-                     cpu_gpr_d[r2], n, 32, env);
+                     cpu_gpr_d[r2], n, 32);
         break;
     case OPC2_32_RRR1_MSUB_Q_64:
         CHECK_REG_PAIR(r4);
         CHECK_REG_PAIR(r3);
         gen_msub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
                      cpu_gpr_d[r3+1], cpu_gpr_d[r1], cpu_gpr_d[r2],
-                     n, env);
+                     n);
         break;
     case OPC2_32_RRR1_MSUB_Q_32_L:
         tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
         gen_msub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
-                     temp, n, 16, env);
+                     temp, n, 16);
         break;
     case OPC2_32_RRR1_MSUB_Q_64_L:
         CHECK_REG_PAIR(r4);
@@ -7938,12 +7933,12 @@ static void decode_rrr1_msubq_h(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_ext16s_tl(temp, cpu_gpr_d[r2]);
         gen_msub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
                      cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
-                     n, env);
+                     n);
         break;
     case OPC2_32_RRR1_MSUB_Q_32_U:
         tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
         gen_msub32_q(cpu_gpr_d[r4], cpu_gpr_d[r3], cpu_gpr_d[r1],
-                     temp, n, 16, env);
+                     temp, n, 16);
         break;
     case OPC2_32_RRR1_MSUB_Q_64_U:
         CHECK_REG_PAIR(r4);
@@ -7951,7 +7946,7 @@ static void decode_rrr1_msubq_h(CPUTriCoreState *env, DisasContext *ctx)
         tcg_gen_sari_tl(temp, cpu_gpr_d[r2], 16);
         gen_msub64_q(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r3],
                      cpu_gpr_d[r3+1], cpu_gpr_d[r1], temp,
-                     n, env);
+                     n);
         break;
     case OPC2_32_RRR1_MSUB_Q_32_LL:
         tcg_gen_ext16s_tl(temp, cpu_gpr_d[r1]);
@@ -8079,7 +8074,7 @@ static void decode_rrr1_msubq_h(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp2);
 }
 
-static void decode_rrr1_msubad_h(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrr1_msubad_h(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1, r2, r3, r4, n;
@@ -8238,7 +8233,7 @@ static void decode_rrr1_msubad_h(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RRRR format */
-static void decode_rrrr_extract_insert(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrrr_extract_insert(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3, r4;
@@ -8295,7 +8290,7 @@ static void decode_rrrr_extract_insert(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* RRRW format */
-static void decode_rrrw_extract_insert(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_rrrw_extract_insert(DisasContext *ctx)
 {
     uint32_t op2;
     int r1, r2, r3, r4;
@@ -8356,7 +8351,7 @@ static void decode_rrrw_extract_insert(CPUTriCoreState *env, DisasContext *ctx)
 }
 
 /* SYS Format*/
-static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_sys_interrupts(DisasContext *ctx)
 {
     uint32_t op2;
     uint32_t r1;
@@ -8391,7 +8386,7 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
     case OPC2_32_SYS_RFE:
         gen_helper_rfe(cpu_env);
         tcg_gen_exit_tb(NULL, 0);
-        ctx->bstate = BS_BRANCH;
+        ctx->base.is_jmp = DISAS_NORETURN;
         break;
     case OPC2_32_SYS_RFM:
         if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM) {
@@ -8404,7 +8399,7 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
             gen_helper_rfm(cpu_env);
             gen_set_label(l1);
             tcg_gen_exit_tb(NULL, 0);
-            ctx->bstate = BS_BRANCH;
+            ctx->base.is_jmp = DISAS_NORETURN;
             tcg_temp_free(tmp);
         } else {
             /* generate privilege trap */
@@ -8417,7 +8412,7 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
         gen_helper_svlcx(cpu_env);
         break;
     case OPC2_32_SYS_RESTORE:
-        if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
             if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM ||
                 (ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_UM1) {
                 tcg_gen_deposit_tl(cpu_ICR, cpu_ICR, cpu_gpr_d[r1], 8, 1);
@@ -8443,7 +8438,7 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
+static void decode_32Bit_opc(DisasContext *ctx)
 {
     int op1;
     int32_t r1, r2, r3;
@@ -8462,22 +8457,22 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     switch (op1) {
 /* ABS-format */
     case OPCM_32_ABS_LDW:
-        decode_abs_ldw(env, ctx);
+        decode_abs_ldw(ctx);
         break;
     case OPCM_32_ABS_LDB:
-        decode_abs_ldb(env, ctx);
+        decode_abs_ldb(ctx);
         break;
     case OPCM_32_ABS_LDMST_SWAP:
-        decode_abs_ldst_swap(env, ctx);
+        decode_abs_ldst_swap(ctx);
         break;
     case OPCM_32_ABS_LDST_CONTEXT:
-        decode_abs_ldst_context(env, ctx);
+        decode_abs_ldst_context(ctx);
         break;
     case OPCM_32_ABS_STORE:
-        decode_abs_store(env, ctx);
+        decode_abs_store(ctx);
         break;
     case OPCM_32_ABS_STOREB_H:
-        decode_abs_storeb_h(env, ctx);
+        decode_abs_storeb_h(ctx);
         break;
     case OPC1_32_ABS_STOREQ:
         address = MASK_OP_ABS_OFF18(ctx->opcode);
@@ -8537,44 +8532,44 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
         break;
 /* Bit-format */
     case OPCM_32_BIT_ANDACC:
-        decode_bit_andacc(env, ctx);
+        decode_bit_andacc(ctx);
         break;
     case OPCM_32_BIT_LOGICAL_T1:
-        decode_bit_logical_t(env, ctx);
+        decode_bit_logical_t(ctx);
         break;
     case OPCM_32_BIT_INSERT:
-        decode_bit_insert(env, ctx);
+        decode_bit_insert(ctx);
         break;
     case OPCM_32_BIT_LOGICAL_T2:
-        decode_bit_logical_t2(env, ctx);
+        decode_bit_logical_t2(ctx);
         break;
     case OPCM_32_BIT_ORAND:
-        decode_bit_orand(env, ctx);
+        decode_bit_orand(ctx);
         break;
     case OPCM_32_BIT_SH_LOGIC1:
-        decode_bit_sh_logic1(env, ctx);
+        decode_bit_sh_logic1(ctx);
         break;
     case OPCM_32_BIT_SH_LOGIC2:
-        decode_bit_sh_logic2(env, ctx);
+        decode_bit_sh_logic2(ctx);
         break;
     /* BO Format */
     case OPCM_32_BO_ADDRMODE_POST_PRE_BASE:
-        decode_bo_addrmode_post_pre_base(env, ctx);
+        decode_bo_addrmode_post_pre_base(ctx);
         break;
     case OPCM_32_BO_ADDRMODE_BITREVERSE_CIRCULAR:
-        decode_bo_addrmode_bitreverse_circular(env, ctx);
+        decode_bo_addrmode_bitreverse_circular(ctx);
         break;
     case OPCM_32_BO_ADDRMODE_LD_POST_PRE_BASE:
-        decode_bo_addrmode_ld_post_pre_base(env, ctx);
+        decode_bo_addrmode_ld_post_pre_base(ctx);
         break;
     case OPCM_32_BO_ADDRMODE_LD_BITREVERSE_CIRCULAR:
-        decode_bo_addrmode_ld_bitreverse_circular(env, ctx);
+        decode_bo_addrmode_ld_bitreverse_circular(ctx);
         break;
     case OPCM_32_BO_ADDRMODE_STCTX_POST_PRE_BASE:
-        decode_bo_addrmode_stctx_post_pre_base(env, ctx);
+        decode_bo_addrmode_stctx_post_pre_base(ctx);
         break;
     case OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR:
-        decode_bo_addrmode_ldmst_bitreverse_circular(env, ctx);
+        decode_bo_addrmode_ldmst_bitreverse_circular(ctx);
         break;
 /* BOL-format */
     case OPC1_32_BOL_LD_A_LONGOFF:
@@ -8588,7 +8583,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPC1_32_BOL_LD_HU_LONGOFF:
     case OPC1_32_BOL_ST_B_LONGOFF:
     case OPC1_32_BOL_ST_H_LONGOFF:
-        decode_bol_opc(env, ctx, op1);
+        decode_bol_opc(ctx, op1);
         break;
 /* BRC Format */
     case OPCM_32_BRC_EQ_NEQ:
@@ -8621,20 +8616,20 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
         break;
 /* RC Format */
     case OPCM_32_RC_LOGICAL_SHIFT:
-        decode_rc_logical_shift(env, ctx);
+        decode_rc_logical_shift(ctx);
         break;
     case OPCM_32_RC_ACCUMULATOR:
-        decode_rc_accumulator(env, ctx);
+        decode_rc_accumulator(ctx);
         break;
     case OPCM_32_RC_SERVICEROUTINE:
-        decode_rc_serviceroutine(env, ctx);
+        decode_rc_serviceroutine(ctx);
         break;
     case OPCM_32_RC_MUL:
-        decode_rc_mul(env, ctx);
+        decode_rc_mul(ctx);
         break;
 /* RCPW Format */
     case OPCM_32_RCPW_MASK_INSERT:
-        decode_rcpw_insert(env, ctx);
+        decode_rcpw_insert(ctx);
         break;
 /* RCRR Format */
     case OPC1_32_RCRR_INSERT:
@@ -8659,17 +8654,17 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
         break;
 /* RCRW Format */
     case OPCM_32_RCRW_MASK_INSERT:
-        decode_rcrw_insert(env, ctx);
+        decode_rcrw_insert(ctx);
         break;
 /* RCR Format */
     case OPCM_32_RCR_COND_SELECT:
-        decode_rcr_cond_select(env, ctx);
+        decode_rcr_cond_select(ctx);
         break;
     case OPCM_32_RCR_MADD:
-        decode_rcr_madd(env, ctx);
+        decode_rcr_madd(ctx);
         break;
     case OPCM_32_RCR_MSUB:
-        decode_rcr_msub(env, ctx);
+        decode_rcr_msub(ctx);
         break;
 /* RLC Format */
     case OPC1_32_RLC_ADDI:
@@ -8682,38 +8677,38 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPC1_32_RLC_MOV_H:
     case OPC1_32_RLC_MOVH_A:
     case OPC1_32_RLC_MTCR:
-        decode_rlc_opc(env, ctx, op1);
+        decode_rlc_opc(ctx, op1);
         break;
 /* RR Format */
     case OPCM_32_RR_ACCUMULATOR:
-        decode_rr_accumulator(env, ctx);
+        decode_rr_accumulator(ctx);
         break;
     case OPCM_32_RR_LOGICAL_SHIFT:
-        decode_rr_logical_shift(env, ctx);
+        decode_rr_logical_shift(ctx);
         break;
     case OPCM_32_RR_ADDRESS:
-        decode_rr_address(env, ctx);
+        decode_rr_address(ctx);
         break;
     case OPCM_32_RR_IDIRECT:
-        decode_rr_idirect(env, ctx);
+        decode_rr_idirect(ctx);
         break;
     case OPCM_32_RR_DIVIDE:
-        decode_rr_divide(env, ctx);
+        decode_rr_divide(ctx);
         break;
 /* RR1 Format */
     case OPCM_32_RR1_MUL:
-        decode_rr1_mul(env, ctx);
+        decode_rr1_mul(ctx);
         break;
     case OPCM_32_RR1_MULQ:
-        decode_rr1_mulq(env, ctx);
+        decode_rr1_mulq(ctx);
         break;
 /* RR2 format */
     case OPCM_32_RR2_MUL:
-        decode_rr2_mul(env, ctx);
+        decode_rr2_mul(ctx);
         break;
 /* RRPW format */
     case OPCM_32_RRPW_EXTRACT_INSERT:
-        decode_rrpw_extract_insert(env, ctx);
+        decode_rrpw_extract_insert(ctx);
         break;
     case OPC1_32_RRPW_DEXTR:
         r1 = MASK_OP_RRPW_S1(ctx->opcode);
@@ -8732,48 +8727,48 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
         break;
 /* RRR Format */
     case OPCM_32_RRR_COND_SELECT:
-        decode_rrr_cond_select(env, ctx);
+        decode_rrr_cond_select(ctx);
         break;
     case OPCM_32_RRR_DIVIDE:
-        decode_rrr_divide(env, ctx);
+        decode_rrr_divide(ctx);
         break;
 /* RRR2 Format */
     case OPCM_32_RRR2_MADD:
-        decode_rrr2_madd(env, ctx);
+        decode_rrr2_madd(ctx);
         break;
     case OPCM_32_RRR2_MSUB:
-        decode_rrr2_msub(env, ctx);
+        decode_rrr2_msub(ctx);
         break;
 /* RRR1 format */
     case OPCM_32_RRR1_MADD:
-        decode_rrr1_madd(env, ctx);
+        decode_rrr1_madd(ctx);
         break;
     case OPCM_32_RRR1_MADDQ_H:
-        decode_rrr1_maddq_h(env, ctx);
+        decode_rrr1_maddq_h(ctx);
         break;
     case OPCM_32_RRR1_MADDSU_H:
-        decode_rrr1_maddsu_h(env, ctx);
+        decode_rrr1_maddsu_h(ctx);
         break;
     case OPCM_32_RRR1_MSUB_H:
-        decode_rrr1_msub(env, ctx);
+        decode_rrr1_msub(ctx);
         break;
     case OPCM_32_RRR1_MSUB_Q:
-        decode_rrr1_msubq_h(env, ctx);
+        decode_rrr1_msubq_h(ctx);
         break;
     case OPCM_32_RRR1_MSUBAD_H:
-        decode_rrr1_msubad_h(env, ctx);
+        decode_rrr1_msubad_h(ctx);
         break;
 /* RRRR format */
     case OPCM_32_RRRR_EXTRACT_INSERT:
-        decode_rrrr_extract_insert(env, ctx);
+        decode_rrrr_extract_insert(ctx);
         break;
 /* RRRW format */
     case OPCM_32_RRRW_EXTRACT_INSERT:
-        decode_rrrw_extract_insert(env, ctx);
+        decode_rrrw_extract_insert(ctx);
         break;
 /* SYS format */
     case OPCM_32_SYS_INTERRUPTS:
-        decode_sys_interrupts(env, ctx);
+        decode_sys_interrupts(ctx);
         break;
     case OPC1_32_SYS_RSTV:
         tcg_gen_movi_tl(cpu_PSW_V, 0);
@@ -8786,70 +8781,130 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
-static void decode_opc(CPUTriCoreState *env, DisasContext *ctx, int *is_branch)
+static bool tricore_insn_is_16bit(uint32_t insn)
 {
-    /* 16-Bit Instruction */
-    if ((ctx->opcode & 0x1) == 0) {
-        ctx->next_pc = ctx->pc + 2;
-        decode_16Bit_opc(env, ctx);
-    /* 32-Bit Instruction */
-    } else {
-        ctx->next_pc = ctx->pc + 4;
-        decode_32Bit_opc(env, ctx);
-    }
+    return (insn & 0x1) == 0;
 }
 
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
+static void tricore_tr_init_disas_context(DisasContextBase *dcbase,
+                                          CPUState *cs)
 {
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
     CPUTriCoreState *env = cs->env_ptr;
-    DisasContext ctx;
-    target_ulong pc_start;
-    int num_insns = 0;
-
-    pc_start = tb->pc;
-    ctx.pc = pc_start;
-    ctx.saved_pc = -1;
-    ctx.tb = tb;
-    ctx.singlestep_enabled = cs->singlestep_enabled;
-    ctx.bstate = BS_NONE;
-    ctx.mem_idx = cpu_mmu_index(env, false);
-    ctx.hflags = (uint32_t)tb->flags;
-
-    tcg_clear_temp_count();
-    gen_tb_start(tb);
-    while (ctx.bstate == BS_NONE) {
-        tcg_gen_insn_start(ctx.pc);
-        num_insns++;
-
-        ctx.opcode = cpu_ldl_code(env, ctx.pc);
-        decode_opc(env, &ctx, 0);
-
-        if (num_insns >= max_insns || tcg_op_buf_full()) {
-            gen_save_pc(ctx.next_pc);
-            tcg_gen_exit_tb(NULL, 0);
-            break;
-        }
-        ctx.pc = ctx.next_pc;
+    ctx->mem_idx = cpu_mmu_index(env, false);
+    ctx->hflags = (uint32_t)ctx->base.tb->flags;
+}
+
+static void tricore_tr_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+}
+
+static void tricore_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+    tcg_gen_insn_start(ctx->base.pc_next);
+}
+
+static bool tricore_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+                                      const CPUBreakpoint *bp)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    generate_qemu_excp(ctx, EXCP_DEBUG);
+    /*
+     * The address covered by the breakpoint must be included in
+     * [tb->pc, tb->pc + tb->size) in order to for it to be
+     * properly cleared -- thus we increment the PC here so that
+     * the logic setting tb->size below does the right thing.
+     */
+    ctx->base.pc_next += 4;
+    return true;
+}
+
+static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx)
+{
+    /*
+     * Return true if the insn at ctx->base.pc_next might cross a page boundary.
+     * (False positives are OK, false negatives are not.)
+     * Our caller ensures we are only called if dc->base.pc_next is less than
+     * 4 bytes from the page boundary, so we cross the page if the first
+     * 16 bits indicate that this is a 32 bit insn.
+     */
+    uint16_t insn = cpu_lduw_code(env, ctx->base.pc_next);
+
+    return !tricore_insn_is_16bit(insn);
+}
+
+
+static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    CPUTriCoreState *env = cpu->env_ptr;
+    uint16_t insn_lo;
+    bool is_16bit;
+
+    insn_lo = cpu_lduw_code(env, ctx->base.pc_next);
+    is_16bit = tricore_insn_is_16bit(insn_lo);
+    if (is_16bit) {
+        ctx->opcode = insn_lo;
+        ctx->pc_succ_insn = ctx->base.pc_next + 2;
+        decode_16Bit_opc(ctx);
+    } else {
+        uint32_t insn_hi = cpu_lduw_code(env, ctx->base.pc_next + 2);
+        ctx->opcode = insn_hi << 16 | insn_lo;
+        ctx->pc_succ_insn = ctx->base.pc_next + 4;
+        decode_32Bit_opc(ctx);
     }
+    ctx->base.pc_next = ctx->pc_succ_insn;
 
-    gen_tb_end(tb, num_insns);
-    tb->size = ctx.pc - pc_start;
-    tb->icount = num_insns;
+    if (ctx->base.is_jmp == DISAS_NEXT) {
+        target_ulong page_start;
 
-    if (tcg_check_temp_count()) {
-        printf("LEAK at %08x\n", env->PC);
+        page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
+        if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE
+            || (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - 3
+                && insn_crosses_page(env, ctx))) {
+            ctx->base.is_jmp = DISAS_TOO_MANY;
+        }
     }
+}
 
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
-        && qemu_log_in_addr_range(pc_start)) {
-        qemu_log_lock();
-        qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cs, pc_start, ctx.pc - pc_start);
-        qemu_log("\n");
-        qemu_log_unlock();
+static void tricore_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+    switch (ctx->base.is_jmp) {
+    case DISAS_TOO_MANY:
+        gen_goto_tb(ctx, 0, ctx->base.pc_next);
+        break;
+    case DISAS_NORETURN:
+        break;
+    default:
+        g_assert_not_reached();
     }
-#endif
+}
+
+static void tricore_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
+{
+    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
+    log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
+}
+
+static const TranslatorOps tricore_tr_ops = {
+    .init_disas_context = tricore_tr_init_disas_context,
+    .tb_start           = tricore_tr_tb_start,
+    .insn_start         = tricore_tr_insn_start,
+    .breakpoint_check   = tricore_tr_breakpoint_check,
+    .translate_insn     = tricore_tr_translate_insn,
+    .tb_stop            = tricore_tr_tb_stop,
+    .disas_log          = tricore_tr_disas_log,
+};
+
+
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
+{
+    DisasContext ctx;
+    translator_loop(&tricore_tr_ops, &ctx.base, cs, tb, max_insns);
 }
 
 void
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 6f02dfcc01..49684fd4f4 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -149,6 +149,7 @@ check-block-$(call land,$(CONFIG_POSIX),$(CONFIG_SOFTMMU)) += tests/check-block.
 
 check-qtest-generic-y += tests/qmp-test$(EXESUF)
 check-qtest-generic-y += tests/qmp-cmd-test$(EXESUF)
+check-qtest-generic-$(CONFIG_MODULES) += tests/modules-test$(EXESUF)
 
 check-qtest-generic-y += tests/device-introspect-test$(EXESUF)
 check-qtest-generic-y += tests/cdrom-test$(EXESUF)
@@ -524,7 +525,7 @@ tests/check-qlit$(EXESUF): tests/check-qlit.o $(test-util-obj-y)
 tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
 tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
 
-tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y) $(chardev-obj-y)
+tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y) $(chardev-obj-y) tests/socket-helpers.o
 tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
 tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
 tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index dbd58e548c..cf535cbd19 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -17,7 +17,9 @@ DOCKER_TESTS := $(notdir $(shell \
 
 DOCKER_TOOLS := travis
 
-DOCKER_SCRIPT=$(SRC_PATH)/tests/docker/docker.py
+ENGINE := auto
+
+DOCKER_SCRIPT=$(SRC_PATH)/tests/docker/docker.py --engine $(ENGINE)
 
 TESTS ?= %
 IMAGES ?= %
@@ -146,7 +148,7 @@ $(foreach i,$(filter-out $(DOCKER_PARTIAL_IMAGES),$(DOCKER_IMAGES) $(DOCKER_DEPR
 )
 
 docker:
-	@echo 'Build QEMU and run tests inside Docker containers'
+	@echo 'Build QEMU and run tests inside Docker or Podman containers'
 	@echo
 	@echo 'Available targets:'
 	@echo
@@ -193,6 +195,8 @@ endif
 	@echo '    EXECUTABLE=<path>    Include executable in image.'
 	@echo '    EXTRA_FILES="<path> [... <path>]"'
 	@echo '                         Include extra files in image.'
+	@echo '    ENGINE=auto/docker/podman'
+	@echo '                         Specify which container engine to run.'
 
 # This rule if for directly running against an arbitrary docker target.
 # It is called by the expanded docker targets (e.g. make
@@ -212,7 +216,7 @@ docker-run: docker-qemu-src
 			"  COPYING $(EXECUTABLE) to $(IMAGE)"))
 	$(call quiet-command,						\
 		$(DOCKER_SCRIPT) run 					\
-			$(if $(NOUSER),,-u $(shell id -u)) 		\
+			$(if $(NOUSER),,--run-as-current-user) 		\
 			--security-opt seccomp=unconfined		\
 			$(if $V,,--rm) 					\
 			$(if $(DEBUG),-ti,)				\
diff --git a/tests/docker/docker.py b/tests/docker/docker.py
index 53a8c9c801..ac5baab4ca 100755
--- a/tests/docker/docker.py
+++ b/tests/docker/docker.py
@@ -20,6 +20,7 @@ import hashlib
 import atexit
 import uuid
 import argparse
+import enum
 import tempfile
 import re
 import signal
@@ -38,6 +39,26 @@ FILTERED_ENV_NAMES = ['ftp_proxy', 'http_proxy', 'https_proxy']
 
 DEVNULL = open(os.devnull, 'wb')
 
+class EngineEnum(enum.IntEnum):
+    AUTO = 1
+    DOCKER = 2
+    PODMAN = 3
+
+    def __str__(self):
+        return self.name.lower()
+
+    def __repr__(self):
+        return str(self)
+
+    @staticmethod
+    def argparse(s):
+        try:
+            return EngineEnum[s.upper()]
+        except KeyError:
+            return s
+
+
+USE_ENGINE = EngineEnum.AUTO
 
 def _text_checksum(text):
     """Calculate a digest string unique to the text content"""
@@ -48,9 +69,14 @@ def _file_checksum(filename):
     return _text_checksum(open(filename, 'rb').read())
 
 
-def _guess_docker_command():
-    """ Guess a working docker command or raise exception if not found"""
-    commands = [["docker"], ["sudo", "-n", "docker"]]
+def _guess_engine_command():
+    """ Guess a working engine command or raise exception if not found"""
+    commands = []
+
+    if USE_ENGINE in [EngineEnum.AUTO, EngineEnum.PODMAN]:
+        commands += [["podman"]]
+    if USE_ENGINE in [EngineEnum.AUTO, EngineEnum.DOCKER]:
+        commands += [["docker"], ["sudo", "-n", "docker"]]
     for cmd in commands:
         try:
             # docker version will return the client details in stdout
@@ -61,7 +87,7 @@ def _guess_docker_command():
         except OSError:
             pass
     commands_txt = "\n".join(["  " + " ".join(x) for x in commands])
-    raise Exception("Cannot find working docker command. Tried:\n%s" %
+    raise Exception("Cannot find working engine command. Tried:\n%s" %
                     commands_txt)
 
 
@@ -190,7 +216,7 @@ def _dockerfile_preprocess(df):
 class Docker(object):
     """ Running Docker commands """
     def __init__(self):
-        self._command = _guess_docker_command()
+        self._command = _guess_engine_command()
         self._instances = []
         atexit.register(self._kill_instances)
         signal.signal(signal.SIGTERM, self._kill_instances)
@@ -333,8 +359,18 @@ class RunCommand(SubCommand):
     def args(self, parser):
         parser.add_argument("--keep", action="store_true",
                             help="Don't remove image when command completes")
+        parser.add_argument("--run-as-current-user", action="store_true",
+                            help="Run container using the current user's uid")
 
     def run(self, args, argv):
+        if args.run_as_current_user:
+            uid = os.getuid()
+            argv = [ "-u", str(uid) ] + argv
+            docker = Docker()
+            if docker._command[0] == "podman":
+                argv = [ "--uidmap", "%d:0:1" % uid,
+                         "--uidmap", "0:1:%d" % uid,
+                         "--uidmap", "%d:%d:64536" % (uid + 1, uid + 1)] + argv
         return Docker().run(argv, args.keep, quiet=args.quiet)
 
 
@@ -502,6 +538,8 @@ class ProbeCommand(SubCommand):
                 print("yes")
             elif docker._command[0] == "sudo":
                 print("sudo")
+            elif docker._command[0] == "podman":
+                print("podman")
         except Exception:
             print("no")
 
@@ -597,9 +635,13 @@ class CheckCommand(SubCommand):
 
 
 def main():
+    global USE_ENGINE
+
     parser = argparse.ArgumentParser(description="A Docker helper",
                                      usage="%s <subcommand> ..." %
                                      os.path.basename(sys.argv[0]))
+    parser.add_argument("--engine", type=EngineEnum.argparse, choices=list(EngineEnum),
+                        help="specify which container engine to use")
     subparsers = parser.add_subparsers(title="subcommands", help=None)
     for cls in SubCommand.__subclasses__():
         cmd = cls()
@@ -608,6 +650,7 @@ def main():
         cmd.args(subp)
         subp.set_defaults(cmdobj=cmd)
     args, argv = parser.parse_known_args()
+    USE_ENGINE = args.engine
     return args.cmdobj.run(args, argv)
 
 
diff --git a/tests/libqtest.c b/tests/libqtest.c
index eb971d0d11..2713b86cf7 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -811,6 +811,12 @@ bool qtest_get_irq(QTestState *s, int num)
     return s->irq_level[num];
 }
 
+void qtest_module_load(QTestState *s, const char *prefix, const char *libname)
+{
+    qtest_sendf(s, "module_load %s %s\n", prefix, libname);
+    qtest_rsp(s, 0);
+}
+
 static int64_t qtest_clock_rsp(QTestState *s)
 {
     gchar **words;
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 7833148358..07ea35867c 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -262,6 +262,8 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
 char *qtest_vhmp(QTestState *s, const char *fmt, va_list ap)
     GCC_FMT_ATTR(2, 0);
 
+void qtest_module_load(QTestState *s, const char *prefix, const char *libname);
+
 /**
  * qtest_get_irq:
  * @s: #QTestState instance to operate on.
diff --git a/tests/modules-test.c b/tests/modules-test.c
new file mode 100644
index 0000000000..f9de3afdb7
--- /dev/null
+++ b/tests/modules-test.c
@@ -0,0 +1,68 @@
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+static void test_modules_load(const void *data)
+{
+    QTestState *qts;
+    const char **args = (const char **)data;
+
+    qts = qtest_init(NULL);
+    qtest_module_load(qts, args[0], args[1]);
+    qtest_quit(qts);
+}
+
+int main(int argc, char *argv[])
+{
+    const char *modules[] = {
+#ifdef CONFIG_CURL
+        "block-", "curl",
+#endif
+#ifdef CONFIG_GLUSTERFS
+        "block-", "gluster",
+#endif
+#ifdef CONFIG_LIBISCSI
+        "block-", "iscsi",
+#endif
+#ifdef CONFIG_LIBNFS
+        "block-", "nfs",
+#endif
+#ifdef CONFIG_LIBSSH
+        "block-", "ssh",
+#endif
+#ifdef CONFIG_RBD
+        "block-", "rbd",
+#endif
+#ifdef CONFIG_AUDIO_ALSA
+        "audio-", "alsa",
+#endif
+#ifdef CONFIG_AUDIO_OSS
+        "audio-", "oss",
+#endif
+#ifdef CONFIG_AUDIO_PA
+        "audio-", "pa",
+#endif
+#ifdef CONFIG_AUDIO_SDL
+        "audio-", "sdl",
+#endif
+#ifdef CONFIG_CURSES
+        "ui-", "curses",
+#endif
+#if defined(CONFIG_GTK) && defined(CONFIG_VTE)
+        "ui-", "gtk",
+#endif
+#ifdef CONFIG_SDL
+        "ui-", "sdl",
+#endif
+    };
+    int i;
+
+    g_test_init(&argc, &argv, NULL);
+
+    for (i = 0; i < G_N_ELEMENTS(modules); i += 2) {
+        char *testname = g_strdup_printf("/module/load/%s", modules[i + 1]);
+        qtest_add_data_func(testname, modules + i, test_modules_load);
+        g_free(testname);
+    }
+
+    return g_test_run();
+}
diff --git a/tests/socket-helpers.c b/tests/socket-helpers.c
index 8112763f5b..19a51e887e 100644
--- a/tests/socket-helpers.c
+++ b/tests/socket-helpers.c
@@ -30,7 +30,16 @@
 # define EAI_ADDRFAMILY 0
 #endif
 
-int socket_can_bind_connect(const char *hostname)
+/*
+ * @hostname: a DNS name or numeric IP address
+ *
+ * Check whether it is possible to bind & connect to ports
+ * on the DNS name or IP address @hostname. If an IP address
+ * is used, it must not be a wildcard address.
+ *
+ * Returns 0 on success, -1 on error with errno set
+ */
+static int socket_can_bind_connect(const char *hostname, int family)
 {
     int lfd = -1, cfd = -1, afd = -1;
     struct addrinfo ai, *res = NULL;
@@ -44,7 +53,7 @@ int socket_can_bind_connect(const char *hostname)
 
     memset(&ai, 0, sizeof(ai));
     ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
-    ai.ai_family = AF_UNSPEC;
+    ai.ai_family = family;
     ai.ai_socktype = SOCK_STREAM;
 
     /* lookup */
@@ -129,7 +138,7 @@ int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6)
 {
     *has_ipv4 = *has_ipv6 = false;
 
-    if (socket_can_bind_connect("127.0.0.1") < 0) {
+    if (socket_can_bind_connect("127.0.0.1", PF_INET) < 0) {
         if (errno != EADDRNOTAVAIL) {
             return -1;
         }
@@ -137,7 +146,7 @@ int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6)
         *has_ipv4 = true;
     }
 
-    if (socket_can_bind_connect("::1") < 0) {
+    if (socket_can_bind_connect("::1", PF_INET6) < 0) {
         if (errno != EADDRNOTAVAIL) {
             return -1;
         }
diff --git a/tests/socket-helpers.h b/tests/socket-helpers.h
index 9de0e6b151..512a004811 100644
--- a/tests/socket-helpers.h
+++ b/tests/socket-helpers.h
@@ -21,17 +21,6 @@
 #define TESTS_SOCKET_HELPERS_H
 
 /*
- * @hostname: a DNS name or numeric IP address
- *
- * Check whether it is possible to bind & connect to ports
- * on the DNS name or IP address @hostname. If an IP address
- * is used, it must not be a wildcard address.
- *
- * Returns 0 on success, -1 on error with errno set
- */
-int socket_can_bind_connect(const char *hostname);
-
-/*
  * @has_ipv4: set to true on return if IPv4 is available
  * @has_ipv6: set to true on return if IPv6 is available
  *
diff --git a/tests/test-char.c b/tests/test-char.c
index f9440cdcfd..b56e43c1eb 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -15,6 +15,7 @@
 #include "io/channel-socket.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qapi-visit-sockets.h"
+#include "socket-helpers.h"
 
 static bool quit;
 
@@ -1356,11 +1357,18 @@ static void char_hotswap_test(void)
 
 int main(int argc, char **argv)
 {
+    bool has_ipv4, has_ipv6;
+
     qemu_init_main_loop(&error_abort);
     socket_init();
 
     g_test_init(&argc, &argv, NULL);
 
+    if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
+        g_printerr("socket_check_protocol_support() failed\n");
+        goto end;
+    }
+
     module_call_init(MODULE_INIT_QOM);
     qemu_add_opts(&qemu_chardev_opts);
 
@@ -1438,10 +1446,12 @@ int main(int argc, char **argv)
     g_test_add_data_func("/char/socket/client/wait-conn-fdpass/" # name, \
                          &client6 ##name, char_socket_client_test)
 
-    SOCKET_SERVER_TEST(tcp, &tcpaddr);
-    SOCKET_CLIENT_TEST(tcp, &tcpaddr);
-    g_test_add_data_func("/char/socket/server/two-clients/tcp", &tcpaddr,
-                         char_socket_server_two_clients_test);
+    if (has_ipv4) {
+        SOCKET_SERVER_TEST(tcp, &tcpaddr);
+        SOCKET_CLIENT_TEST(tcp, &tcpaddr);
+        g_test_add_data_func("/char/socket/server/two-clients/tcp", &tcpaddr,
+                             char_socket_server_two_clients_test);
+    }
 #ifndef WIN32
     SOCKET_SERVER_TEST(unix, &unixaddr);
     SOCKET_CLIENT_TEST(unix, &unixaddr);
@@ -1456,5 +1466,6 @@ int main(int argc, char **argv)
     g_test_add_func("/char/hotswap", char_hotswap_test);
     g_test_add_func("/char/websocket", char_websock_test);
 
+end:
     return g_test_run();
 }
diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c
index d2053c464c..d172f3070f 100644
--- a/tests/test-io-channel-socket.c
+++ b/tests/test-io-channel-socket.c
@@ -566,7 +566,8 @@ int main(int argc, char **argv)
      * with either IPv4 or IPv6 disabled.
      */
     if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
-        return 1;
+        g_printerr("socket_check_protocol_support() failed\n");
+        goto end;
     }
 
     if (has_ipv4) {
@@ -595,5 +596,6 @@ int main(int argc, char **argv)
                     test_io_channel_unix_listen_cleanup);
 #endif /* _WIN32 */
 
+end:
     return g_test_run();
 }
diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c
index f1ebffee5a..e2a3a8a093 100644
--- a/tests/test-util-sockets.c
+++ b/tests/test-util-sockets.c
@@ -242,7 +242,8 @@ int main(int argc, char **argv)
      * with either IPv4 or IPv6 disabled.
      */
     if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
-        return 1;
+        g_printerr("socket_check_protocol_support() failed\n");
+        goto end;
     }
 
     if (has_ipv4) {
@@ -264,5 +265,6 @@ int main(int argc, char **argv)
                         test_socket_fd_pass_num_nocli);
     }
 
+end:
     return g_test_run();
 }
diff --git a/ui/curses.c b/ui/curses.c
index a6e260eb96..ec281125ac 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -225,6 +225,8 @@ static wint_t console_getch(enum maybe_keycode *maybe_keycode)
     case ERR:
         ret = -1;
         break;
+    default:
+        abort();
     }
     return ret;
 }
diff --git a/ui/input-linux.c b/ui/input-linux.c
index 59456fe765..a7b280b25b 100644
--- a/ui/input-linux.c
+++ b/ui/input-linux.c
@@ -113,6 +113,10 @@ static bool input_linux_check_toggle(InputLinux *il)
         return il->keydown[KEY_LEFTALT] &&
             il->keydown[KEY_RIGHTALT];
 
+    case GRAB_TOGGLE_KEYS_SHIFT_SHIFT:
+        return il->keydown[KEY_LEFTSHIFT] &&
+            il->keydown[KEY_RIGHTSHIFT];
+
     case GRAB_TOGGLE_KEYS_META_META:
         return il->keydown[KEY_LEFTMETA] &&
             il->keydown[KEY_RIGHTMETA];
diff --git a/util/module.c b/util/module.c
index 142db7e911..e9fe3e5422 100644
--- a/util/module.c
+++ b/util/module.c
@@ -156,8 +156,10 @@ out:
 }
 #endif
 
-void module_load_one(const char *prefix, const char *lib_name)
+bool module_load_one(const char *prefix, const char *lib_name)
 {
+    bool success = false;
+
 #ifdef CONFIG_MODULES
     char *fname = NULL;
     char *exec_dir;
@@ -170,7 +172,7 @@ void module_load_one(const char *prefix, const char *lib_name)
 
     if (!g_module_supported()) {
         fprintf(stderr, "Module is not supported by system.\n");
-        return;
+        return false;
     }
 
     if (!loaded_modules) {
@@ -179,11 +181,10 @@ void module_load_one(const char *prefix, const char *lib_name)
 
     module_name = g_strdup_printf("%s%s", prefix, lib_name);
 
-    if (g_hash_table_lookup(loaded_modules, module_name)) {
+    if (!g_hash_table_add(loaded_modules, module_name)) {
         g_free(module_name);
-        return;
+        return true;
     }
-    g_hash_table_insert(loaded_modules, module_name, module_name);
 
     exec_dir = qemu_get_exec_dir();
     search_dir = getenv("QEMU_MODULE_DIR");
@@ -206,13 +207,19 @@ void module_load_one(const char *prefix, const char *lib_name)
         fname = NULL;
         /* Try loading until loaded a module file */
         if (!ret) {
+            success = true;
             break;
         }
     }
 
+    if (!success) {
+        g_hash_table_remove(loaded_modules, module_name);
+    }
+
     for (i = 0; i < n_dirs; i++) {
         g_free(dirs[i]);
     }
 
 #endif
+    return success;
 }