summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile21
-rw-r--r--Makefile.objs2
-rw-r--r--backends/baum.c2
-rw-r--r--backends/msmouse.c2
-rw-r--r--balloon.c13
-rw-r--r--block.c73
-rw-r--r--block/backup.c2
-rw-r--r--block/mirror.c9
-rw-r--r--block/qcow2-refcount.c14
-rw-r--r--block/quorum.c25
-rw-r--r--block/stream.c4
-rw-r--r--blockdev.c12
-rw-r--r--blockjob.c53
-rwxr-xr-xconfigure2
-rw-r--r--cpus.c4
-rw-r--r--docs/qapi-code-gen.txt18
-rw-r--r--docs/qmp/qmp-events.txt551
-rw-r--r--exec.c1
-rw-r--r--fpu/softfloat-macros.h38
-rw-r--r--fpu/softfloat.c48
-rw-r--r--hmp.c7
-rw-r--r--hw/acpi/core.c4
-rw-r--r--hw/acpi/memory_hotplug.c34
-rw-r--r--hw/audio/fmopl.c31
-rw-r--r--hw/block/virtio-blk.c6
-rw-r--r--hw/core/qdev.c12
-rw-r--r--hw/i386/pc.c47
-rw-r--r--hw/i386/pc_piix.c53
-rw-r--r--hw/i386/pc_q35.c53
-rw-r--r--hw/ide/core.c6
-rw-r--r--hw/misc/pvpanic.c13
-rw-r--r--hw/net/e1000.c73
-rw-r--r--hw/net/e1000_regs.h3
-rw-r--r--hw/net/virtio-net.c13
-rw-r--r--hw/pci-bridge/ioh3420.c7
-rw-r--r--hw/pci-bridge/xio3130_downstream.c7
-rw-r--r--hw/pci/pcie.c62
-rw-r--r--hw/ppc/spapr_rtas.c3
-rw-r--r--hw/scsi/scsi-disk.c6
-rw-r--r--hw/timer/mc146818rtc.c3
-rw-r--r--hw/virtio/vhost.c21
-rw-r--r--hw/virtio/virtio-balloon.c6
-rw-r--r--hw/virtio/virtio-pci.c2
-rw-r--r--hw/watchdog/watchdog.c23
-rw-r--r--include/block/block.h4
-rw-r--r--include/block/block_int.h3
-rw-r--r--include/block/blockjob.h17
-rw-r--r--include/exec/exec-all.h2
-rw-r--r--include/fpu/softfloat.h99
-rw-r--r--include/hw/i386/pc.h13
-rw-r--r--include/hw/pci/pci.h3
-rw-r--r--include/hw/pci/pcie.h2
-rw-r--r--include/hw/pci/pcie_regs.h2
-rw-r--r--include/hw/virtio/vhost.h1
-rw-r--r--include/hw/xen/xen.h3
-rw-r--r--include/monitor/monitor.h41
-rw-r--r--include/qapi/qmp-event.h27
-rw-r--r--include/qemu/cache-utils.h44
-rw-r--r--include/qemu/osdep.h12
-rw-r--r--include/qemu/sockets.h3
-rw-r--r--include/sysemu/balloon.h2
-rw-r--r--include/sysemu/char.h20
-rw-r--r--include/sysemu/os-posix.h2
-rw-r--r--include/sysemu/sysemu.h2
-rw-r--r--linux-user/main.c4
-rw-r--r--monitor.c229
-rw-r--r--pc-bios/s390-ccw.imgbin9336 -> 9432 bytes
-rw-r--r--pc-bios/s390-ccw/bootmap.c82
-rw-r--r--pc-bios/s390-ccw/virtio.c2
-rw-r--r--qapi-event.json318
-rw-r--r--qapi-schema.json174
-rw-r--r--qapi/Makefile.objs1
-rw-r--r--qapi/block-core.json150
-rw-r--r--qapi/block.json14
-rw-r--r--qapi/qmp-event.c74
-rw-r--r--qapi/string-output-visitor.c2
-rw-r--r--qemu-char.c143
-rw-r--r--qobject/json-lexer.c4
-rw-r--r--scripts/qapi-commands.py8
-rw-r--r--scripts/qapi-event.py369
-rw-r--r--scripts/qapi-visit.py20
-rw-r--r--scripts/qapi.py37
-rw-r--r--spice-qemu-char.c2
-rw-r--r--stubs/Makefile.objs3
-rw-r--r--stubs/chr-baum-init.c7
-rw-r--r--stubs/mon-protocol-event.c6
-rw-r--r--stubs/qemu-chr-open-spice.c14
-rw-r--r--target-s390x/kvm.c9
-rw-r--r--tcg/ppc/tcg-target.c3124
-rw-r--r--tcg/ppc/tcg-target.h114
-rw-r--r--tcg/ppc64/tcg-target.c2186
-rw-r--r--tcg/ppc64/tcg-target.h131
-rw-r--r--tcg/tcg.c1
-rw-r--r--tests/Makefile18
-rw-r--r--tests/check-qjson.c7
-rw-r--r--tests/qapi-schema/event-nest-struct.err1
-rw-r--r--tests/qapi-schema/event-nest-struct.exit1
-rw-r--r--tests/qapi-schema/event-nest-struct.json2
-rw-r--r--tests/qapi-schema/event-nest-struct.out0
-rw-r--r--tests/qapi-schema/qapi-schema-test.json12
-rw-r--r--tests/qapi-schema/qapi-schema-test.out10
-rw-r--r--tests/test-qmp-event.c265
-rw-r--r--tests/vhost-user-test.c128
-rw-r--r--ui/console.c2
-rw-r--r--ui/spice-core.c77
-rw-r--r--ui/vnc.c120
-rw-r--r--ui/vnc.h4
-rw-r--r--util/Makefile.objs2
-rw-r--r--util/cache-utils.c86
-rw-r--r--util/getauxval.c51
-rw-r--r--util/qemu-sockets.c10
-rw-r--r--vl.c33
-rw-r--r--xen-hvm-stub.c3
-rw-r--r--xen-hvm.c53
114 files changed, 4649 insertions, 5155 deletions
diff --git a/Makefile b/Makefile
index 3c8f19c964..7d0c8ec7cc 100644
--- a/Makefile
+++ b/Makefile
@@ -45,8 +45,8 @@ endif
 endif
 
 GENERATED_HEADERS = config-host.h qemu-options.def
-GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
-GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
+GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
+GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
 
 GENERATED_HEADERS += trace/generated-events.h
 GENERATED_SOURCES += trace/generated-events.c
@@ -202,7 +202,7 @@ Makefile: $(version-obj-y) $(version-lobj-y)
 # Build libraries
 
 libqemustub.a: $(stub-obj-y)
-libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
+libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o qapi-event.o
 
 block-modules = $(foreach o,$(block-obj-m),"$(basename $(subst /,-,$o))",) NULL
 util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)'
@@ -246,18 +246,27 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
 		$(gen-out-type) -o qga/qapi-generated -p "qga-" -i $<, \
 		"  GEN   $@")
 
+qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
+               $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
+               $(SRC_PATH)/qapi-event.json
+
 qapi-types.c qapi-types.h :\
-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
+$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
 		$(gen-out-type) -o "." -b -i $<, \
 		"  GEN   $@")
 qapi-visit.c qapi-visit.h :\
-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
+$(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
 		$(gen-out-type) -o "." -b -i $<, \
 		"  GEN   $@")
+qapi-event.c qapi-event.h :\
+$(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
+		$(gen-out-type) -o "." -b -i $<, \
+		"  GEN   $@")
 qmp-commands.h qmp-marshal.c :\
-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
+$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
 		$(gen-out-type) -o "." -m -i $<, \
 		"  GEN   $@")
diff --git a/Makefile.objs b/Makefile.objs
index b897e1dc34..1f76cea569 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -12,7 +12,7 @@ block-obj-y += main-loop.o iohandler.o qemu-timer.o
 block-obj-$(CONFIG_POSIX) += aio-posix.o
 block-obj-$(CONFIG_WIN32) += aio-win32.o
 block-obj-y += block/
-block-obj-y += qapi-types.o qapi-visit.o
+block-obj-y += qapi-types.o qapi-visit.o qapi-event.o
 block-obj-y += qemu-io-cmds.o
 
 block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
diff --git a/backends/baum.c b/backends/baum.c
index 759003f623..796512d387 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -574,7 +574,7 @@ CharDriverState *chr_baum_init(void)
     int tty;
 
     baum = g_malloc0(sizeof(BaumDriverState));
-    baum->chr = chr = g_malloc0(sizeof(CharDriverState));
+    baum->chr = chr = qemu_chr_alloc();
 
     chr->opaque = baum;
     chr->chr_write = baum_write;
diff --git a/backends/msmouse.c b/backends/msmouse.c
index c0dbfcdd6b..650a5314d4 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -67,7 +67,7 @@ CharDriverState *qemu_chr_open_msmouse(void)
 {
     CharDriverState *chr;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     chr->chr_write = msmouse_chr_write;
     chr->chr_close = msmouse_chr_close;
     chr->explicit_be_open = true;
diff --git a/balloon.c b/balloon.c
index e321f2c688..b70da4fa29 100644
--- a/balloon.c
+++ b/balloon.c
@@ -81,19 +81,6 @@ static int qemu_balloon_status(BalloonInfo *info)
     return 1;
 }
 
-void qemu_balloon_changed(int64_t actual)
-{
-    QObject *data;
-
-    data = qobject_from_jsonf("{ 'actual': %" PRId64 " }",
-                              actual);
-
-    monitor_protocol_event(QEVENT_BALLOON_CHANGE, data);
-
-    qobject_decref(data);
-}
-
-
 BalloonInfo *qmp_query_balloon(Error **errp)
 {
     BalloonInfo *info;
diff --git a/block.c b/block.c
index ff44e76c87..e6f9b71e11 100644
--- a/block.c
+++ b/block.c
@@ -24,7 +24,6 @@
 #include "config-host.h"
 #include "qemu-common.h"
 #include "trace.h"
-#include "monitor/monitor.h"
 #include "block/block_int.h"
 #include "block/blockjob.h"
 #include "qemu/module.h"
@@ -35,6 +34,7 @@
 #include "block/qapi.h"
 #include "qmp-commands.h"
 #include "qemu/timer.h"
+#include "qapi-event.h"
 
 #ifdef CONFIG_BSD
 #include <sys/types.h>
@@ -2132,47 +2132,6 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
     bs->dev_opaque = opaque;
 }
 
-void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
-                               enum MonitorEvent ev,
-                               BlockErrorAction action, bool is_read)
-{
-    QObject *data;
-    const char *action_str;
-
-    switch (action) {
-    case BDRV_ACTION_REPORT:
-        action_str = "report";
-        break;
-    case BDRV_ACTION_IGNORE:
-        action_str = "ignore";
-        break;
-    case BDRV_ACTION_STOP:
-        action_str = "stop";
-        break;
-    default:
-        abort();
-    }
-
-    data = qobject_from_jsonf("{ 'device': %s, 'action': %s, 'operation': %s }",
-                              bdrv->device_name,
-                              action_str,
-                              is_read ? "read" : "write");
-    monitor_protocol_event(ev, data);
-
-    qobject_decref(data);
-}
-
-static void bdrv_emit_qmp_eject_event(BlockDriverState *bs, bool ejected)
-{
-    QObject *data;
-
-    data = qobject_from_jsonf("{ 'device': %s, 'tray-open': %i }",
-                              bdrv_get_device_name(bs), ejected);
-    monitor_protocol_event(QEVENT_DEVICE_TRAY_MOVED, data);
-
-    qobject_decref(data);
-}
-
 static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load)
 {
     if (bs->dev_ops && bs->dev_ops->change_media_cb) {
@@ -2180,11 +2139,13 @@ static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load)
         bs->dev_ops->change_media_cb(bs->dev_opaque, load);
         if (tray_was_closed) {
             /* tray open */
-            bdrv_emit_qmp_eject_event(bs, true);
+            qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
+                                              true, &error_abort);
         }
         if (load) {
             /* tray close */
-            bdrv_emit_qmp_eject_event(bs, false);
+            qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
+                                              false, &error_abort);
         }
     }
 }
@@ -3606,13 +3567,14 @@ BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int e
 
     switch (on_err) {
     case BLOCKDEV_ON_ERROR_ENOSPC:
-        return (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT;
+        return (error == ENOSPC) ?
+               BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
     case BLOCKDEV_ON_ERROR_STOP:
-        return BDRV_ACTION_STOP;
+        return BLOCK_ERROR_ACTION_STOP;
     case BLOCKDEV_ON_ERROR_REPORT:
-        return BDRV_ACTION_REPORT;
+        return BLOCK_ERROR_ACTION_REPORT;
     case BLOCKDEV_ON_ERROR_IGNORE:
-        return BDRV_ACTION_IGNORE;
+        return BLOCK_ERROR_ACTION_IGNORE;
     default:
         abort();
     }
@@ -3627,7 +3589,7 @@ void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
 {
     assert(error >= 0);
 
-    if (action == BDRV_ACTION_STOP) {
+    if (action == BLOCK_ERROR_ACTION_STOP) {
         /* First set the iostatus, so that "info block" returns an iostatus
          * that matches the events raised so far (an additional error iostatus
          * is fine, but not a lost one).
@@ -3643,10 +3605,16 @@ void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
          * also ensures that the STOP/RESUME pair of events is emitted.
          */
         qemu_system_vmstop_request_prepare();
-        bdrv_emit_qmp_error_event(bs, QEVENT_BLOCK_IO_ERROR, action, is_read);
+        qapi_event_send_block_io_error(bdrv_get_device_name(bs),
+                                       is_read ? IO_OPERATION_TYPE_READ :
+                                       IO_OPERATION_TYPE_WRITE,
+                                       action, &error_abort);
         qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
     } else {
-        bdrv_emit_qmp_error_event(bs, QEVENT_BLOCK_IO_ERROR, action, is_read);
+        qapi_event_send_block_io_error(bdrv_get_device_name(bs),
+                                       is_read ? IO_OPERATION_TYPE_READ :
+                                       IO_OPERATION_TYPE_WRITE,
+                                       action, &error_abort);
     }
 }
 
@@ -5216,7 +5184,8 @@ void bdrv_eject(BlockDriverState *bs, bool eject_flag)
     }
 
     if (bs->device_name[0] != '\0') {
-        bdrv_emit_qmp_eject_event(bs, eject_flag);
+        qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
+                                          eject_flag, &error_abort);
     }
 }
 
diff --git a/block/backup.c b/block/backup.c
index 15a2e55e8e..7978ae2e50 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -325,7 +325,7 @@ static void coroutine_fn backup_run(void *opaque)
                 /* Depending on error action, fail now or retry cluster */
                 BlockErrorAction action =
                     backup_error_action(job, error_is_read, -ret);
-                if (action == BDRV_ACTION_REPORT) {
+                if (action == BLOCK_ERROR_ACTION_REPORT) {
                     break;
                 } else {
                     start--;
diff --git a/block/mirror.c b/block/mirror.c
index 94c8661777..301a04de8e 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -118,7 +118,7 @@ static void mirror_write_complete(void *opaque, int ret)
 
         bdrv_set_dirty(source, op->sector_num, op->nb_sectors);
         action = mirror_error_action(s, false, -ret);
-        if (action == BDRV_ACTION_REPORT && s->ret >= 0) {
+        if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) {
             s->ret = ret;
         }
     }
@@ -135,7 +135,7 @@ static void mirror_read_complete(void *opaque, int ret)
 
         bdrv_set_dirty(source, op->sector_num, op->nb_sectors);
         action = mirror_error_action(s, true, -ret);
-        if (action == BDRV_ACTION_REPORT && s->ret >= 0) {
+        if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) {
             s->ret = ret;
         }
 
@@ -415,7 +415,8 @@ static void coroutine_fn mirror_run(void *opaque)
             trace_mirror_before_flush(s);
             ret = bdrv_flush(s->target);
             if (ret < 0) {
-                if (mirror_error_action(s, false, -ret) == BDRV_ACTION_REPORT) {
+                if (mirror_error_action(s, false, -ret) ==
+                    BLOCK_ERROR_ACTION_REPORT) {
                     goto immediate_exit;
                 }
             } else {
@@ -426,7 +427,7 @@ static void coroutine_fn mirror_run(void *opaque)
                  */
                 s->common.offset = end * BDRV_SECTOR_SIZE;
                 if (!s->synced) {
-                    block_job_ready(&s->common);
+                    block_job_event_ready(&s->common);
                     s->synced = true;
                 }
 
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 9507aef847..cc6cf743d6 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -27,6 +27,7 @@
 #include "block/qcow2.h"
 #include "qemu/range.h"
 #include "qapi/qmp/types.h"
+#include "qapi-event.h"
 
 static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size);
 static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
@@ -1807,7 +1808,6 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
     } else if (ret > 0) {
         int metadata_ol_bitnr = ffs(ret) - 1;
         char *message;
-        QObject *data;
 
         assert(metadata_ol_bitnr < QCOW2_OL_MAX_BITNR);
 
@@ -1816,12 +1816,14 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                 metadata_ol_names[metadata_ol_bitnr]);
         message = g_strdup_printf("Prevented %s overwrite",
                 metadata_ol_names[metadata_ol_bitnr]);
-        data = qobject_from_jsonf("{ 'device': %s, 'msg': %s, 'offset': %"
-                PRId64 ", 'size': %" PRId64 " }", bs->device_name, message,
-                offset, size);
-        monitor_protocol_event(QEVENT_BLOCK_IMAGE_CORRUPTED, data);
+        qapi_event_send_block_image_corrupted(bdrv_get_device_name(bs),
+                                              message,
+                                              true,
+                                              offset,
+                                              true,
+                                              size,
+                                              &error_abort);
         g_free(message);
-        qobject_decref(data);
 
         qcow2_mark_corrupt(bs);
         bs->drv = NULL; /* make BDS unusable */
diff --git a/block/quorum.c b/block/quorum.c
index 426077a520..86802d306b 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -17,6 +17,7 @@
 #include <gnutls/crypto.h>
 #include "block/block_int.h"
 #include "qapi/qmp/qjson.h"
+#include "qapi-event.h"
 
 #define HASH_LENGTH 32
 
@@ -198,32 +199,22 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s,
 
 static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret)
 {
-    QObject *data;
-    assert(node_name);
-    data = qobject_from_jsonf("{ 'node-name': %s"
-                              ", 'sector-num': %" PRId64
-                              ", 'sectors-count': %d }",
-                              node_name, acb->sector_num, acb->nb_sectors);
+    const char *msg = NULL;
     if (ret < 0) {
-        QDict *dict = qobject_to_qdict(data);
-        qdict_put(dict, "error", qstring_from_str(strerror(-ret)));
+        msg = strerror(-ret);
     }
-    monitor_protocol_event(QEVENT_QUORUM_REPORT_BAD, data);
-    qobject_decref(data);
+    qapi_event_send_quorum_report_bad(!!msg, msg, node_name,
+                                      acb->sector_num, acb->nb_sectors, &error_abort);
 }
 
 static void quorum_report_failure(QuorumAIOCB *acb)
 {
-    QObject *data;
     const char *reference = acb->common.bs->device_name[0] ?
                             acb->common.bs->device_name :
                             acb->common.bs->node_name;
-    data = qobject_from_jsonf("{ 'reference': %s"
-                              ", 'sector-num': %" PRId64
-                              ", 'sectors-count': %d }",
-                              reference, acb->sector_num, acb->nb_sectors);
-    monitor_protocol_event(QEVENT_QUORUM_FAILURE, data);
-    qobject_decref(data);
+
+    qapi_event_send_quorum_failure(reference, acb->sector_num,
+                                   acb->nb_sectors, &error_abort);
 }
 
 static int quorum_vote_error(QuorumAIOCB *acb);
diff --git a/block/stream.c b/block/stream.c
index 91d18a2db7..043340994d 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -159,14 +159,14 @@ wait:
             BlockErrorAction action =
                 block_job_error_action(&s->common, s->common.bs, s->on_error,
                                        true, -ret);
-            if (action == BDRV_ACTION_STOP) {
+            if (action == BLOCK_ERROR_ACTION_STOP) {
                 n = 0;
                 continue;
             }
             if (error == 0) {
                 error = ret;
             }
-            if (action == BDRV_ACTION_REPORT) {
+            if (action == BLOCK_ERROR_ACTION_REPORT) {
                 break;
             }
         }
diff --git a/blockdev.c b/blockdev.c
index 9b0f8ac45e..03ab153d01 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1847,23 +1847,21 @@ void qmp_block_resize(bool has_device, const char *device,
 static void block_job_cb(void *opaque, int ret)
 {
     BlockDriverState *bs = opaque;
-    QObject *obj;
+    const char *msg = NULL;
 
     trace_block_job_cb(bs, bs->job, ret);
 
     assert(bs->job);
-    obj = qobject_from_block_job(bs->job);
+
     if (ret < 0) {
-        QDict *dict = qobject_to_qdict(obj);
-        qdict_put(dict, "error", qstring_from_str(strerror(-ret)));
+        msg = strerror(-ret);
     }
 
     if (block_job_is_cancelled(bs->job)) {
-        monitor_protocol_event(QEVENT_BLOCK_JOB_CANCELLED, obj);
+        block_job_event_cancelled(bs->job);
     } else {
-        monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj);
+        block_job_event_completed(bs->job, msg);
     }
-    qobject_decref(obj);
 
     bdrv_put_ref_bh_schedule(bs);
 }
diff --git a/blockjob.c b/blockjob.c
index 7d84ca1d6c..4da86cdfcd 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -26,7 +26,6 @@
 #include "config-host.h"
 #include "qemu-common.h"
 #include "trace.h"
-#include "monitor/monitor.h"
 #include "block/block.h"
 #include "block/blockjob.h"
 #include "block/block_int.h"
@@ -34,6 +33,7 @@
 #include "block/coroutine.h"
 #include "qmp-commands.h"
 #include "qemu/timer.h"
+#include "qapi-event.h"
 
 void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
                        int64_t speed, BlockDriverCompletionFunc *cb,
@@ -232,26 +232,31 @@ static void block_job_iostatus_set_err(BlockJob *job, int error)
     }
 }
 
+void block_job_event_cancelled(BlockJob *job)
+{
+    qapi_event_send_block_job_cancelled(job->driver->job_type,
+                                        bdrv_get_device_name(job->bs),
+                                        job->len,
+                                        job->offset,
+                                        job->speed,
+                                        &error_abort);
+}
 
-QObject *qobject_from_block_job(BlockJob *job)
+void block_job_event_completed(BlockJob *job, const char *msg)
 {
-    return qobject_from_jsonf("{ 'type': %s,"
-                              "'device': %s,"
-                              "'len': %" PRId64 ","
-                              "'offset': %" PRId64 ","
-                              "'speed': %" PRId64 " }",
-                              BlockJobType_lookup[job->driver->job_type],
-                              bdrv_get_device_name(job->bs),
-                              job->len,
-                              job->offset,
-                              job->speed);
+    qapi_event_send_block_job_completed(job->driver->job_type,
+                                        bdrv_get_device_name(job->bs),
+                                        job->len,
+                                        job->offset,
+                                        job->speed,
+                                        !!msg,
+                                        msg,
+                                        &error_abort);
 }
 
-void block_job_ready(BlockJob *job)
+void block_job_event_ready(BlockJob *job)
 {
-    QObject *data = qobject_from_block_job(job);
-    monitor_protocol_event(QEVENT_BLOCK_JOB_READY, data);
-    qobject_decref(data);
+    qapi_event_send_block_job_ready(bdrv_get_device_name(job->bs), &error_abort);
 }
 
 BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
@@ -262,22 +267,26 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
 
     switch (on_err) {
     case BLOCKDEV_ON_ERROR_ENOSPC:
-        action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT;
+        action = (error == ENOSPC) ?
+                 BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
         break;
     case BLOCKDEV_ON_ERROR_STOP:
-        action = BDRV_ACTION_STOP;
+        action = BLOCK_ERROR_ACTION_STOP;
         break;
     case BLOCKDEV_ON_ERROR_REPORT:
-        action = BDRV_ACTION_REPORT;
+        action = BLOCK_ERROR_ACTION_REPORT;
         break;
     case BLOCKDEV_ON_ERROR_IGNORE:
-        action = BDRV_ACTION_IGNORE;
+        action = BLOCK_ERROR_ACTION_IGNORE;
         break;
     default:
         abort();
     }
-    bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read);
-    if (action == BDRV_ACTION_STOP) {
+    qapi_event_send_block_job_error(bdrv_get_device_name(bs),
+                                    is_read ? IO_OPERATION_TYPE_READ :
+                                    IO_OPERATION_TYPE_WRITE,
+                                    action, &error_abort);
+    if (action == BLOCK_ERROR_ACTION_STOP) {
         block_job_pause(job);
         block_job_iostatus_set_err(job, error);
         if (bs != job->bs) {
diff --git a/configure b/configure
index 998964e6c0..9c1471e70f 100755
--- a/configure
+++ b/configure
@@ -4747,6 +4747,8 @@ elif test "$ARCH" = "s390x" ; then
   QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES"
 elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then
   QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES"
+elif test "$ARCH" = "ppc64" ; then
+  QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/ppc $QEMU_INCLUDES"
 else
   QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES"
 fi
diff --git a/cpus.c b/cpus.c
index 06da4e7665..5e7f2cf3cf 100644
--- a/cpus.c
+++ b/cpus.c
@@ -26,6 +26,7 @@
 #include "config-host.h"
 
 #include "monitor/monitor.h"
+#include "qapi/qmp/qerror.h"
 #include "sysemu/sysemu.h"
 #include "exec/gdbstub.h"
 #include "sysemu/dma.h"
@@ -38,6 +39,7 @@
 #include "qemu/main-loop.h"
 #include "qemu/bitmap.h"
 #include "qemu/seqlock.h"
+#include "qapi-event.h"
 
 #ifndef _WIN32
 #include "qemu/compatfd.h"
@@ -530,7 +532,7 @@ static int do_vm_stop(RunState state)
         pause_all_vcpus();
         runstate_set(state);
         vm_state_notify(0, state);
-        monitor_protocol_event(QEVENT_STOP, NULL);
+        qapi_event_send_stop(&error_abort);
     }
 
     bdrv_drain_all();
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index dea0d505a7..3a0c99e1da 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -215,6 +215,24 @@ An example command is:
    'data': { 'arg1': 'str', '*arg2': 'str' },
    'returns': 'str' }
 
+=== Events ===
+
+Events are defined with the keyword 'event'.  When 'data' is also specified,
+additional info will be carried on.  Finally there will be C API generated
+in qapi-event.h; when called by QEMU code, a message with timestamp will
+be emitted on the wire.  If timestamp is -1, it means failure to retrieve host
+time.
+
+An example event is:
+
+{ 'event': 'EVENT_C',
+  'data': { '*a': 'int', 'b': 'str' } }
+
+Resulting in this JSON object:
+
+{ "event": "EVENT_C",
+  "data": { "b": "test string" },
+  "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
 
 == Code generation ==
 
diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt
deleted file mode 100644
index 22fea580a9..0000000000
--- a/docs/qmp/qmp-events.txt
+++ /dev/null
@@ -1,551 +0,0 @@
-                   QEMU Machine Protocol Events
-                   ============================
-
-ACPI_DEVICE_OST
----------------
-
-Emitted when guest executes ACPI _OST method.
-
- - data: ACPIOSTInfo type as described in qapi-schema.json
-
-{ "event": "ACPI_DEVICE_OST",
-     "data": { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0 } }
-
-BALLOON_CHANGE
---------------
-
-Emitted when the guest changes the actual BALLOON level. This
-value is equivalent to the 'actual' field return by the
-'query-balloon' command
-
-Data:
-
-- "actual": actual level of the guest memory balloon in bytes (json-number)
-
-Example:
-
-{ "event": "BALLOON_CHANGE",
-    "data": { "actual": 944766976 },
-    "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
-
-BLOCK_IMAGE_CORRUPTED
----------------------
-
-Emitted when a disk image is being marked corrupt.
-
-Data:
-
-- "device": Device name (json-string)
-- "msg":    Informative message (e.g., reason for the corruption) (json-string)
-- "offset": If the corruption resulted from an image access, this is the access
-            offset into the image (json-int)
-- "size":   If the corruption resulted from an image access, this is the access
-            size (json-int)
-
-Example:
-
-{ "event": "BLOCK_IMAGE_CORRUPTED",
-    "data": { "device": "ide0-hd0",
-        "msg": "Prevented active L1 table overwrite", "offset": 196608,
-        "size": 65536 },
-    "timestamp": { "seconds": 1378126126, "microseconds": 966463 } }
-
-BLOCK_IO_ERROR
---------------
-
-Emitted when a disk I/O error occurs.
-
-Data:
-
-- "device": device name (json-string)
-- "operation": I/O operation (json-string, "read" or "write")
-- "action": action that has been taken, it's one of the following (json-string):
-    "ignore": error has been ignored
-    "report": error has been reported to the device
-    "stop": the VM is going to stop because of the error
-
-Example:
-
-{ "event": "BLOCK_IO_ERROR",
-    "data": { "device": "ide0-hd1",
-              "operation": "write",
-              "action": "stop" },
-    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
-
-Note: If action is "stop", a STOP event will eventually follow the
-BLOCK_IO_ERROR event.
-
-BLOCK_JOB_CANCELLED
--------------------
-
-Emitted when a block job has been cancelled.
-
-Data:
-
-- "type":     Job type (json-string; "stream" for image streaming
-                                     "commit" for block commit)
-- "device":   Device name (json-string)
-- "len":      Maximum progress value (json-int)
-- "offset":   Current progress value (json-int)
-              On success this is equal to len.
-              On failure this is less than len.
-- "speed":    Rate limit, bytes per second (json-int)
-
-Example:
-
-{ "event": "BLOCK_JOB_CANCELLED",
-     "data": { "type": "stream", "device": "virtio-disk0",
-               "len": 10737418240, "offset": 134217728,
-               "speed": 0 },
-     "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
-
-BLOCK_JOB_COMPLETED
--------------------
-
-Emitted when a block job has completed.
-
-Data:
-
-- "type":     Job type (json-string; "stream" for image streaming
-                                     "commit" for block commit)
-- "device":   Device name (json-string)
-- "len":      Maximum progress value (json-int)
-- "offset":   Current progress value (json-int)
-              On success this is equal to len.
-              On failure this is less than len.
-- "speed":    Rate limit, bytes per second (json-int)
-- "error":    Error message (json-string, optional)
-              Only present on failure.  This field contains a human-readable
-              error message.  There are no semantics other than that streaming
-              has failed and clients should not try to interpret the error
-              string.
-
-Example:
-
-{ "event": "BLOCK_JOB_COMPLETED",
-     "data": { "type": "stream", "device": "virtio-disk0",
-               "len": 10737418240, "offset": 10737418240,
-               "speed": 0 },
-     "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
-
-BLOCK_JOB_ERROR
----------------
-
-Emitted when a block job encounters an error.
-
-Data:
-
-- "device": device name (json-string)
-- "operation": I/O operation (json-string, "read" or "write")
-- "action": action that has been taken, it's one of the following (json-string):
-    "ignore": error has been ignored, the job may fail later
-    "report": error will be reported and the job canceled
-    "stop": error caused job to be paused
-
-Example:
-
-{ "event": "BLOCK_JOB_ERROR",
-    "data": { "device": "ide0-hd1",
-              "operation": "write",
-              "action": "stop" },
-    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
-
-BLOCK_JOB_READY
----------------
-
-Emitted when a block job is ready to complete.
-
-Data:
-
-- "device": device name (json-string)
-
-Example:
-
-{ "event": "BLOCK_JOB_READY",
-    "data": { "device": "ide0-hd1" },
-    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
-
-Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
-event.
-
-DEVICE_DELETED
---------------
-
-Emitted whenever the device removal completion is acknowledged
-by the guest.
-At this point, it's safe to reuse the specified device ID.
-Device removal can be initiated by the guest or by HMP/QMP commands.
-
-Data:
-
-- "device": device name (json-string, optional)
-- "path": device path (json-string)
-
-{ "event": "DEVICE_DELETED",
-  "data": { "device": "virtio-net-pci-0",
-            "path": "/machine/peripheral/virtio-net-pci-0" },
-  "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
-
-DEVICE_TRAY_MOVED
------------------
-
-It's emitted whenever the tray of a removable device is moved by the guest
-or by HMP/QMP commands.
-
-Data:
-
-- "device": device name (json-string)
-- "tray-open": true if the tray has been opened or false if it has been closed
-               (json-bool)
-
-{ "event": "DEVICE_TRAY_MOVED",
-  "data": { "device": "ide1-cd0",
-            "tray-open": true
-  },
-  "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
-
-GUEST_PANICKED
---------------
-
-Emitted when guest OS panic is detected.
-
-Data:
-
-- "action": Action that has been taken (json-string, currently always "pause").
-
-Example:
-
-{ "event": "GUEST_PANICKED",
-     "data": { "action": "pause" } }
-
-NIC_RX_FILTER_CHANGED
----------------------
-
-The event is emitted once until the query command is executed,
-the first event will always be emitted.
-
-Data:
-
-- "name": net client name (json-string)
-- "path": device path (json-string)
-
-{ "event": "NIC_RX_FILTER_CHANGED",
-  "data": { "name": "vnet0",
-            "path": "/machine/peripheral/vnet0/virtio-backend" },
-  "timestamp": { "seconds": 1368697518, "microseconds": 326866 } }
-}
-
-QUORUM_FAILURE
---------------
-
-Emitted by the Quorum block driver if it fails to establish a quorum.
-
-Data:
-
-- "reference":    device name if defined else node name.
-- "sector-num":   Number of the first sector of the failed read operation.
-- "sector-count": Failed read operation sector count.
-
-Example:
-
-{ "event": "QUORUM_FAILURE",
-     "data": { "reference": "usr1", "sector-num": 345435, "sector-count": 5 },
-     "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
-
-QUORUM_REPORT_BAD
------------------
-
-Emitted to report a corruption of a Quorum file.
-
-Data:
-
-- "error":        Error message (json-string, optional)
-                  Only present on failure.  This field contains a human-readable
-                  error message.  There are no semantics other than that the
-                  block layer reported an error and clients should not try to
-                  interpret the error string.
-- "node-name":    The graph node name of the block driver state.
-- "sector-num":   Number of the first sector of the failed read operation.
-- "sector-count": Failed read operation sector count.
-
-Example:
-
-{ "event": "QUORUM_REPORT_BAD",
-     "data": { "node-name": "1.raw", "sector-num": 345435, "sector-count": 5 },
-     "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
-
-RESET
------
-
-Emitted when the Virtual Machine is reseted.
-
-Data: None.
-
-Example:
-
-{ "event": "RESET",
-    "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
-
-RESUME
-------
-
-Emitted when the Virtual Machine resumes execution.
-
-Data: None.
-
-Example:
-
-{ "event": "RESUME",
-    "timestamp": { "seconds": 1271770767, "microseconds": 582542 } }
-
-RTC_CHANGE
-----------
-
-Emitted when the guest changes the RTC time.
-
-Data:
-
-- "offset": Offset between base RTC clock (as specified by -rtc base), and
-new RTC clock value (json-number)
-
-Example:
-
-{ "event": "RTC_CHANGE",
-    "data": { "offset": 78 },
-    "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
-
-SHUTDOWN
---------
-
-Emitted when the Virtual Machine is powered down.
-
-Data: None.
-
-Example:
-
-{ "event": "SHUTDOWN",
-    "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
-
-Note: If the command-line option "-no-shutdown" has been specified, a STOP
-event will eventually follow the SHUTDOWN event.
-
-SPICE_CONNECTED, SPICE_DISCONNECTED
------------------------------------
-
-Emitted when a SPICE client connects or disconnects.
-
-Data:
-
-- "server": Server information (json-object)
-  - "host": IP address (json-string)
-  - "port": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-- "client": Client information (json-object)
-  - "host": IP address (json-string)
-  - "port": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-
-Example:
-
-{ "timestamp": {"seconds": 1290688046, "microseconds": 388707},
-  "event": "SPICE_CONNECTED",
-  "data": {
-    "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
-    "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
-}}
-
-SPICE_INITIALIZED
------------------
-
-Emitted after initial handshake and authentication takes place (if any)
-and the SPICE channel is up'n'running
-
-Data:
-
-- "server": Server information (json-object)
-  - "host": IP address (json-string)
-  - "port": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-  - "auth": authentication method (json-string, optional)
-- "client": Client information (json-object)
-  - "host": IP address (json-string)
-  - "port": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-  - "connection-id": spice connection id.  All channels with the same id
-                     belong to the same spice session (json-int)
-  - "channel-type": channel type.  "1" is the main control channel, filter for
-                    this one if you want track spice sessions only (json-int)
-  - "channel-id": channel id.  Usually "0", might be different needed when
-                  multiple channels of the same type exist, such as multiple
-                  display channels in a multihead setup (json-int)
-  - "tls": whevener the channel is encrypted (json-bool)
-
-Example:
-
-{ "timestamp": {"seconds": 1290688046, "microseconds": 417172},
-  "event": "SPICE_INITIALIZED",
-  "data": {"server": {"auth": "spice", "port": "5921",
-                      "family": "ipv4", "host": "127.0.0.1"},
-           "client": {"port": "49004", "family": "ipv4", "channel-type": 3,
-                      "connection-id": 1804289383, "host": "127.0.0.1",
-                      "channel-id": 0, "tls": true}
-}}
-
-STOP
-----
-
-Emitted when the Virtual Machine is stopped.
-
-Data: None.
-
-Example:
-
-{ "event": "STOP",
-    "timestamp": { "seconds": 1267041730, "microseconds": 281295 } }
-
-SUSPEND
--------
-
-Emitted when guest enters S3 state.
-
-Data: None.
-
-Example:
-
-{ "event": "SUSPEND",
-     "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
-
-SUSPEND_DISK
-------------
-
-Emitted when the guest makes a request to enter S4 state.
-
-Data: None.
-
-Example:
-
-{ "event": "SUSPEND_DISK",
-     "timestamp": { "seconds": 1344456160, "microseconds": 309119 } }
-
-Note: QEMU shuts down when entering S4 state.
-
-VNC_CONNECTED
--------------
-
-Emitted when a VNC client establishes a connection.
-
-Data:
-
-- "server": Server information (json-object)
-  - "host": IP address (json-string)
-  - "service": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-  - "auth": authentication method (json-string, optional)
-- "client": Client information (json-object)
-  - "host": IP address (json-string)
-  - "service": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-
-Example:
-
-{ "event": "VNC_CONNECTED",
-    "data": {
-        "server": { "auth": "sasl", "family": "ipv4",
-                    "service": "5901", "host": "0.0.0.0" },
-        "client": { "family": "ipv4", "service": "58425",
-                    "host": "127.0.0.1" } },
-    "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
-
-
-Note: This event is emitted before any authentication takes place, thus
-the authentication ID is not provided.
-
-VNC_DISCONNECTED
-----------------
-
-Emitted when the connection is closed.
-
-Data:
-
-- "server": Server information (json-object)
-  - "host": IP address (json-string)
-  - "service": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-  - "auth": authentication method (json-string, optional)
-- "client": Client information (json-object)
-  - "host": IP address (json-string)
-  - "service": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-  - "x509_dname": TLS dname (json-string, optional)
-  - "sasl_username": SASL username (json-string, optional)
-
-Example:
-
-{ "event": "VNC_DISCONNECTED",
-    "data": {
-        "server": { "auth": "sasl", "family": "ipv4",
-                    "service": "5901", "host": "0.0.0.0" },
-        "client": { "family": "ipv4", "service": "58425",
-                    "host": "127.0.0.1", "sasl_username": "luiz" } },
-    "timestamp": { "seconds": 1262976601, "microseconds": 975795 } }
-
-VNC_INITIALIZED
----------------
-
-Emitted after authentication takes place (if any) and the VNC session is
-made active.
-
-Data:
-
-- "server": Server information (json-object)
-  - "host": IP address (json-string)
-  - "service": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-  - "auth": authentication method (json-string, optional)
-- "client": Client information (json-object)
-  - "host": IP address (json-string)
-  - "service": port number (json-string)
-  - "family": address family (json-string, "ipv4" or "ipv6")
-  - "x509_dname": TLS dname (json-string, optional)
-  - "sasl_username": SASL username (json-string, optional)
-
-Example:
-
-{ "event": "VNC_INITIALIZED",
-    "data": {
-        "server": { "auth": "sasl", "family": "ipv4",
-                    "service": "5901", "host": "0.0.0.0"},
-        "client": { "family": "ipv4", "service": "46089",
-                    "host": "127.0.0.1", "sasl_username": "luiz" } },
-        "timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
-
-WAKEUP
-------
-
-Emitted when the guest has woken up from S3 and is running.
-
-Data: None.
-
-Example:
-
-{ "event": "WAKEUP",
-     "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
-
-WATCHDOG
---------
-
-Emitted when the watchdog device's timer is expired.
-
-Data:
-
-- "action": Action that has been taken, it's one of the following (json-string):
-            "reset", "shutdown", "poweroff", "pause", "debug", or "none"
-
-Example:
-
-{ "event": "WATCHDOG",
-     "data": { "action": "reset" },
-     "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
-
-Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
-followed respectively by the RESET, SHUTDOWN, or STOP events.
diff --git a/exec.c b/exec.c
index 1ca7baca0b..c8494051a6 100644
--- a/exec.c
+++ b/exec.c
@@ -50,7 +50,6 @@
 
 #include "exec/memory-internal.h"
 #include "exec/ram_addr.h"
-#include "qemu/cache-utils.h"
 
 #include "qemu/range.h"
 
diff --git a/fpu/softfloat-macros.h b/fpu/softfloat-macros.h
index 9b095456c5..0dcda93f72 100644
--- a/fpu/softfloat-macros.h
+++ b/fpu/softfloat-macros.h
@@ -55,7 +55,7 @@ these four paragraphs for those parts of this code that are retained.
 | The result is stored in the location pointed to by `zPtr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void shift32RightJamming(uint32_t a, int_fast16_t count, uint32_t *zPtr)
+static inline void shift32RightJamming(uint32_t a, int_fast16_t count, uint32_t *zPtr)
 {
     uint32_t z;
 
@@ -81,7 +81,7 @@ INLINE void shift32RightJamming(uint32_t a, int_fast16_t count, uint32_t *zPtr)
 | The result is stored in the location pointed to by `zPtr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void shift64RightJamming(uint64_t a, int_fast16_t count, uint64_t *zPtr)
+static inline void shift64RightJamming(uint64_t a, int_fast16_t count, uint64_t *zPtr)
 {
     uint64_t z;
 
@@ -115,7 +115,7 @@ INLINE void shift64RightJamming(uint64_t a, int_fast16_t count, uint64_t *zPtr)
 | described above, and is returned at the location pointed to by `z1Ptr'.)
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  shift64ExtraRightJamming(
      uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
 {
@@ -152,7 +152,7 @@ INLINE void
 | which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  shift128Right(
      uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
 {
@@ -187,7 +187,7 @@ INLINE void
 | the locations pointed to by `z0Ptr' and `z1Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  shift128RightJamming(
      uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
 {
@@ -238,7 +238,7 @@ INLINE void
 | `z2Ptr'.)
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  shift128ExtraRightJamming(
      uint64_t a0,
      uint64_t a1,
@@ -296,7 +296,7 @@ INLINE void
 | pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  shortShift128Left(
      uint64_t a0, uint64_t a1, int_fast16_t count, uint64_t *z0Ptr, uint64_t *z1Ptr)
 {
@@ -315,7 +315,7 @@ INLINE void
 | `z1Ptr', and `z2Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  shortShift192Left(
      uint64_t a0,
      uint64_t a1,
@@ -350,7 +350,7 @@ INLINE void
 | are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  add128(
      uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
@@ -370,7 +370,7 @@ INLINE void
 | `z1Ptr', and `z2Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  add192(
      uint64_t a0,
      uint64_t a1,
@@ -408,7 +408,7 @@ INLINE void
 | `z1Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  sub128(
      uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
@@ -426,7 +426,7 @@ INLINE void
 | pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  sub192(
      uint64_t a0,
      uint64_t a1,
@@ -462,7 +462,7 @@ INLINE void
 | `z0Ptr' and `z1Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void mul64To128( uint64_t a, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr )
+static inline void mul64To128( uint64_t a, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr )
 {
     uint32_t aHigh, aLow, bHigh, bLow;
     uint64_t z0, zMiddleA, zMiddleB, z1;
@@ -492,7 +492,7 @@ INLINE void mul64To128( uint64_t a, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr
 | `z2Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  mul128By64To192(
      uint64_t a0,
      uint64_t a1,
@@ -520,7 +520,7 @@ INLINE void
 | the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
 *----------------------------------------------------------------------------*/
 
-INLINE void
+static inline void
  mul128To256(
      uint64_t a0,
      uint64_t a1,
@@ -702,7 +702,7 @@ static int8 countLeadingZeros64( uint64_t a )
 | Otherwise, returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 == b0 ) && ( a1 == b1 );
@@ -715,7 +715,7 @@ INLINE flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 | Otherwise, returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
@@ -728,7 +728,7 @@ INLINE flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 | returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
@@ -741,7 +741,7 @@ INLINE flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 | Otherwise, returns 0.
 *----------------------------------------------------------------------------*/
 
-INLINE flag ne128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline flag ne128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
 {
 
     return ( a0 != b0 ) || ( a1 != b1 );
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e00a6fbca6..9274ebf101 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -66,7 +66,7 @@ these four paragraphs for those parts of this code that are retained.
 | Returns the fraction bits of the half-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE uint32_t extractFloat16Frac(float16 a)
+static inline uint32_t extractFloat16Frac(float16 a)
 {
     return float16_val(a) & 0x3ff;
 }
@@ -75,7 +75,7 @@ INLINE uint32_t extractFloat16Frac(float16 a)
 | Returns the exponent bits of the half-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE int_fast16_t extractFloat16Exp(float16 a)
+static inline int_fast16_t extractFloat16Exp(float16 a)
 {
     return (float16_val(a) >> 10) & 0x1f;
 }
@@ -84,7 +84,7 @@ INLINE int_fast16_t extractFloat16Exp(float16 a)
 | Returns the sign bit of the single-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE flag extractFloat16Sign(float16 a)
+static inline flag extractFloat16Sign(float16 a)
 {
     return float16_val(a)>>15;
 }
@@ -255,7 +255,7 @@ static int64 roundAndPackUint64(flag zSign, uint64_t absZ0,
 | Returns the fraction bits of the single-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE uint32_t extractFloat32Frac( float32 a )
+static inline uint32_t extractFloat32Frac( float32 a )
 {
 
     return float32_val(a) & 0x007FFFFF;
@@ -266,7 +266,7 @@ INLINE uint32_t extractFloat32Frac( float32 a )
 | Returns the exponent bits of the single-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE int_fast16_t extractFloat32Exp(float32 a)
+static inline int_fast16_t extractFloat32Exp(float32 a)
 {
 
     return ( float32_val(a)>>23 ) & 0xFF;
@@ -277,7 +277,7 @@ INLINE int_fast16_t extractFloat32Exp(float32 a)
 | Returns the sign bit of the single-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE flag extractFloat32Sign( float32 a )
+static inline flag extractFloat32Sign( float32 a )
 {
 
     return float32_val(a)>>31;
@@ -328,7 +328,7 @@ static void
 | significand.
 *----------------------------------------------------------------------------*/
 
-INLINE float32 packFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig)
+static inline float32 packFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig)
 {
 
     return make_float32(
@@ -440,7 +440,7 @@ static float32
 | Returns the fraction bits of the double-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE uint64_t extractFloat64Frac( float64 a )
+static inline uint64_t extractFloat64Frac( float64 a )
 {
 
     return float64_val(a) & LIT64( 0x000FFFFFFFFFFFFF );
@@ -451,7 +451,7 @@ INLINE uint64_t extractFloat64Frac( float64 a )
 | Returns the exponent bits of the double-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE int_fast16_t extractFloat64Exp(float64 a)
+static inline int_fast16_t extractFloat64Exp(float64 a)
 {
 
     return ( float64_val(a)>>52 ) & 0x7FF;
@@ -462,7 +462,7 @@ INLINE int_fast16_t extractFloat64Exp(float64 a)
 | Returns the sign bit of the double-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE flag extractFloat64Sign( float64 a )
+static inline flag extractFloat64Sign( float64 a )
 {
 
     return float64_val(a)>>63;
@@ -513,7 +513,7 @@ static void
 | significand.
 *----------------------------------------------------------------------------*/
 
-INLINE float64 packFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig)
+static inline float64 packFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig)
 {
 
     return make_float64(
@@ -625,7 +625,7 @@ static float64
 | value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE uint64_t extractFloatx80Frac( floatx80 a )
+static inline uint64_t extractFloatx80Frac( floatx80 a )
 {
 
     return a.low;
@@ -637,7 +637,7 @@ INLINE uint64_t extractFloatx80Frac( floatx80 a )
 | value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE int32 extractFloatx80Exp( floatx80 a )
+static inline int32 extractFloatx80Exp( floatx80 a )
 {
 
     return a.high & 0x7FFF;
@@ -649,7 +649,7 @@ INLINE int32 extractFloatx80Exp( floatx80 a )
 | `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE flag extractFloatx80Sign( floatx80 a )
+static inline flag extractFloatx80Sign( floatx80 a )
 {
 
     return a.high>>15;
@@ -679,7 +679,7 @@ static void
 | extended double-precision floating-point value, returning the result.
 *----------------------------------------------------------------------------*/
 
-INLINE floatx80 packFloatx80( flag zSign, int32 zExp, uint64_t zSig )
+static inline floatx80 packFloatx80( flag zSign, int32 zExp, uint64_t zSig )
 {
     floatx80 z;
 
@@ -921,7 +921,7 @@ static floatx80
 | floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE uint64_t extractFloat128Frac1( float128 a )
+static inline uint64_t extractFloat128Frac1( float128 a )
 {
 
     return a.low;
@@ -933,7 +933,7 @@ INLINE uint64_t extractFloat128Frac1( float128 a )
 | floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE uint64_t extractFloat128Frac0( float128 a )
+static inline uint64_t extractFloat128Frac0( float128 a )
 {
 
     return a.high & LIT64( 0x0000FFFFFFFFFFFF );
@@ -945,7 +945,7 @@ INLINE uint64_t extractFloat128Frac0( float128 a )
 | `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE int32 extractFloat128Exp( float128 a )
+static inline int32 extractFloat128Exp( float128 a )
 {
 
     return ( a.high>>48 ) & 0x7FFF;
@@ -956,7 +956,7 @@ INLINE int32 extractFloat128Exp( float128 a )
 | Returns the sign bit of the quadruple-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
-INLINE flag extractFloat128Sign( float128 a )
+static inline flag extractFloat128Sign( float128 a )
 {
 
     return a.high>>63;
@@ -1017,7 +1017,7 @@ static void
 | significand.
 *----------------------------------------------------------------------------*/
 
-INLINE float128
+static inline float128
  packFloat128( flag zSign, int32 zExp, uint64_t zSig0, uint64_t zSig1 )
 {
     float128 z;
@@ -7088,7 +7088,7 @@ uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
 }
 
 #define COMPARE(s, nan_exp)                                                  \
-INLINE int float ## s ## _compare_internal( float ## s a, float ## s b,      \
+static inline int float ## s ## _compare_internal( float ## s a, float ## s b,      \
                                       int is_quiet STATUS_PARAM )            \
 {                                                                            \
     flag aSign, bSign;                                                       \
@@ -7140,7 +7140,7 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM )  \
 COMPARE(32, 0xff)
 COMPARE(64, 0x7ff)
 
-INLINE int floatx80_compare_internal( floatx80 a, floatx80 b,
+static inline int floatx80_compare_internal( floatx80 a, floatx80 b,
                                       int is_quiet STATUS_PARAM )
 {
     flag aSign, bSign;
@@ -7186,7 +7186,7 @@ int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
     return floatx80_compare_internal(a, b, 1 STATUS_VAR);
 }
 
-INLINE int float128_compare_internal( float128 a, float128 b,
+static inline int float128_compare_internal( float128 a, float128 b,
                                       int is_quiet STATUS_PARAM )
 {
     flag aSign, bSign;
@@ -7242,7 +7242,7 @@ int float128_compare_quiet( float128 a, float128 b STATUS_PARAM )
  * semantics provided by many CPUs which predate that specification.
  */
 #define MINMAX(s)                                                       \
-INLINE float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
+static inline float ## s float ## s ## _minmax(float ## s a, float ## s b,     \
                                         int ismin, int isieee STATUS_PARAM) \
 {                                                                       \
     flag aSign, bSign;                                                  \
diff --git a/hmp.c b/hmp.c
index 41006f5eef..dc3d2795d2 100644
--- a/hmp.c
+++ b/hmp.c
@@ -465,7 +465,8 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict)
         for (client = info->clients; client; client = client->next) {
             monitor_printf(mon, "Client:\n");
             monitor_printf(mon, "     address: %s:%s\n",
-                           client->value->host, client->value->service);
+                           client->value->base->host,
+                           client->value->base->service);
             monitor_printf(mon, "  x509_dname: %s\n",
                            client->value->x509_dname ?
                            client->value->x509_dname : "none");
@@ -513,7 +514,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict)
         for (chan = info->channels; chan; chan = chan->next) {
             monitor_printf(mon, "Channel:\n");
             monitor_printf(mon, "     address: %s:%s%s\n",
-                           chan->value->host, chan->value->port,
+                           chan->value->base->host, chan->value->base->port,
                            chan->value->tls ? " [tls]" : "");
             monitor_printf(mon, "     session: %" PRId64 "\n",
                            chan->value->connection_id);
@@ -1692,7 +1693,7 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
         ov = string_output_visitor_new(false);
         visit_type_uint16List(string_output_get_visitor(ov),
                               &m->value->host_nodes, NULL, NULL);
-        monitor_printf(mon, "memory device %d\n", i);
+        monitor_printf(mon, "memory backend: %d\n", i);
         monitor_printf(mon, "  size:  %" PRId64 "\n", m->value->size);
         monitor_printf(mon, "  merge: %s\n",
                        m->value->merge ? "true" : "false");
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 79414b44c7..a7368fb242 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -22,11 +22,11 @@
 #include "hw/hw.h"
 #include "hw/i386/pc.h"
 #include "hw/acpi/acpi.h"
-#include "monitor/monitor.h"
 #include "qemu/config-file.h"
 #include "qapi/opts-visitor.h"
 #include "qapi/dealloc-visitor.h"
 #include "qapi-visit.h"
+#include "qapi-event.h"
 
 struct acpi_table_header {
     uint16_t _length;         /* our length, not actual part of the hdr */
@@ -550,7 +550,7 @@ static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
             break;
         default:
             if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */
-                monitor_protocol_event(QEVENT_SUSPEND_DISK, NULL);
+                qapi_event_send_suspend_disk(&error_abort);
                 qemu_system_shutdown_request();
             }
             break;
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index de4ddc204f..38ca415f64 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -3,10 +3,7 @@
 #include "hw/mem/pc-dimm.h"
 #include "hw/boards.h"
 #include "trace.h"
-#include "qapi-visit.h"
-#include "monitor/monitor.h"
-#include "qapi/dealloc-visitor.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi-event.h"
 
 static ACPIOSTInfo *acpi_memory_device_status(int slot, MemStatus *mdev)
 {
@@ -39,29 +36,6 @@ void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list)
     }
 }
 
-static void acpi_memory_ost_mon_event(const MemHotplugState *mem_st)
-{
-    Visitor *v;
-    QObject *out_info;
-    QapiDeallocVisitor *md;
-    QmpOutputVisitor *mo = qmp_output_visitor_new();
-    MemStatus *mdev = &mem_st->devs[mem_st->selector];
-    ACPIOSTInfo *info = acpi_memory_device_status(mem_st->selector, mdev);
-
-    v = qmp_output_get_visitor(mo);
-    visit_type_ACPIOSTInfo(v, &info, "unused", NULL);
-
-    out_info = qmp_output_get_qobject(mo);
-    monitor_protocol_event(QEVENT_ACPI_OST, out_info);
-    qobject_decref(out_info);
-
-    qmp_output_visitor_cleanup(mo);
-    md = qapi_dealloc_visitor_new();
-    v = qapi_dealloc_get_visitor(md);
-    visit_type_ACPIOSTInfo(v, &info, "unused", NULL);
-    qapi_dealloc_visitor_cleanup(md);
-}
-
 static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
                                          unsigned int size)
 {
@@ -115,6 +89,7 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
 {
     MemHotplugState *mem_st = opaque;
     MemStatus *mdev;
+    ACPIOSTInfo *info;
 
     if (!mem_st->dev_count) {
         return;
@@ -147,7 +122,10 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
         mdev->ost_status = data;
         trace_mhp_acpi_write_ost_status(mem_st->selector, mdev->ost_status);
         /* TODO: implement memory removal on guest signal */
-        acpi_memory_ost_mon_event(mem_st);
+
+        info = acpi_memory_device_status(mem_st->selector, mdev);
+        qapi_event_send_acpi_device_ost(info, &error_abort);
+        qapi_free_ACPIOSTInfo(info);
         break;
     case 0x14:
         mdev = &mem_st->devs[mem_st->selector];
diff --git a/hw/audio/fmopl.c b/hw/audio/fmopl.c
index 290a224edc..adcef2d3b9 100644
--- a/hw/audio/fmopl.c
+++ b/hw/audio/fmopl.c
@@ -30,7 +30,6 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#define INLINE		static inline
 #define HAS_YM3812	1
 
 #include <stdio.h>
@@ -247,7 +246,7 @@ static INT32 feedback2;		/* connect for SLOT 2 */
 
 /* --------------------- subroutines  --------------------- */
 
-INLINE int Limit( int val, int max, int min ) {
+static inline int Limit( int val, int max, int min ) {
 	if ( val > max )
 		val = max;
 	else if ( val < min )
@@ -257,7 +256,7 @@ INLINE int Limit( int val, int max, int min ) {
 }
 
 /* status set and IRQ handling */
-INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
+static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
 {
 	/* set status flag */
 	OPL->status |= flag;
@@ -273,7 +272,7 @@ INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
 }
 
 /* status reset and IRQ handling */
-INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
+static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
 {
 	/* reset status flag */
 	OPL->status &=~flag;
@@ -289,7 +288,7 @@ INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
 }
 
 /* IRQ mask set */
-INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
+static inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
 {
 	OPL->statusmask = flag;
 	/* IRQ handling check */
@@ -298,7 +297,7 @@ INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
 }
 
 /* ----- key on  ----- */
-INLINE void OPL_KEYON(OPL_SLOT *SLOT)
+static inline void OPL_KEYON(OPL_SLOT *SLOT)
 {
 	/* sin wave restart */
 	SLOT->Cnt = 0;
@@ -309,7 +308,7 @@ INLINE void OPL_KEYON(OPL_SLOT *SLOT)
 	SLOT->eve = EG_AED;
 }
 /* ----- key off ----- */
-INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
+static inline void OPL_KEYOFF(OPL_SLOT *SLOT)
 {
 	if( SLOT->evm > ENV_MOD_RR)
 	{
@@ -325,7 +324,7 @@ INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
 
 /* ---------- calcrate Envelope Generator & Phase Generator ---------- */
 /* return : envelope output */
-INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
+static inline UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
 {
 	/* calcrate envelope generator */
 	if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
@@ -371,7 +370,7 @@ static void set_algorithm( OPL_CH *CH)
 }
 
 /* ---------- frequency counter for operater update ---------- */
-INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
+static inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
 {
 	int ksr;
 
@@ -391,7 +390,7 @@ INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
 }
 
 /* set multi,am,vib,EG-TYP,KSR,mul */
-INLINE void set_mul(FM_OPL *OPL,int slot,int v)
+static inline void set_mul(FM_OPL *OPL,int slot,int v)
 {
 	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@@ -405,7 +404,7 @@ INLINE void set_mul(FM_OPL *OPL,int slot,int v)
 }
 
 /* set ksl & tl */
-INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
+static inline void set_ksl_tl(FM_OPL *OPL,int slot,int v)
 {
 	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@@ -421,7 +420,7 @@ INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
 }
 
 /* set attack rate & decay rate  */
-INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
+static inline void set_ar_dr(FM_OPL *OPL,int slot,int v)
 {
 	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@@ -438,7 +437,7 @@ INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
 }
 
 /* set sustain level & release rate */
-INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
+static inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
 {
 	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@@ -455,7 +454,7 @@ INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
 /* operator output calcrator */
 #define OP_OUT(slot,env,con)   slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
 /* ---------- calcrate one of channel ---------- */
-INLINE void OPL_CALC_CH( OPL_CH *CH )
+static inline void OPL_CALC_CH( OPL_CH *CH )
 {
 	UINT32 env_out;
 	OPL_SLOT *SLOT;
@@ -500,7 +499,7 @@ INLINE void OPL_CALC_CH( OPL_CH *CH )
 
 /* ---------- calcrate rhythm block ---------- */
 #define WHITE_NOISE_db 6.0
-INLINE void OPL_CALC_RH( OPL_CH *CH )
+static inline void OPL_CALC_RH( OPL_CH *CH )
 {
 	UINT32 env_tam,env_sd,env_top,env_hh;
 	int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
@@ -716,7 +715,7 @@ static void OPLCloseTable( void )
 }
 
 /* CSM Key Control */
-INLINE void CSMKeyControll(OPL_CH *CH)
+static inline void CSMKeyControll(OPL_CH *CH)
 {
 	OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
 	OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 85aa8715ba..08562ea390 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -56,17 +56,17 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
     BlockErrorAction action = bdrv_get_error_action(req->dev->bs, is_read, error);
     VirtIOBlock *s = req->dev;
 
-    if (action == BDRV_ACTION_STOP) {
+    if (action == BLOCK_ERROR_ACTION_STOP) {
         req->next = s->rq;
         s->rq = req;
-    } else if (action == BDRV_ACTION_REPORT) {
+    } else if (action == BLOCK_ERROR_ACTION_REPORT) {
         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
         bdrv_acct_done(s->bs, &req->acct);
         g_free(req);
     }
 
     bdrv_error_action(s->bs, action, is_read, error);
-    return action != BDRV_ACTION_IGNORE;
+    return action != BLOCK_ERROR_ACTION_IGNORE;
 }
 
 static void virtio_blk_rw_complete(void *opaque, int ret)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index b9cd4fc814..d1eba3cc3d 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -32,9 +32,9 @@
 #include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
 #include "qapi/qmp/qjson.h"
-#include "monitor/monitor.h"
 #include "hw/hotplug.h"
 #include "hw/boards.h"
+#include "qapi-event.h"
 
 int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
@@ -972,7 +972,6 @@ static void device_unparent(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
     BusState *bus;
-    QObject *event_data;
     bool have_realized = dev->realized;
 
     if (dev->realized) {
@@ -992,14 +991,7 @@ static void device_unparent(Object *obj)
     if (have_realized) {
         gchar *path = object_get_canonical_path(OBJECT(dev));
 
-        if (dev->id) {
-            event_data = qobject_from_jsonf("{ 'device': %s, 'path': %s }",
-                                            dev->id, path);
-        } else {
-            event_data = qobject_from_jsonf("{ 'path': %s }", path);
-        }
-        monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
-        qobject_decref(event_data);
+        qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);
         g_free(path);
     }
 }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 67eb45089e..2cf22b1293 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1643,11 +1643,58 @@ pc_machine_get_hotplug_memory_region_size(Object *obj, Visitor *v, void *opaque,
     visit_type_int(v, &value, name, errp);
 }
 
+static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v,
+                                         void *opaque, const char *name,
+                                         Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+    uint64_t value = pcms->max_ram_below_4g;
+
+    visit_type_size(v, &value, name, errp);
+}
+
+static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
+                                         void *opaque, const char *name,
+                                         Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+    Error *error = NULL;
+    uint64_t value;
+
+    visit_type_size(v, &value, name, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+    if (value > (1ULL << 32)) {
+        error_set(&error, ERROR_CLASS_GENERIC_ERROR,
+                  "Machine option 'max-ram-below-4g=%"PRIu64
+                  "' expects size less than or equal to 4G", value);
+        error_propagate(errp, error);
+        return;
+    }
+
+    if (value < (1ULL << 20)) {
+        error_report("Warning: small max_ram_below_4g(%"PRIu64
+                     ") less than 1M.  BIOS may not work..",
+                     value);
+    }
+
+    pcms->max_ram_below_4g = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
+    PCMachineState *pcms = PC_MACHINE(obj);
+
     object_property_add(obj, PC_MACHINE_MEMHP_REGION_SIZE, "int",
                         pc_machine_get_hotplug_memory_region_size,
                         NULL, NULL, NULL, NULL);
+    pcms->max_ram_below_4g = 1ULL << 32; /* 4G */
+    object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
+                        pc_machine_get_max_ram_below_4g,
+                        pc_machine_set_max_ram_below_4g,
+                        NULL, NULL, NULL);
 }
 
 static void pc_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 3e7524b961..47546b72ae 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -48,6 +48,7 @@
 #include "exec/address-spaces.h"
 #include "hw/acpi/acpi.h"
 #include "cpu.h"
+#include "qemu/error-report.h"
 #ifdef CONFIG_XEN
 #  include <xen/hvm/hvm_info_table.h>
 #endif
@@ -98,21 +99,7 @@ static void pc_init1(MachineState *machine,
     DeviceState *icc_bridge;
     FWCfgState *fw_cfg = NULL;
     PcGuestInfo *guest_info;
-
-    if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) {
-        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
-        exit(1);
-    }
-
-    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
-    object_property_add_child(qdev_get_machine(), "icc-bridge",
-                              OBJECT(icc_bridge), NULL);
-
-    pc_cpus_init(machine->cpu_model, icc_bridge);
-
-    if (kvm_enabled() && kvmclock_enabled) {
-        kvmclock_create();
-    }
+    ram_addr_t lowmem;
 
     /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory).
      * If it doesn't, we need to split it in chunks below and above 4G.
@@ -122,7 +109,25 @@ static void pc_init1(MachineState *machine,
      * breaking migration.
      */
     if (machine->ram_size >= 0xe0000000) {
-        ram_addr_t lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000;
+        lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000;
+    } else {
+        lowmem = 0xe0000000;
+    }
+
+    /* Handle the machine opt max-ram-below-4g.  It is basicly doing
+     * min(qemu limit, user limit).
+     */
+    if (lowmem > pc_machine->max_ram_below_4g) {
+        lowmem = pc_machine->max_ram_below_4g;
+        if (machine->ram_size - lowmem > lowmem &&
+            lowmem & ((1ULL << 30) - 1)) {
+            error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
+                         ") not a multiple of 1G; possible bad performance.",
+                         pc_machine->max_ram_below_4g);
+        }
+    }
+
+    if (machine->ram_size >= lowmem) {
         above_4g_mem_size = machine->ram_size - lowmem;
         below_4g_mem_size = lowmem;
     } else {
@@ -130,6 +135,22 @@ static void pc_init1(MachineState *machine,
         below_4g_mem_size = machine->ram_size;
     }
 
+    if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size,
+                                      &ram_memory) != 0) {
+        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
+        exit(1);
+    }
+
+    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
+    object_property_add_child(qdev_get_machine(), "icc-bridge",
+                              OBJECT(icc_bridge), NULL);
+
+    pc_cpus_init(machine->cpu_model, icc_bridge);
+
+    if (kvm_enabled() && kvmclock_enabled) {
+        kvmclock_create();
+    }
+
     if (pci_enabled) {
         pci_memory = g_new(MemoryRegion, 1);
         memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index aa71332ee1..155db99f63 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -44,6 +44,7 @@
 #include "hw/ide/ahci.h"
 #include "hw/usb.h"
 #include "hw/cpu/icc_bus.h"
+#include "qemu/error-report.h"
 
 /* ICH9 AHCI has 6 ports */
 #define MAX_SATA_PORTS     6
@@ -85,20 +86,7 @@ static void pc_q35_init(MachineState *machine)
     PCIDevice *ahci;
     DeviceState *icc_bridge;
     PcGuestInfo *guest_info;
-
-    if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) {
-        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
-        exit(1);
-    }
-
-    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
-    object_property_add_child(qdev_get_machine(), "icc-bridge",
-                              OBJECT(icc_bridge), NULL);
-
-    pc_cpus_init(machine->cpu_model, icc_bridge);
-    pc_acpi_init("q35-acpi-dsdt.aml");
-
-    kvmclock_create();
+    ram_addr_t lowmem;
 
     /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
      * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
@@ -110,7 +98,25 @@ static void pc_q35_init(MachineState *machine)
      * breaking migration.
      */
     if (machine->ram_size >= 0xb0000000) {
-        ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
+        lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
+    } else {
+        lowmem = 0xb0000000;
+    }
+
+    /* Handle the machine opt max-ram-below-4g.  It is basicly doing
+     * min(qemu limit, user limit).
+     */
+    if (lowmem > pc_machine->max_ram_below_4g) {
+        lowmem = pc_machine->max_ram_below_4g;
+        if (machine->ram_size - lowmem > lowmem &&
+            lowmem & ((1ULL << 30) - 1)) {
+            error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
+                         ") not a multiple of 1G; possible bad performance.",
+                         pc_machine->max_ram_below_4g);
+        }
+    }
+
+    if (machine->ram_size >= lowmem) {
         above_4g_mem_size = machine->ram_size - lowmem;
         below_4g_mem_size = lowmem;
     } else {
@@ -118,6 +124,21 @@ static void pc_q35_init(MachineState *machine)
         below_4g_mem_size = machine->ram_size;
     }
 
+    if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size,
+                                      &ram_memory) != 0) {
+        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
+        exit(1);
+    }
+
+    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
+    object_property_add_child(qdev_get_machine(), "icc-bridge",
+                              OBJECT(icc_bridge), NULL);
+
+    pc_cpus_init(machine->cpu_model, icc_bridge);
+    pc_acpi_init("q35-acpi-dsdt.aml");
+
+    kvmclock_create();
+
     /* pci enabled */
     if (pci_enabled) {
         pci_memory = g_new(MemoryRegion, 1);
@@ -388,7 +409,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
     .name = "pc-q35-1.4",
     .init = pc_q35_init_1_4,
     .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_4,
+        PC_Q35_COMPAT_1_4,
         { /* end of list */ }
     },
 };
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 1cac5f53dc..3a38f1e599 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -596,10 +596,10 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
     bool is_read = (op & BM_STATUS_RETRY_READ) != 0;
     BlockErrorAction action = bdrv_get_error_action(s->bs, is_read, error);
 
-    if (action == BDRV_ACTION_STOP) {
+    if (action == BLOCK_ERROR_ACTION_STOP) {
         s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
         s->bus->error_status = op;
-    } else if (action == BDRV_ACTION_REPORT) {
+    } else if (action == BLOCK_ERROR_ACTION_REPORT) {
         if (op & BM_STATUS_DMA_RETRY) {
             dma_buf_commit(s);
             ide_dma_error(s);
@@ -608,7 +608,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
         }
     }
     bdrv_error_action(s->bs, action, is_read, error);
-    return action != BDRV_ACTION_IGNORE;
+    return action != BLOCK_ERROR_ACTION_IGNORE;
 }
 
 void ide_dma_cb(void *opaque, int ret)
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index 5377feed69..994f8af8e6 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -14,12 +14,12 @@
 
 #include "qapi/qmp/qobject.h"
 #include "qapi/qmp/qjson.h"
-#include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
 
 #include "hw/nvram/fw_cfg.h"
 #include "hw/i386/pc.h"
+#include "qapi-event.h"
 
 /* The bit of supported pv event */
 #define PVPANIC_F_PANICKED      0
@@ -31,15 +31,6 @@
 #define ISA_PVPANIC_DEVICE(obj)    \
     OBJECT_CHECK(PVPanicState, (obj), TYPE_ISA_PVPANIC_DEVICE)
 
-static void panicked_mon_event(const char *action)
-{
-    QObject *data;
-
-    data = qobject_from_jsonf("{ 'action': %s }", action);
-    monitor_protocol_event(QEVENT_GUEST_PANICKED, data);
-    qobject_decref(data);
-}
-
 static void handle_event(int event)
 {
     static bool logged;
@@ -50,7 +41,7 @@ static void handle_event(int event)
     }
 
     if (event & PVPANIC_PANICKED) {
-        panicked_mon_event("pause");
+        qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
         vm_stop(RUN_STATE_GUEST_PANICKED);
         return;
     }
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 57bdffde08..0fc29a0ae3 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -175,6 +175,8 @@ e1000_link_down(E1000State *s)
 {
     s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
     s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+    s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
+    s->phy_reg[PHY_LP_ABILITY] &= ~MII_LPAR_LPACK;
 }
 
 static void
@@ -197,23 +199,11 @@ set_phy_ctrl(E1000State *s, int index, uint16_t val)
     }
     if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
         e1000_link_down(s);
-        s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
         DBGOUT(PHY, "Start link auto negotiation\n");
         timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
     }
 }
 
-static void
-e1000_autoneg_timer(void *opaque)
-{
-    E1000State *s = opaque;
-    if (!qemu_get_queue(s->nic)->link_down) {
-        e1000_link_up(s);
-    }
-    s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
-    DBGOUT(PHY, "Auto negotiation is completed\n");
-}
-
 static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = {
     [PHY_CTRL] = set_phy_ctrl,
 };
@@ -227,7 +217,8 @@ static const char phy_regcap[0x20] = {
     [PHY_CTRL] = PHY_RW,	[PHY_1000T_CTRL] = PHY_RW,
     [PHY_LP_ABILITY] = PHY_R,	[PHY_1000T_STATUS] = PHY_R,
     [PHY_AUTONEG_ADV] = PHY_RW,	[M88E1000_RX_ERR_CNTR] = PHY_R,
-    [PHY_ID2] = PHY_R,		[M88E1000_PHY_SPEC_STATUS] = PHY_R
+    [PHY_ID2] = PHY_R,		[M88E1000_PHY_SPEC_STATUS] = PHY_R,
+    [PHY_AUTONEG_EXP] = PHY_R,
 };
 
 /* PHY_ID2 documented in 8254x_GBe_SDM.pdf, pp. 250 */
@@ -344,6 +335,19 @@ set_ics(E1000State *s, int index, uint32_t val)
     set_interrupt_cause(s, 0, val | s->mac_reg[ICR]);
 }
 
+static void
+e1000_autoneg_timer(void *opaque)
+{
+    E1000State *s = opaque;
+    if (!qemu_get_queue(s->nic)->link_down) {
+        e1000_link_up(s);
+        s->phy_reg[PHY_LP_ABILITY] |= MII_LPAR_LPACK;
+        s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+        DBGOUT(PHY, "Auto negotiation is completed\n");
+        set_ics(s, 0, E1000_ICS_LSC); /* signal link status change to guest */
+    }
+}
+
 static int
 rxbufsize(uint32_t v)
 {
@@ -844,6 +848,14 @@ receive_filter(E1000State *s, const uint8_t *buf, int size)
     return 0;
 }
 
+static bool
+have_autoneg(E1000State *s)
+{
+    return (s->compat_flags & E1000_FLAG_AUTONEG) &&
+           (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN) &&
+           (s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG);
+}
+
 static void
 e1000_set_link_status(NetClientState *nc)
 {
@@ -853,7 +865,14 @@ e1000_set_link_status(NetClientState *nc)
     if (nc->link_down) {
         e1000_link_down(s);
     } else {
-        e1000_link_up(s);
+        if (have_autoneg(s) &&
+            !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
+            /* emulate auto-negotiation if supported */
+            timer_mod(s->autoneg_timer,
+                      qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
+        } else {
+            e1000_link_up(s);
+        }
     }
 
     if (s->mac_reg[STATUS] != old_status)
@@ -1279,19 +1298,13 @@ static void e1000_pre_save(void *opaque)
         e1000_mit_timer(s);
     }
 
-    if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
-        return;
-    }
-
     /*
-     * If link is down and auto-negotiation is ongoing, complete
-     * auto-negotiation immediately.  This allows is to look at
-     * MII_SR_AUTONEG_COMPLETE to infer link status on load.
+     * If link is down and auto-negotiation is supported and ongoing,
+     * complete auto-negotiation immediately. This allows us to look
+     * at MII_SR_AUTONEG_COMPLETE to infer link status on load.
      */
-    if (nc->link_down &&
-        s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
-        s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG) {
-         s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+    if (nc->link_down && have_autoneg(s)) {
+        s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
     }
 }
 
@@ -1313,15 +1326,11 @@ static int e1000_post_load(void *opaque, int version_id)
      * Alternatively, restart link negotiation if it was in progress. */
     nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;
 
-    if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
-        return 0;
-    }
-
-    if (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
-        s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG &&
+    if (have_autoneg(s) &&
         !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
         nc->link_down = false;
-        timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
+        timer_mod(s->autoneg_timer,
+                  qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
     }
 
     return 0;
diff --git a/hw/net/e1000_regs.h b/hw/net/e1000_regs.h
index 13ac6713d4..60b96aaf13 100644
--- a/hw/net/e1000_regs.h
+++ b/hw/net/e1000_regs.h
@@ -384,6 +384,9 @@
 #define MII_SR_100X_FD_CAPS      0x4000	/* 100X  Full Duplex Capable */
 #define MII_SR_100T4_CAPS        0x8000	/* 100T4 Capable */
 
+/* PHY Link Partner Ability Register */
+#define MII_LPAR_LPACK           0x4000 /* Acked by link partner */
+
 /* Interrupt Cause Read */
 #define E1000_ICR_TXDW          0x00000001 /* Transmit desc written back */
 #define E1000_ICR_TXQE          0x00000002 /* Transmit Queue empty */
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d8588f3808..00b5e07ddd 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -22,7 +22,7 @@
 #include "net/vhost_net.h"
 #include "hw/virtio/virtio-bus.h"
 #include "qapi/qmp/qjson.h"
-#include "monitor/monitor.h"
+#include "qapi-event.h"
 
 #define VIRTIO_NET_VM_VERSION    11
 
@@ -199,19 +199,12 @@ static void virtio_net_set_link_status(NetClientState *nc)
 
 static void rxfilter_notify(NetClientState *nc)
 {
-    QObject *event_data;
     VirtIONet *n = qemu_get_nic_opaque(nc);
 
     if (nc->rxfilter_notify_enabled) {
         gchar *path = object_get_canonical_path(OBJECT(n->qdev));
-        if (n->netclient_name) {
-            event_data = qobject_from_jsonf("{ 'name': %s, 'path': %s }",
-                                    n->netclient_name, path);
-        } else {
-            event_data = qobject_from_jsonf("{ 'path': %s }", path);
-        }
-        monitor_protocol_event(QEVENT_NIC_RX_FILTER_CHANGED, event_data);
-        qobject_decref(event_data);
+        qapi_event_send_nic_rx_filter_changed(!!n->netclient_name,
+                                              n->netclient_name, path, &error_abort);
         g_free(path);
 
         /* disable event notification to avoid events flooding */
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index f4e17ac41a..7cd87fcbb4 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -180,6 +180,12 @@ PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
     return PCIE_SLOT(d);
 }
 
+static Property ioh3420_props[] = {
+    DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
+                    QEMU_PCIE_SLTCAP_PCP_BITNR, true),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 static const VMStateDescription vmstate_ioh3420 = {
     .name = "ioh-3240-express-root-port",
     .version_id = 1,
@@ -210,6 +216,7 @@ static void ioh3420_class_init(ObjectClass *klass, void *data)
     dc->desc = "Intel IOH device id 3420 PCIE Root Port";
     dc->reset = ioh3420_reset;
     dc->vmsd = &vmstate_ioh3420;
+    dc->props = ioh3420_props;
 }
 
 static const TypeInfo ioh3420_info = {
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index 8f22f93f8e..51f20d7467 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -147,6 +147,12 @@ PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
     return PCIE_SLOT(d);
 }
 
+static Property xio3130_downstream_props[] = {
+    DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
+                    QEMU_PCIE_SLTCAP_PCP_BITNR, true),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 static const VMStateDescription vmstate_xio3130_downstream = {
     .name = "xio3130-express-downstream-port",
     .version_id = 1,
@@ -177,6 +183,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
     dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
     dc->reset = xio3130_downstream_reset;
     dc->vmsd = &vmstate_xio3130_downstream;
+    dc->props = xio3130_downstream_props;
 }
 
 static const TypeInfo xio3130_downstream_info = {
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 02cde6f96c..a123c01ef1 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -224,7 +224,7 @@ static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev,
     *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
     uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA);
 
-    PCIE_DEV_PRINTF(PCI_DEVICE(dev), "hotplug state: %d\n", state);
+    PCIE_DEV_PRINTF(PCI_DEVICE(dev), "hotplug state: 0x%x\n", sltsta);
     if (sltsta & PCI_EXP_SLTSTA_EIS) {
         /* the slot is electromechanically locked.
          * This error is propagated up to qdev and then to HMP/QMP.
@@ -258,7 +258,8 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
 
     pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
                                PCI_EXP_SLTSTA_PDS);
-    pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
+    pcie_cap_slot_event(PCI_DEVICE(hotplug_dev),
+                        PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
 }
 
 void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
@@ -268,10 +269,7 @@ void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
 
     pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
 
-    object_unparent(OBJECT(dev));
-    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
-                                 PCI_EXP_SLTSTA_PDS);
-    pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
+    pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev));
 }
 
 /* pci express slot for pci express root/downstream port
@@ -294,6 +292,15 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot)
                                PCI_EXP_SLTCAP_AIP |
                                PCI_EXP_SLTCAP_ABP);
 
+    if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) {
+        pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP,
+                                   PCI_EXP_SLTCAP_PCP);
+        pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL,
+                                     PCI_EXP_SLTCTL_PCC);
+        pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
+                                   PCI_EXP_SLTCTL_PCC);
+    }
+
     pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL,
                                  PCI_EXP_SLTCTL_PIC |
                                  PCI_EXP_SLTCTL_AIC);
@@ -327,6 +334,10 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot)
 void pcie_cap_slot_reset(PCIDevice *dev)
 {
     uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+    uint8_t port_type = pcie_cap_get_type(dev);
+
+    assert(port_type == PCI_EXP_TYPE_DOWNSTREAM ||
+           port_type == PCI_EXP_TYPE_ROOT_PORT);
 
     PCIE_DEV_PRINTF(dev, "reset\n");
 
@@ -339,9 +350,25 @@ void pcie_cap_slot_reset(PCIDevice *dev)
                                  PCI_EXP_SLTCTL_PDCE |
                                  PCI_EXP_SLTCTL_ABPE);
     pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL,
-                               PCI_EXP_SLTCTL_PIC_OFF |
                                PCI_EXP_SLTCTL_AIC_OFF);
 
+    if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) {
+        /* Downstream ports enforce device number 0. */
+        bool populated = pci_bridge_get_sec_bus(PCI_BRIDGE(dev))->devices[0];
+        uint16_t pic;
+
+        if (populated) {
+            pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
+                                         PCI_EXP_SLTCTL_PCC);
+        } else {
+            pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL,
+                                       PCI_EXP_SLTCTL_PCC);
+        }
+
+        pic = populated ? PCI_EXP_SLTCTL_PIC_ON : PCI_EXP_SLTCTL_PIC_OFF;
+        pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL, pic);
+    }
+
     pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
                                  PCI_EXP_SLTSTA_EIS |/* on reset,
                                                         the lock is released */
@@ -352,6 +379,11 @@ void pcie_cap_slot_reset(PCIDevice *dev)
     hotplug_event_update_event_status(dev);
 }
 
+static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
+{
+    object_unparent(OBJECT(dev));
+}
+
 void pcie_cap_slot_write_config(PCIDevice *dev,
                                 uint32_t addr, uint32_t val, int len)
 {
@@ -376,6 +408,22 @@ void pcie_cap_slot_write_config(PCIDevice *dev,
                         sltsta);
     }
 
+    /*
+     * If the slot is polulated, power indicator is off and power
+     * controller is off, it is safe to detach the devices.
+     */
+    if ((sltsta & PCI_EXP_SLTSTA_PDS) && (val & PCI_EXP_SLTCTL_PCC) &&
+        ((val & PCI_EXP_SLTCTL_PIC_OFF) == PCI_EXP_SLTCTL_PIC_OFF)) {
+            PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
+            pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+                                pcie_unplug_device, NULL);
+
+            pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
+                                         PCI_EXP_SLTSTA_PDS);
+            pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
+                                       PCI_EXP_SLTSTA_PDC);
+    }
+
     hotplug_event_notify(dev);
 
     /* 
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index ea4a2b2698..8d08539baa 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -32,6 +32,7 @@
 
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
+#include "qapi-event.h"
 
 #include <libfdt.h>
 
@@ -93,7 +94,7 @@ static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     tm.tm_sec = rtas_ld(args, 5);
 
     /* Just generate a monitor event for the change */
-    rtc_change_mon_event(&tm);
+    qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
     spapr->rtc_offset = qemu_timedate_diff(&tm);
 
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index a529ad24c7..d47ecd6ab4 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -419,7 +419,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
     BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read, error);
 
-    if (action == BDRV_ACTION_REPORT) {
+    if (action == BLOCK_ERROR_ACTION_REPORT) {
         switch (error) {
         case ENOMEDIUM:
             scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
@@ -439,10 +439,10 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
         }
     }
     bdrv_error_action(s->qdev.conf.bs, action, is_read, error);
-    if (action == BDRV_ACTION_STOP) {
+    if (action == BLOCK_ERROR_ACTION_STOP) {
         scsi_req_retry(&r->req);
     }
-    return action != BDRV_ACTION_IGNORE;
+    return action != BLOCK_ERROR_ACTION_IGNORE;
 }
 
 static void scsi_write_complete(void * opaque, int ret)
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 1201f90db5..05002bf9d6 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -26,6 +26,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/timer/mc146818rtc.h"
 #include "qapi/visitor.h"
+#include "qapi-event.h"
 
 #ifdef TARGET_I386
 #include "hw/i386/apic.h"
@@ -530,7 +531,7 @@ static void rtc_set_time(RTCState *s)
     s->base_rtc = mktimegm(&tm);
     s->last_update = qemu_clock_get_ns(rtc_clock);
 
-    rtc_change_mon_event(&tm);
+    qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
 }
 
 static void rtc_set_cmos(RTCState *s, const struct tm *tm)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index c1b1aad6cf..e55fe1cc7e 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -20,6 +20,7 @@
 #include <linux/vhost.h>
 #include "exec/address-spaces.h"
 #include "hw/virtio/virtio-bus.h"
+#include "migration/migration.h"
 
 static void vhost_dev_sync_region(struct vhost_dev *dev,
                                   MemoryRegionSection *section,
@@ -304,7 +305,9 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
                                       uint64_t size)
 {
     int i;
-    for (i = 0; i < dev->nvqs; ++i) {
+    int r = 0;
+
+    for (i = 0; !r && i < dev->nvqs; ++i) {
         struct vhost_virtqueue *vq = dev->vqs + i;
         hwaddr l;
         void *p;
@@ -316,15 +319,15 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
         p = cpu_physical_memory_map(vq->ring_phys, &l, 1);
         if (!p || l != vq->ring_size) {
             fprintf(stderr, "Unable to map ring buffer for ring %d\n", i);
-            return -ENOMEM;
+            r = -ENOMEM;
         }
         if (p != vq->ring) {
             fprintf(stderr, "Ring buffer relocated for ring %d\n", i);
-            return -EBUSY;
+            r = -EBUSY;
         }
         cpu_physical_memory_unmap(p, l, 0, 0);
     }
-    return 0;
+    return r;
 }
 
 static struct vhost_memory_region *vhost_dev_find_reg(struct vhost_dev *dev,
@@ -854,6 +857,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         .eventfd_del = vhost_eventfd_del,
         .priority = 10
     };
+    hdev->migration_blocker = NULL;
+    if (!(hdev->features & (0x1 << VHOST_F_LOG_ALL))) {
+        error_setg(&hdev->migration_blocker,
+                   "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature.");
+        migrate_add_blocker(hdev->migration_blocker);
+    }
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
     hdev->n_mem_sections = 0;
     hdev->mem_sections = NULL;
@@ -882,6 +891,10 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
         vhost_virtqueue_cleanup(hdev->vqs + i);
     }
     memory_listener_unregister(&hdev->memory_listener);
+    if (hdev->migration_blocker) {
+        migrate_del_blocker(hdev->migration_blocker);
+        error_free(hdev->migration_blocker);
+    }
     g_free(hdev->mem);
     g_free(hdev->mem_sections);
     hdev->vhost_ops->vhost_backend_cleanup(hdev);
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 22cd52edee..2a2e58a297 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -24,6 +24,7 @@
 #include "sysemu/kvm.h"
 #include "exec/address-spaces.h"
 #include "qapi/visitor.h"
+#include "qapi-event.h"
 
 #if defined(__linux__)
 #include <sys/mman.h>
@@ -289,8 +290,9 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
     memcpy(&config, config_data, sizeof(struct virtio_balloon_config));
     dev->actual = le32_to_cpu(config.actual);
     if (dev->actual != oldactual) {
-        qemu_balloon_changed(ram_size -
-                       ((ram_addr_t) dev->actual << VIRTIO_BALLOON_PFN_SHIFT));
+        qapi_event_send_balloon_change(ram_size -
+                        ((ram_addr_t) dev->actual << VIRTIO_BALLOON_PFN_SHIFT),
+                        &error_abort);
     }
 }
 
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index ce97514b69..57e1e6141e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -976,6 +976,8 @@ static void virtio_pci_device_plugged(DeviceState *d)
 
     if (proxy->nvectors &&
         msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) {
+        error_report("unable to init msix vectors to %" PRIu32,
+                     proxy->nvectors);
         proxy->nvectors = 0;
     }
 
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index f28161b2d6..4aebd34924 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -24,9 +24,9 @@
 #include "qemu/config-file.h"
 #include "qemu/queue.h"
 #include "qapi/qmp/types.h"
-#include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/watchdog.h"
+#include "qapi-event.h"
 
 /* Possible values for action parameter. */
 #define WDT_RESET        1	/* Hard reset. */
@@ -101,15 +101,6 @@ int select_watchdog_action(const char *p)
     return 0;
 }
 
-static void watchdog_mon_event(const char *action)
-{
-    QObject *data;
-
-    data = qobject_from_jsonf("{ 'action': %s }", action);
-    monitor_protocol_event(QEVENT_WATCHDOG, data);
-    qobject_decref(data);
-}
-
 /* This actually performs the "action" once a watchdog has expired,
  * ie. reboot, shutdown, exit, etc.
  */
@@ -117,31 +108,31 @@ void watchdog_perform_action(void)
 {
     switch(watchdog_action) {
     case WDT_RESET:             /* same as 'system_reset' in monitor */
-        watchdog_mon_event("reset");
+        qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_RESET, &error_abort);
         qemu_system_reset_request();
         break;
 
     case WDT_SHUTDOWN:          /* same as 'system_powerdown' in monitor */
-        watchdog_mon_event("shutdown");
+        qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_SHUTDOWN, &error_abort);
         qemu_system_powerdown_request();
         break;
 
     case WDT_POWEROFF:          /* same as 'quit' command in monitor */
-        watchdog_mon_event("poweroff");
+        qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_POWEROFF, &error_abort);
         exit(0);
 
     case WDT_PAUSE:             /* same as 'stop' command in monitor */
-        watchdog_mon_event("pause");
+        qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_PAUSE, &error_abort);
         vm_stop(RUN_STATE_WATCHDOG);
         break;
 
     case WDT_DEBUG:
-        watchdog_mon_event("debug");
+        qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_DEBUG, &error_abort);
         fprintf(stderr, "watchdog: timer fired\n");
         break;
 
     case WDT_NONE:
-        watchdog_mon_event("none");
+        qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_NONE, &error_abort);
         break;
     }
 }
diff --git a/include/block/block.h b/include/block/block.h
index f15b99b00b..d0baf4fb83 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -150,10 +150,6 @@ typedef enum {
 #define BDRV_BLOCK_ALLOCATED    0x10
 #define BDRV_BLOCK_OFFSET_MASK  BDRV_SECTOR_MASK
 
-typedef enum {
-    BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
-} BlockErrorAction;
-
 typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
 
 typedef struct BDRVReopenState {
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 7aa2213f77..715c761fad 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -425,9 +425,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
 #ifdef _WIN32
 int is_windows_drive(const char *filename);
 #endif
-void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
-                               enum MonitorEvent ev,
-                               BlockErrorAction action, bool is_read);
 
 /**
  * stream_start:
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index c0a787530b..e443987ea8 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -217,12 +217,21 @@ void block_job_pause(BlockJob *job);
 void block_job_resume(BlockJob *job);
 
 /**
- * qobject_from_block_job:
+ * block_job_event_cancle:
  * @job: The job whose information is requested.
  *
- * Return a QDict corresponding to @job's query-block-jobs entry.
+ * Send a BLOCK_JOB_CANCELLED event for the specified job.
  */
-QObject *qobject_from_block_job(BlockJob *job);
+void block_job_event_cancelled(BlockJob *job);
+
+/**
+ * block_job_ready:
+ * @job: The job which is now ready to complete.
+ * @msg: Error message. Only present on failure.
+ *
+ * Send a BLOCK_JOB_COMPLETED event for the specified job.
+ */
+void block_job_event_completed(BlockJob *job, const char *msg);
 
 /**
  * block_job_ready:
@@ -230,7 +239,7 @@ QObject *qobject_from_block_job(BlockJob *job);
  *
  * Send a BLOCK_JOB_READY event for the specified job.
  */
-void block_job_ready(BlockJob *job);
+void block_job_event_ready(BlockJob *job);
 
 /**
  * block_job_is_paused:
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 3d62d9c464..5e5d86ec46 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -224,7 +224,7 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
     /* no need to flush icache explicitly */
 }
 #elif defined(_ARCH_PPC)
-void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
+void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
 #define tb_set_jmp_target1 ppc_tb_set_jmp_target
 #elif defined(__i386__) || defined(__x86_64__)
 static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 4b3090ca74..77177c5317 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -63,7 +63,6 @@ typedef uint64_t uint64;
 typedef int64_t int64;
 
 #define LIT64( a ) a##LL
-#define INLINE static inline
 
 #define STATUS_PARAM , float_status *status
 #define STATUS(field) status->field
@@ -181,59 +180,59 @@ typedef struct float_status {
     flag default_nan_mode;
 } float_status;
 
-INLINE void set_float_detect_tininess(int val STATUS_PARAM)
+static inline void set_float_detect_tininess(int val STATUS_PARAM)
 {
     STATUS(float_detect_tininess) = val;
 }
-INLINE void set_float_rounding_mode(int val STATUS_PARAM)
+static inline void set_float_rounding_mode(int val STATUS_PARAM)
 {
     STATUS(float_rounding_mode) = val;
 }
-INLINE void set_float_exception_flags(int val STATUS_PARAM)
+static inline void set_float_exception_flags(int val STATUS_PARAM)
 {
     STATUS(float_exception_flags) = val;
 }
-INLINE void set_floatx80_rounding_precision(int val STATUS_PARAM)
+static inline void set_floatx80_rounding_precision(int val STATUS_PARAM)
 {
     STATUS(floatx80_rounding_precision) = val;
 }
-INLINE void set_flush_to_zero(flag val STATUS_PARAM)
+static inline void set_flush_to_zero(flag val STATUS_PARAM)
 {
     STATUS(flush_to_zero) = val;
 }
-INLINE void set_flush_inputs_to_zero(flag val STATUS_PARAM)
+static inline void set_flush_inputs_to_zero(flag val STATUS_PARAM)
 {
     STATUS(flush_inputs_to_zero) = val;
 }
-INLINE void set_default_nan_mode(flag val STATUS_PARAM)
+static inline void set_default_nan_mode(flag val STATUS_PARAM)
 {
     STATUS(default_nan_mode) = val;
 }
-INLINE int get_float_detect_tininess(float_status *status)
+static inline int get_float_detect_tininess(float_status *status)
 {
     return STATUS(float_detect_tininess);
 }
-INLINE int get_float_rounding_mode(float_status *status)
+static inline int get_float_rounding_mode(float_status *status)
 {
     return STATUS(float_rounding_mode);
 }
-INLINE int get_float_exception_flags(float_status *status)
+static inline int get_float_exception_flags(float_status *status)
 {
     return STATUS(float_exception_flags);
 }
-INLINE int get_floatx80_rounding_precision(float_status *status)
+static inline int get_floatx80_rounding_precision(float_status *status)
 {
     return STATUS(floatx80_rounding_precision);
 }
-INLINE flag get_flush_to_zero(float_status *status)
+static inline flag get_flush_to_zero(float_status *status)
 {
     return STATUS(flush_to_zero);
 }
-INLINE flag get_flush_inputs_to_zero(float_status *status)
+static inline flag get_flush_inputs_to_zero(float_status *status)
 {
     return STATUS(flush_inputs_to_zero);
 }
-INLINE flag get_default_nan_mode(float_status *status)
+static inline flag get_default_nan_mode(float_status *status)
 {
     return STATUS(default_nan_mode);
 }
@@ -284,22 +283,22 @@ float128 int64_to_float128(int64_t STATUS_PARAM);
 float128 uint64_to_float128(uint64_t STATUS_PARAM);
 
 /* We provide the int16 versions for symmetry of API with float-to-int */
-INLINE float32 int16_to_float32(int16_t v STATUS_PARAM)
+static inline float32 int16_to_float32(int16_t v STATUS_PARAM)
 {
     return int32_to_float32(v STATUS_VAR);
 }
 
-INLINE float32 uint16_to_float32(uint16_t v STATUS_PARAM)
+static inline float32 uint16_to_float32(uint16_t v STATUS_PARAM)
 {
     return uint32_to_float32(v STATUS_VAR);
 }
 
-INLINE float64 int16_to_float64(int16_t v STATUS_PARAM)
+static inline float64 int16_to_float64(int16_t v STATUS_PARAM)
 {
     return int32_to_float64(v STATUS_VAR);
 }
 
-INLINE float64 uint16_to_float64(uint16_t v STATUS_PARAM)
+static inline float64 uint16_to_float64(uint16_t v STATUS_PARAM)
 {
     return uint32_to_float64(v STATUS_VAR);
 }
@@ -319,7 +318,7 @@ int float16_is_quiet_nan( float16 );
 int float16_is_signaling_nan( float16 );
 float16 float16_maybe_silence_nan( float16 );
 
-INLINE int float16_is_any_nan(float16 a)
+static inline int float16_is_any_nan(float16 a)
 {
     return ((float16_val(a) & ~0x8000) > 0x7c00);
 }
@@ -380,7 +379,7 @@ int float32_is_signaling_nan( float32 );
 float32 float32_maybe_silence_nan( float32 );
 float32 float32_scalbn( float32, int STATUS_PARAM );
 
-INLINE float32 float32_abs(float32 a)
+static inline float32 float32_abs(float32 a)
 {
     /* Note that abs does *not* handle NaN specially, nor does
      * it flush denormal inputs to zero.
@@ -388,7 +387,7 @@ INLINE float32 float32_abs(float32 a)
     return make_float32(float32_val(a) & 0x7fffffff);
 }
 
-INLINE float32 float32_chs(float32 a)
+static inline float32 float32_chs(float32 a)
 {
     /* Note that chs does *not* handle NaN specially, nor does
      * it flush denormal inputs to zero.
@@ -396,32 +395,32 @@ INLINE float32 float32_chs(float32 a)
     return make_float32(float32_val(a) ^ 0x80000000);
 }
 
-INLINE int float32_is_infinity(float32 a)
+static inline int float32_is_infinity(float32 a)
 {
     return (float32_val(a) & 0x7fffffff) == 0x7f800000;
 }
 
-INLINE int float32_is_neg(float32 a)
+static inline int float32_is_neg(float32 a)
 {
     return float32_val(a) >> 31;
 }
 
-INLINE int float32_is_zero(float32 a)
+static inline int float32_is_zero(float32 a)
 {
     return (float32_val(a) & 0x7fffffff) == 0;
 }
 
-INLINE int float32_is_any_nan(float32 a)
+static inline int float32_is_any_nan(float32 a)
 {
     return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL);
 }
 
-INLINE int float32_is_zero_or_denormal(float32 a)
+static inline int float32_is_zero_or_denormal(float32 a)
 {
     return (float32_val(a) & 0x7f800000) == 0;
 }
 
-INLINE float32 float32_set_sign(float32 a, int sign)
+static inline float32 float32_set_sign(float32 a, int sign)
 {
     return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31));
 }
@@ -490,7 +489,7 @@ int float64_is_signaling_nan( float64 );
 float64 float64_maybe_silence_nan( float64 );
 float64 float64_scalbn( float64, int STATUS_PARAM );
 
-INLINE float64 float64_abs(float64 a)
+static inline float64 float64_abs(float64 a)
 {
     /* Note that abs does *not* handle NaN specially, nor does
      * it flush denormal inputs to zero.
@@ -498,7 +497,7 @@ INLINE float64 float64_abs(float64 a)
     return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
 }
 
-INLINE float64 float64_chs(float64 a)
+static inline float64 float64_chs(float64 a)
 {
     /* Note that chs does *not* handle NaN specially, nor does
      * it flush denormal inputs to zero.
@@ -506,32 +505,32 @@ INLINE float64 float64_chs(float64 a)
     return make_float64(float64_val(a) ^ 0x8000000000000000LL);
 }
 
-INLINE int float64_is_infinity(float64 a)
+static inline int float64_is_infinity(float64 a)
 {
     return (float64_val(a) & 0x7fffffffffffffffLL ) == 0x7ff0000000000000LL;
 }
 
-INLINE int float64_is_neg(float64 a)
+static inline int float64_is_neg(float64 a)
 {
     return float64_val(a) >> 63;
 }
 
-INLINE int float64_is_zero(float64 a)
+static inline int float64_is_zero(float64 a)
 {
     return (float64_val(a) & 0x7fffffffffffffffLL) == 0;
 }
 
-INLINE int float64_is_any_nan(float64 a)
+static inline int float64_is_any_nan(float64 a)
 {
     return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL);
 }
 
-INLINE int float64_is_zero_or_denormal(float64 a)
+static inline int float64_is_zero_or_denormal(float64 a)
 {
     return (float64_val(a) & 0x7ff0000000000000LL) == 0;
 }
 
-INLINE float64 float64_set_sign(float64 a, int sign)
+static inline float64 float64_set_sign(float64 a, int sign)
 {
     return make_float64((float64_val(a) & 0x7fffffffffffffffULL)
                         | ((int64_t)sign << 63));
@@ -585,39 +584,39 @@ int floatx80_is_signaling_nan( floatx80 );
 floatx80 floatx80_maybe_silence_nan( floatx80 );
 floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
 
-INLINE floatx80 floatx80_abs(floatx80 a)
+static inline floatx80 floatx80_abs(floatx80 a)
 {
     a.high &= 0x7fff;
     return a;
 }
 
-INLINE floatx80 floatx80_chs(floatx80 a)
+static inline floatx80 floatx80_chs(floatx80 a)
 {
     a.high ^= 0x8000;
     return a;
 }
 
-INLINE int floatx80_is_infinity(floatx80 a)
+static inline int floatx80_is_infinity(floatx80 a)
 {
     return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL;
 }
 
-INLINE int floatx80_is_neg(floatx80 a)
+static inline int floatx80_is_neg(floatx80 a)
 {
     return a.high >> 15;
 }
 
-INLINE int floatx80_is_zero(floatx80 a)
+static inline int floatx80_is_zero(floatx80 a)
 {
     return (a.high & 0x7fff) == 0 && a.low == 0;
 }
 
-INLINE int floatx80_is_zero_or_denormal(floatx80 a)
+static inline int floatx80_is_zero_or_denormal(floatx80 a)
 {
     return (a.high & 0x7fff) == 0;
 }
 
-INLINE int floatx80_is_any_nan(floatx80 a)
+static inline int floatx80_is_any_nan(floatx80 a)
 {
     return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
 }
@@ -670,39 +669,39 @@ int float128_is_signaling_nan( float128 );
 float128 float128_maybe_silence_nan( float128 );
 float128 float128_scalbn( float128, int STATUS_PARAM );
 
-INLINE float128 float128_abs(float128 a)
+static inline float128 float128_abs(float128 a)
 {
     a.high &= 0x7fffffffffffffffLL;
     return a;
 }
 
-INLINE float128 float128_chs(float128 a)
+static inline float128 float128_chs(float128 a)
 {
     a.high ^= 0x8000000000000000LL;
     return a;
 }
 
-INLINE int float128_is_infinity(float128 a)
+static inline int float128_is_infinity(float128 a)
 {
     return (a.high & 0x7fffffffffffffffLL) == 0x7fff000000000000LL && a.low == 0;
 }
 
-INLINE int float128_is_neg(float128 a)
+static inline int float128_is_neg(float128 a)
 {
     return a.high >> 63;
 }
 
-INLINE int float128_is_zero(float128 a)
+static inline int float128_is_zero(float128 a)
 {
     return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
 }
 
-INLINE int float128_is_zero_or_denormal(float128 a)
+static inline int float128_is_zero_or_denormal(float128 a)
 {
     return (a.high & 0x7fff000000000000LL) == 0;
 }
 
-INLINE int float128_is_any_nan(float128 a)
+static inline int float128_is_any_nan(float128 a)
 {
     return ((a.high >> 48) & 0x7fff) == 0x7fff &&
         ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0));
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 19f78ea336..486e98feac 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -33,10 +33,13 @@ struct PCMachineState {
     MemoryRegion hotplug_memory;
 
     HotplugHandler *acpi_dev;
+
+    uint64_t max_ram_below_4g;
 };
 
 #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
 #define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size"
+#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
 
 /**
  * PCMachineClass:
@@ -297,8 +300,16 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
             .driver   = "ICH9-LPC",\
             .property = "memory-hotplug-support",\
             .value    = "off",\
+        },{\
+            .driver   = "xio3130-downstream",\
+            .property = COMPAT_PROP_PCP,\
+            .value    = "off",\
+        },{\
+            .driver   = "ioh3420",\
+            .property = COMPAT_PROP_PCP,\
+            .value    = "off",\
         }
-
+ 
 #define PC_Q35_COMPAT_1_7 \
         PC_COMPAT_1_7, \
         PC_Q35_COMPAT_2_0, \
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 8c25ae5d1d..c352c7b3ad 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -158,6 +158,9 @@ enum {
     QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR),
 #define QEMU_PCI_SLOTID_BITNR 6
     QEMU_PCI_CAP_SLOTID = (1 << QEMU_PCI_SLOTID_BITNR),
+    /* PCI Express capability - Power Controller Present */
+#define QEMU_PCIE_SLTCAP_PCP_BITNR 7
+    QEMU_PCIE_SLTCAP_PCP = (1 << QEMU_PCIE_SLTCAP_PCP_BITNR),
 };
 
 #define TYPE_PCI_DEVICE "pci-device"
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index b0bf7e3ce1..7fe81f31ef 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -76,6 +76,8 @@ struct PCIExpressDevice {
     PCIEAERLog aer_log;
 };
 
+#define COMPAT_PROP_PCP "power_controller_present"
+
 /* PCI express capability helper functions */
 int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port);
 int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset);
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 4d123d9fcc..652d9fc58c 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -57,6 +57,8 @@
 #define PCI_EXP_SLTCTL_PIC_SHIFT        (ffs(PCI_EXP_SLTCTL_PIC) - 1)
 #define PCI_EXP_SLTCTL_PIC_OFF                          \
     (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_PIC_SHIFT)
+#define PCI_EXP_SLTCTL_PIC_ON                          \
+    (PCI_EXP_SLTCTL_IND_ON << PCI_EXP_SLTCTL_PIC_SHIFT)
 
 #define PCI_EXP_SLTCTL_SUPPORTED        \
             (PCI_EXP_SLTCTL_ABPE |      \
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 33028ec8c2..d5593d1620 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -45,6 +45,7 @@ struct vhost_dev {
     bool log_enabled;
     vhost_log_chunk_t *log;
     unsigned long long log_size;
+    Error *migration_blocker;
     bool force;
     bool memory_changed;
     hwaddr mem_changed_start_addr;
diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
index 85fda3dee4..f71f2d8963 100644
--- a/include/hw/xen/xen.h
+++ b/include/hw/xen/xen.h
@@ -37,10 +37,11 @@ void xen_cmos_set_s3_resume(void *opaque, int irq, int level);
 qemu_irq *xen_interrupt_controller_init(void);
 
 int xen_init(MachineClass *mc);
-int xen_hvm_init(MemoryRegion **ram_memory);
 void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
 
 #if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
+int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
+                 MemoryRegion **ram_memory);
 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
                    struct MemoryRegion *mr);
 void xen_modified_memory(ram_addr_t start, ram_addr_t length);
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 97696ea693..3d6929d6cd 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -19,49 +19,8 @@ extern Monitor *default_mon;
 /* flags for monitor commands */
 #define MONITOR_CMD_ASYNC       0x0001
 
-/* QMP events */
-typedef enum MonitorEvent {
-    QEVENT_SHUTDOWN,
-    QEVENT_RESET,
-    QEVENT_POWERDOWN,
-    QEVENT_STOP,
-    QEVENT_RESUME,
-    QEVENT_VNC_CONNECTED,
-    QEVENT_VNC_INITIALIZED,
-    QEVENT_VNC_DISCONNECTED,
-    QEVENT_BLOCK_IO_ERROR,
-    QEVENT_RTC_CHANGE,
-    QEVENT_WATCHDOG,
-    QEVENT_SPICE_CONNECTED,
-    QEVENT_SPICE_INITIALIZED,
-    QEVENT_SPICE_DISCONNECTED,
-    QEVENT_BLOCK_JOB_COMPLETED,
-    QEVENT_BLOCK_JOB_CANCELLED,
-    QEVENT_BLOCK_JOB_ERROR,
-    QEVENT_BLOCK_JOB_READY,
-    QEVENT_DEVICE_DELETED,
-    QEVENT_DEVICE_TRAY_MOVED,
-    QEVENT_NIC_RX_FILTER_CHANGED,
-    QEVENT_SUSPEND,
-    QEVENT_SUSPEND_DISK,
-    QEVENT_WAKEUP,
-    QEVENT_BALLOON_CHANGE,
-    QEVENT_SPICE_MIGRATE_COMPLETED,
-    QEVENT_GUEST_PANICKED,
-    QEVENT_BLOCK_IMAGE_CORRUPTED,
-    QEVENT_QUORUM_FAILURE,
-    QEVENT_QUORUM_REPORT_BAD,
-    QEVENT_ACPI_OST,
-
-    /* Add to 'monitor_event_names' array in monitor.c when
-     * defining new events here */
-
-    QEVENT_MAX,
-} MonitorEvent;
-
 int monitor_cur_is_qmp(void);
 
-void monitor_protocol_event(MonitorEvent event, QObject *data);
 void monitor_init(CharDriverState *chr, int flags);
 
 int monitor_suspend(Monitor *mon);
diff --git a/include/qapi/qmp-event.h b/include/qapi/qmp-event.h
new file mode 100644
index 0000000000..8a8ffb5718
--- /dev/null
+++ b/include/qapi/qmp-event.h
@@ -0,0 +1,27 @@
+/*
+ * QMP Event related
+ *
+ * Copyright (c) 2014 Wenchao Xia
+ *
+ * Authors:
+ *  Wenchao Xia   <wenchaoqemu@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_EVENT_H
+#define QMP_EVENT_H
+
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+
+typedef void (*QMPEventFuncEmit)(unsigned event, QDict *dict, Error **errp);
+
+void qmp_event_set_func_emit(QMPEventFuncEmit emit);
+
+QMPEventFuncEmit qmp_event_get_func_emit(void);
+
+QDict *qmp_event_build_dict(const char *event_name);
+#endif
diff --git a/include/qemu/cache-utils.h b/include/qemu/cache-utils.h
deleted file mode 100644
index 211245bea0..0000000000
--- a/include/qemu/cache-utils.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef QEMU_CACHE_UTILS_H
-#define QEMU_CACHE_UTILS_H
-
-#if defined(_ARCH_PPC)
-
-#include <stdint.h> /* uintptr_t */
-
-struct qemu_cache_conf {
-    unsigned long dcache_bsize;
-    unsigned long icache_bsize;
-};
-
-extern struct qemu_cache_conf qemu_cache_conf;
-
-void qemu_cache_utils_init(void);
-
-/* mildly adjusted code from tcg-dyngen.c */
-static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
-{
-    unsigned long p, start1, stop1;
-    unsigned long dsize = qemu_cache_conf.dcache_bsize;
-    unsigned long isize = qemu_cache_conf.icache_bsize;
-
-    start1 = start & ~(dsize - 1);
-    stop1 = (stop + dsize - 1) & ~(dsize - 1);
-    for (p = start1; p < stop1; p += dsize) {
-        asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
-    }
-    asm volatile ("sync" : : : "memory");
-
-    start &= start & ~(isize - 1);
-    stop1 = (stop + isize - 1) & ~(isize - 1);
-    for (p = start1; p < stop1; p += isize) {
-        asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
-    }
-    asm volatile ("sync" : : : "memory");
-    asm volatile ("isync" : : : "memory");
-}
-
-#else
-#define qemu_cache_utils_init() do { } while (0)
-#endif
-
-#endif /* QEMU_CACHE_UTILS_H */
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 6d35c1bcba..8480d523f0 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -251,18 +251,6 @@ unsigned long qemu_getauxval(unsigned long type);
 static inline unsigned long qemu_getauxval(unsigned long type) { return 0; }
 #endif
 
-/**
- * qemu_init_auxval:
- * @envp: the third argument to main
- *
- * If supported and required, locate the auxiliary vector at program startup.
- */
-#if defined(CONFIG_GETAUXVAL) || !defined(__linux__)
-static inline void qemu_init_auxval(char **envp) { }
-#else
-void qemu_init_auxval(char **envp);
-#endif
-
 void qemu_set_tty_echo(int fd, bool echo);
 
 void os_mem_prealloc(int fd, char *area, size_t sz);
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 45588d7d58..fdbb196787 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -29,6 +29,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #include "qemu/option.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
+#include "qapi-types.h"
 
 extern QemuOptsList socket_optslist;
 
@@ -60,7 +61,7 @@ int inet_nonblocking_connect(const char *str,
                              void *opaque, Error **errp);
 
 int inet_dgram_opts(QemuOpts *opts, Error **errp);
-const char *inet_strfamily(int family);
+NetworkAddressFamily inet_netfamily(int family);
 
 int unix_listen_opts(QemuOpts *opts, Error **errp);
 int unix_listen(const char *path, char *ostr, int olen, Error **errp);
diff --git a/include/sysemu/balloon.h b/include/sysemu/balloon.h
index bd9d39505d..0345e01efb 100644
--- a/include/sysemu/balloon.h
+++ b/include/sysemu/balloon.h
@@ -24,6 +24,4 @@ int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
 			     QEMUBalloonStatus *stat_func, void *opaque);
 void qemu_remove_balloon_handler(void *opaque);
 
-void qemu_balloon_changed(int64_t actual);
-
 #endif
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 672ed39a31..c8b15f9729 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -54,6 +54,7 @@ typedef struct {
 typedef void IOEventHandler(void *opaque, int event);
 
 struct CharDriverState {
+    QemuMutex chr_write_lock;
     void (*init)(struct CharDriverState *s);
     int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
     int (*chr_sync_read)(struct CharDriverState *s,
@@ -89,6 +90,15 @@ struct CharDriverState {
 };
 
 /**
+ * @qemu_chr_alloc:
+ *
+ * Allocate and initialize a new CharDriverState.
+ *
+ * Returns: a newly allocated CharDriverState.
+ */
+CharDriverState *qemu_chr_alloc(void);
+
+/**
  * @qemu_chr_new_from_opts:
  *
  * Create a new character backend from a QemuOpts list.
@@ -155,6 +165,7 @@ void qemu_chr_fe_event(CharDriverState *s, int event);
  * @qemu_chr_fe_printf:
  *
  * Write to a character backend using a printf style interface.
+ * This function is thread-safe.
  *
  * @fmt see #printf
  */
@@ -167,8 +178,9 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
 /**
  * @qemu_chr_fe_write:
  *
- * Write data to a character backend from the front end.  This function will
- * send data from the front end to the back end.
+ * Write data to a character backend from the front end.  This function
+ * will send data from the front end to the back end.  This function
+ * is thread-safe.
  *
  * @buf the data
  * @len the number of bytes to send
@@ -183,7 +195,7 @@ int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len);
  * Write data to a character backend from the front end.  This function will
  * send data from the front end to the back end.  Unlike @qemu_chr_fe_write,
  * this function will block if the back end cannot consume all of the data
- * attempted to be written.
+ * attempted to be written.  This function is thread-safe.
  *
  * @buf the data
  * @len the number of bytes to send
@@ -207,7 +219,7 @@ int qemu_chr_fe_read_all(CharDriverState *s, uint8_t *buf, int len);
 /**
  * @qemu_chr_fe_ioctl:
  *
- * Issue a device specific ioctl to a backend.
+ * Issue a device specific ioctl to a backend.  This function is thread-safe.
  *
  * @cmd see CHR_IOCTL_*
  * @arg the data associated with @cmd
diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 25d0b2a73f..f1315213f1 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -26,6 +26,8 @@
 #ifndef QEMU_OS_POSIX_H
 #define QEMU_OS_POSIX_H
 
+#include <sys/time.h>
+
 void os_set_line_buffering(void);
 void os_set_proc_name(const char *s);
 void os_setup_signal_handling(void);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 6b4cc133c5..285c45baf2 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -202,8 +202,6 @@ void do_usb_add(Monitor *mon, const QDict *qdict);
 void do_usb_del(Monitor *mon, const QDict *qdict);
 void usb_info(Monitor *mon, const QDict *qdict);
 
-void rtc_change_mon_event(struct tm *tm);
-
 void add_boot_device_path(int32_t bootindex, DeviceState *dev,
                           const char *suffix);
 char *get_boot_devices_list(size_t *size, bool ignore_suffixes);
diff --git a/linux-user/main.c b/linux-user/main.c
index a87c6f7ed4..df1bb0e758 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -28,7 +28,6 @@
 
 #include "qemu.h"
 #include "qemu-common.h"
-#include "qemu/cache-utils.h"
 #include "cpu.h"
 #include "tcg.h"
 #include "qemu/timer.h"
@@ -3829,9 +3828,6 @@ int main(int argc, char **argv, char **envp)
 
     module_call_init(MODULE_INIT_QOM);
 
-    qemu_init_auxval(envp);
-    qemu_cache_utils_init();
-
     if ((envlist = envlist_create()) == NULL) {
         (void) fprintf(stderr, "Unable to allocate envlist\n");
         exit(1);
diff --git a/monitor.c b/monitor.c
index c7f879713e..a8ab600c88 100644
--- a/monitor.c
+++ b/monitor.c
@@ -71,6 +71,8 @@
 #include "hmp.h"
 #include "qemu/thread.h"
 #include "block/qapi.h"
+#include "qapi/qmp-event.h"
+#include "qapi-event.h"
 
 /* for pic/irq_info */
 #if defined(TARGET_SPARC)
@@ -179,23 +181,28 @@ typedef struct MonitorControl {
  * throttling is calculated globally, rather than per-Monitor
  * instance.
  */
-typedef struct MonitorEventState {
-    MonitorEvent event; /* Event being tracked */
-    int64_t rate;       /* Period over which to throttle. 0 to disable */
-    int64_t last;       /* Time at which event was last emitted */
+typedef struct MonitorQAPIEventState {
+    QAPIEvent event;    /* Event being tracked */
+    int64_t rate;       /* Minimum time (in ns) between two events */
+    int64_t last;       /* QEMU_CLOCK_REALTIME value at last emission */
     QEMUTimer *timer;   /* Timer for handling delayed events */
     QObject *data;      /* Event pending delayed dispatch */
-} MonitorEventState;
+} MonitorQAPIEventState;
 
 struct Monitor {
     CharDriverState *chr;
-    int mux_out;
     int reset_seen;
     int flags;
     int suspend_cnt;
     bool skip_flush;
+
+    QemuMutex out_lock;
     QString *outbuf;
-    guint watch;
+    guint out_watch;
+
+    /* Read under either BQL or out_lock, written with BQL+out_lock.  */
+    int mux_out;
+
     ReadLineState *rs;
     MonitorControl *mc;
     CPUState *mon_cpu;
@@ -210,6 +217,9 @@ struct Monitor {
 /* QMP checker flags */
 #define QMP_ACCEPT_UNKNOWNS 1
 
+/* Protects mon_list, monitor_event_state.  */
+static QemuMutex monitor_lock;
+
 static QLIST_HEAD(mon_list, Monitor) mon_list;
 static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
 static int mon_refcount;
@@ -268,17 +278,22 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
     }
 }
 
+static void monitor_flush_locked(Monitor *mon);
+
 static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
                                   void *opaque)
 {
     Monitor *mon = opaque;
 
-    mon->watch = 0;
-    monitor_flush(mon);
+    qemu_mutex_lock(&mon->out_lock);
+    mon->out_watch = 0;
+    monitor_flush_locked(mon);
+    qemu_mutex_unlock(&mon->out_lock);
     return FALSE;
 }
 
-void monitor_flush(Monitor *mon)
+/* Called with mon->out_lock held.  */
+static void monitor_flush_locked(Monitor *mon)
 {
     int rc;
     size_t len;
@@ -305,18 +320,26 @@ void monitor_flush(Monitor *mon)
             QDECREF(mon->outbuf);
             mon->outbuf = tmp;
         }
-        if (mon->watch == 0) {
-            mon->watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT,
-                                               monitor_unblocked, mon);
+        if (mon->out_watch == 0) {
+            mon->out_watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT,
+                                                   monitor_unblocked, mon);
         }
     }
 }
 
+void monitor_flush(Monitor *mon)
+{
+    qemu_mutex_lock(&mon->out_lock);
+    monitor_flush_locked(mon);
+    qemu_mutex_unlock(&mon->out_lock);
+}
+
 /* flush at every end of line */
 static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
 
+    qemu_mutex_lock(&mon->out_lock);
     for(;;) {
         c = *str++;
         if (c == '\0')
@@ -326,9 +349,10 @@ static void monitor_puts(Monitor *mon, const char *str)
         }
         qstring_append_chr(mon->outbuf, c);
         if (c == '\n') {
-            monitor_flush(mon);
+            monitor_flush_locked(mon);
         }
     }
+    qemu_mutex_unlock(&mon->out_lock);
 }
 
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
@@ -439,66 +463,14 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
     QDECREF(qmp);
 }
 
-static void timestamp_put(QDict *qdict)
-{
-    int err;
-    QObject *obj;
-    qemu_timeval tv;
 
-    err = qemu_gettimeofday(&tv);
-    if (err < 0)
-        return;
-
-    obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
-                                "'microseconds': %" PRId64 " }",
-                                (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
-    qdict_put_obj(qdict, "timestamp", obj);
-}
-
-
-static const char *monitor_event_names[] = {
-    [QEVENT_SHUTDOWN] = "SHUTDOWN",
-    [QEVENT_RESET] = "RESET",
-    [QEVENT_POWERDOWN] = "POWERDOWN",
-    [QEVENT_STOP] = "STOP",
-    [QEVENT_RESUME] = "RESUME",
-    [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED",
-    [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED",
-    [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED",
-    [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR",
-    [QEVENT_RTC_CHANGE] = "RTC_CHANGE",
-    [QEVENT_WATCHDOG] = "WATCHDOG",
-    [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED",
-    [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED",
-    [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED",
-    [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
-    [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
-    [QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR",
-    [QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY",
-    [QEVENT_DEVICE_DELETED] = "DEVICE_DELETED",
-    [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
-    [QEVENT_NIC_RX_FILTER_CHANGED] = "NIC_RX_FILTER_CHANGED",
-    [QEVENT_SUSPEND] = "SUSPEND",
-    [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
-    [QEVENT_WAKEUP] = "WAKEUP",
-    [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
-    [QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED",
-    [QEVENT_GUEST_PANICKED] = "GUEST_PANICKED",
-    [QEVENT_BLOCK_IMAGE_CORRUPTED] = "BLOCK_IMAGE_CORRUPTED",
-    [QEVENT_QUORUM_FAILURE] = "QUORUM_FAILURE",
-    [QEVENT_QUORUM_REPORT_BAD] = "QUORUM_REPORT_BAD",
-    [QEVENT_ACPI_OST] = "ACPI_DEVICE_OST",
-};
-QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
-
-static MonitorEventState monitor_event_state[QEVENT_MAX];
+static MonitorQAPIEventState monitor_qapi_event_state[QAPI_EVENT_MAX];
 
 /*
- * Emits the event to every monitor instance
+ * Emits the event to every monitor instance, @event is only used for trace
+ * Called with monitor_lock held.
  */
-static void
-monitor_protocol_event_emit(MonitorEvent event,
-                            QObject *data)
+static void monitor_qapi_event_emit(QAPIEvent event, QObject *data)
 {
     Monitor *mon;
 
@@ -510,20 +482,18 @@ monitor_protocol_event_emit(MonitorEvent event,
     }
 }
 
-
 /*
  * Queue a new event for emission to Monitor instances,
  * applying any rate limiting if required.
  */
 static void
-monitor_protocol_event_queue(MonitorEvent event,
-                             QObject *data)
+monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp)
 {
-    MonitorEventState *evstate;
+    MonitorQAPIEventState *evstate;
+    assert(event < QAPI_EVENT_MAX);
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-    assert(event < QEVENT_MAX);
 
-    evstate = &(monitor_event_state[event]);
+    evstate = &(monitor_qapi_event_state[event]);
     trace_monitor_protocol_event_queue(event,
                                        data,
                                        evstate->rate,
@@ -531,8 +501,9 @@ monitor_protocol_event_queue(MonitorEvent event,
                                        now);
 
     /* Rate limit of 0 indicates no throttling */
+    qemu_mutex_lock(&monitor_lock);
     if (!evstate->rate) {
-        monitor_protocol_event_emit(event, data);
+        monitor_qapi_event_emit(event, QOBJECT(data));
         evstate->last = now;
     } else {
         int64_t delta = now - evstate->last;
@@ -548,39 +519,39 @@ monitor_protocol_event_queue(MonitorEvent event,
                 int64_t then = evstate->last + evstate->rate;
                 timer_mod_ns(evstate->timer, then);
             }
-            evstate->data = data;
+            evstate->data = QOBJECT(data);
             qobject_incref(evstate->data);
         } else {
-            monitor_protocol_event_emit(event, data);
+            monitor_qapi_event_emit(event, QOBJECT(data));
             evstate->last = now;
         }
     }
+    qemu_mutex_unlock(&monitor_lock);
 }
 
-
 /*
  * The callback invoked by QemuTimer when a delayed
  * event is ready to be emitted
  */
-static void monitor_protocol_event_handler(void *opaque)
+static void monitor_qapi_event_handler(void *opaque)
 {
-    MonitorEventState *evstate = opaque;
+    MonitorQAPIEventState *evstate = opaque;
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
 
-
     trace_monitor_protocol_event_handler(evstate->event,
                                          evstate->data,
                                          evstate->last,
                                          now);
+    qemu_mutex_lock(&monitor_lock);
     if (evstate->data) {
-        monitor_protocol_event_emit(evstate->event, evstate->data);
+        monitor_qapi_event_emit(evstate->event, evstate->data);
         qobject_decref(evstate->data);
         evstate->data = NULL;
     }
     evstate->last = now;
+    qemu_mutex_unlock(&monitor_lock);
 }
 
-
 /*
  * @event: the event ID to be limited
  * @rate: the rate limit in milliseconds
@@ -590,65 +561,35 @@ static void monitor_protocol_event_handler(void *opaque)
  * milliseconds
  */
 static void
-monitor_protocol_event_throttle(MonitorEvent event,
-                                int64_t rate)
+monitor_qapi_event_throttle(QAPIEvent event, int64_t rate)
 {
-    MonitorEventState *evstate;
-    assert(event < QEVENT_MAX);
+    MonitorQAPIEventState *evstate;
+    assert(event < QAPI_EVENT_MAX);
 
-    evstate = &(monitor_event_state[event]);
+    evstate = &(monitor_qapi_event_state[event]);
 
     trace_monitor_protocol_event_throttle(event, rate);
     evstate->event = event;
     evstate->rate = rate * SCALE_MS;
-    evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
-                                    SCALE_MS,
-                                    monitor_protocol_event_handler,
-                                    evstate);
     evstate->last = 0;
     evstate->data = NULL;
+    evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
+                               SCALE_MS,
+                               monitor_qapi_event_handler,
+                               evstate);
 }
 
-
-/* Global, one-time initializer to configure the rate limiting
- * and initialize state */
-static void monitor_protocol_event_init(void)
+static void monitor_qapi_event_init(void)
 {
-    /* Limit RTC & BALLOON events to 1 per second */
-    monitor_protocol_event_throttle(QEVENT_RTC_CHANGE, 1000);
-    monitor_protocol_event_throttle(QEVENT_BALLOON_CHANGE, 1000);
-    monitor_protocol_event_throttle(QEVENT_WATCHDOG, 1000);
+    /* Limit guest-triggerable events to 1 per second */
+    monitor_qapi_event_throttle(QAPI_EVENT_RTC_CHANGE, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_WATCHDOG, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_BALLOON_CHANGE, 1000);
     /* limit the rate of quorum events to avoid hammering the management */
-    monitor_protocol_event_throttle(QEVENT_QUORUM_REPORT_BAD, 1000);
-    monitor_protocol_event_throttle(QEVENT_QUORUM_FAILURE, 1000);
-}
-
-/**
- * monitor_protocol_event(): Generate a Monitor event
- *
- * Event-specific data can be emitted through the (optional) 'data' parameter.
- */
-void monitor_protocol_event(MonitorEvent event, QObject *data)
-{
-    QDict *qmp;
-    const char *event_name;
-
-    assert(event < QEVENT_MAX);
-
-    event_name = monitor_event_names[event];
-    assert(event_name != NULL);
-
-    qmp = qdict_new();
-    timestamp_put(qmp);
-    qdict_put(qmp, "event", qstring_from_str(event_name));
-    if (data) {
-        qobject_incref(data);
-        qdict_put_obj(qmp, "data", data);
-    }
+    monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_REPORT_BAD, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_FAILURE, 1000);
 
-    trace_monitor_protocol_event(event, event_name, qmp);
-    monitor_protocol_event_queue(event, QOBJECT(qmp));
-    QDECREF(qmp);
+    qmp_event_set_func_emit(monitor_qapi_event_queue);
 }
 
 static int do_qmp_capabilities(Monitor *mon, const QDict *params,
@@ -667,6 +608,7 @@ static void handle_user_command(Monitor *mon, const char *cmdline);
 static void monitor_data_init(Monitor *mon)
 {
     memset(mon, 0, sizeof(Monitor));
+    qemu_mutex_init(&mon->out_lock);
     mon->outbuf = qstring_new();
     /* Use *mon_cmds by default. */
     mon->cmd_table = mon_cmds;
@@ -675,6 +617,7 @@ static void monitor_data_init(Monitor *mon)
 static void monitor_data_destroy(Monitor *mon)
 {
     QDECREF(mon->outbuf);
+    qemu_mutex_destroy(&mon->out_lock);
 }
 
 char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
@@ -702,11 +645,13 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     handle_user_command(&hmp, command_line);
     cur_mon = old_mon;
 
+    qemu_mutex_lock(&hmp.out_lock);
     if (qstring_get_length(hmp.outbuf) > 0) {
         output = g_strdup(qstring_get_str(hmp.outbuf));
     } else {
         output = g_strdup("");
     }
+    qemu_mutex_unlock(&hmp.out_lock);
 
 out:
     monitor_data_destroy(&hmp);
@@ -1045,10 +990,10 @@ CommandInfoList *qmp_query_commands(Error **errp)
 EventInfoList *qmp_query_events(Error **errp)
 {
     EventInfoList *info, *ev_list = NULL;
-    MonitorEvent e;
+    QAPIEvent e;
 
-    for (e = 0 ; e < QEVENT_MAX ; e++) {
-        const char *event_name = monitor_event_names[e];
+    for (e = 0 ; e < QAPI_EVENT_MAX ; e++) {
+        const char *event_name = QAPIEvent_lookup[e];
         assert(event_name != NULL);
         info = g_malloc0(sizeof(*info));
         info->value = g_malloc0(sizeof(*info->value));
@@ -2968,7 +2913,7 @@ static mon_cmd_t info_cmds[] = {
         .name       = "memdev",
         .args_type  = "",
         .params     = "",
-        .help       = "show the memory device",
+        .help       = "show memory backends",
         .mhandler.cmd = hmp_info_memdev,
     },
     {
@@ -5266,7 +5211,9 @@ static void monitor_event(void *opaque, int event)
 
     switch (event) {
     case CHR_EVENT_MUX_IN:
+        qemu_mutex_lock(&mon->out_lock);
         mon->mux_out = 0;
+        qemu_mutex_unlock(&mon->out_lock);
         if (mon->reset_seen) {
             readline_restart(mon->rs);
             monitor_resume(mon);
@@ -5286,7 +5233,9 @@ static void monitor_event(void *opaque, int event)
         } else {
             mon->suspend_cnt++;
         }
+        qemu_mutex_lock(&mon->out_lock);
         mon->mux_out = 1;
+        qemu_mutex_unlock(&mon->out_lock);
         break;
 
     case CHR_EVENT_OPENED:
@@ -5351,13 +5300,18 @@ static void monitor_readline_flush(void *opaque)
     monitor_flush(opaque);
 }
 
+static void __attribute__((constructor)) monitor_lock_init(void)
+{
+    qemu_mutex_init(&monitor_lock);
+}
+
 void monitor_init(CharDriverState *chr, int flags)
 {
     static int is_first_init = 1;
     Monitor *mon;
 
     if (is_first_init) {
-        monitor_protocol_event_init();
+        monitor_qapi_event_init();
         sortcmdlist();
         is_first_init = 0;
     }
@@ -5388,7 +5342,10 @@ void monitor_init(CharDriverState *chr, int flags)
                               monitor_event, mon);
     }
 
+    qemu_mutex_lock(&monitor_lock);
     QLIST_INSERT_HEAD(&mon_list, mon, entry);
+    qemu_mutex_unlock(&monitor_lock);
+
     if (!default_mon || (flags & MONITOR_IS_DEFAULT))
         default_mon = mon;
 }
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index f6223e77c2..1c7f7640fc 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differdiff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 53a460df84..5ee3fcb38f 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -58,6 +58,52 @@ struct mbr {
 /* Scratch space */
 static uint8_t sec[SECTOR_SIZE] __attribute__((__aligned__(SECTOR_SIZE)));
 
+typedef struct ResetInfo {
+    uint32_t ipl_mask;
+    uint32_t ipl_addr;
+    uint32_t ipl_continue;
+} ResetInfo;
+
+ResetInfo save;
+
+static void jump_to_IPL_2(void)
+{
+    ResetInfo *current = 0;
+
+    void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
+    debug_print_addr("set IPL addr to", ipl);
+
+    /* Ensure the guest output starts fresh */
+    sclp_print("\n");
+
+    *current = save;
+    ipl(); /* should not return */
+}
+
+static void jump_to_IPL_code(uint64_t address)
+{
+    /*
+     * The IPL PSW is at address 0. We also must not overwrite the
+     * content of non-BIOS memory after we loaded the guest, so we
+     * save the original content and restore it in jump_to_IPL_2.
+     */
+    ResetInfo *current = 0;
+
+    save = *current;
+    current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
+    current->ipl_continue = address & 0x7fffffff;
+
+    /*
+     * HACK ALERT.
+     * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
+     * can then use r15 as its stack pointer.
+     */
+    asm volatile("lghi 1,1\n\t"
+                 "diag 1,1,0x308\n\t"
+                 : : : "1", "memory");
+    virtio_panic("\n! IPL returns !\n");
+}
+
 /* Check for ZIPL magic. Returns 0 if not matched. */
 static int zipl_magic(uint8_t *ptr)
 {
@@ -72,10 +118,26 @@ static int zipl_magic(uint8_t *ptr)
     return 1;
 }
 
+#define FREE_SPACE_FILLER '\xAA'
+
+static inline bool unused_space(const void *p, unsigned int size)
+{
+    int i;
+    const unsigned char *m = p;
+
+    for (i = 0; i < size; i++) {
+        if (m[i] != FREE_SPACE_FILLER) {
+            return false;
+        }
+    }
+    return true;
+}
+
 static int zipl_load_segment(struct component_entry *entry)
 {
     const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr));
     struct scsi_blockptr *bprs = (void*)sec;
+    const int bprs_size = sizeof(sec);
     uint64_t blockno;
     long address;
     int i;
@@ -87,6 +149,7 @@ static int zipl_load_segment(struct component_entry *entry)
     debug_print_int("addr", address);
 
     do {
+        memset(bprs, FREE_SPACE_FILLER, bprs_size);
         if (virtio_read(blockno, (uint8_t *)bprs)) {
             debug_print_int("failed reading bprs at", blockno);
             goto fail;
@@ -104,6 +167,16 @@ static int zipl_load_segment(struct component_entry *entry)
             if (i == (max_entries - 1))
                 break;
 
+            if (bprs[i].blockct == 0 && unused_space(&bprs[i + 1],
+                sizeof(struct scsi_blockptr))) {
+                /* This is a "continue" pointer.
+                 * This ptr is the last one in the current script section.
+                 * I.e. the next ptr must point to the unused memory area.
+                 * The blockno is not zero, so the upper loop must continue
+                 * reading next section of BPRS.
+                 */
+                break;
+            }
             address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
                                          (void*)address);
             if (address == -1)
@@ -123,7 +196,6 @@ static int zipl_run(struct scsi_blockptr *pte)
 {
     struct component_header *header;
     struct component_entry *entry;
-    void (*ipl)(void);
     uint8_t tmp_sec[SECTOR_SIZE];
 
     virtio_read(pte->blockno, tmp_sec);
@@ -157,14 +229,8 @@ static int zipl_run(struct scsi_blockptr *pte)
         goto fail;
     }
 
-    /* Ensure the guest output starts fresh */
-    sclp_print("\n");
-
-    /* And run the OS! */
-    ipl = (void*)(entry->load_address & 0x7fffffff);
-    debug_print_addr("set IPL addr to", ipl);
     /* should not return */
-    ipl();
+    jump_to_IPL_code(entry->load_address);
 
     return 0;
 
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index a46914dd68..bbb3c4f36d 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -240,7 +240,7 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
 {
     u8 status;
     int sec = rec_list1;
-    int sec_num = (((rec_list2 >> 32)+ 1) & 0xffff);
+    int sec_num = ((rec_list2 >> 32) & 0xffff) + 1;
     int sec_len = rec_list2 >> 48;
     ulong addr = (ulong)load_addr;
 
diff --git a/qapi-event.json b/qapi-event.json
new file mode 100644
index 0000000000..e7a47f9927
--- /dev/null
+++ b/qapi-event.json
@@ -0,0 +1,318 @@
+##
+# @SHUTDOWN
+#
+# Emitted when the virtual machine has shutdown, possibly indicating that QEMU
+# is about about to exit.
+#
+# Note: If the command-line option "-no-shutdown" has been specified, qemu will
+# not exit, and a STOP event will eventually follow the SHUTDOWN event
+#
+# Since: 0.12.0
+##
+{ 'event': 'SHUTDOWN' }
+
+##
+# @POWERDOWN
+#
+# Emitted when the virtual machine is powered down through the power control
+# system, such as via ACPI.
+#
+# Since: 0.12.0
+##
+{ 'event': 'POWERDOWN' }
+
+##
+# @RESET
+#
+# Emitted when the virtual machine is reset
+#
+# Since: 0.12.0
+##
+{ 'event': 'RESET' }
+
+##
+# @STOP
+#
+# Emitted when the virtual machine is stopped
+#
+# Since: 0.12.0
+##
+{ 'event': 'STOP' }
+
+##
+# @RESUME
+#
+# Emitted when the virtual machine resumes execution
+#
+# Since: 0.12.0
+##
+{ 'event': 'RESUME' }
+
+##
+# @SUSPEND
+#
+# Emitted when guest enters a hardware suspension state, for example, S3 state,
+# which is sometimes called standby state
+#
+# Since: 1.1
+##
+{ 'event': 'SUSPEND' }
+
+##
+# @SUSPEND_DISK
+#
+# Emitted when guest enters a hardware suspension state with data saved on
+# disk, for example, S4 state, which is sometimes called hibernate state
+#
+# Note: QEMU shuts down (similar to event @SHUTDOWN) when entering this state
+#
+# Since: 1.2
+##
+{ 'event': 'SUSPEND_DISK' }
+
+##
+# @WAKEUP
+#
+# Emitted when the guest has woken up from suspend state and is running
+#
+# Since: 1.1
+##
+{ 'event': 'WAKEUP' }
+
+##
+# @RTC_CHANGE
+#
+# Emitted when the guest changes the RTC time.
+#
+# @offset: offset between base RTC clock (as specified by -rtc base), and
+#          new RTC clock value
+#
+# Since: 0.13.0
+##
+{ 'event': 'RTC_CHANGE',
+  'data': { 'offset': 'int' } }
+
+##
+# @WATCHDOG
+#
+# Emitted when the watchdog device's timer is expired
+#
+# @action: action that has been taken
+#
+# Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
+# followed respectively by the RESET, SHUTDOWN, or STOP events
+#
+# Since: 0.13.0
+##
+{ 'event': 'WATCHDOG',
+  'data': { 'action': 'WatchdogExpirationAction' } }
+
+##
+# @DEVICE_DELETED
+#
+# Emitted whenever the device removal completion is acknowledged by the guest.
+# At this point, it's safe to reuse the specified device ID. Device removal can
+# be initiated by the guest or by HMP/QMP commands.
+#
+# @device: #optional, device name
+#
+# @path: device path
+#
+# Since: 1.5
+##
+{ 'event': 'DEVICE_DELETED',
+  'data': { '*device': 'str', 'path': 'str' } }
+
+##
+# @NIC_RX_FILTER_CHANGED
+#
+# Emitted once until the 'query-rx-filter' command is executed, the first event
+# will always be emitted
+#
+# @name: #optional, net client name
+#
+# @path: device path
+#
+# Since: 1.6
+##
+{ 'event': 'NIC_RX_FILTER_CHANGED',
+  'data': { '*name': 'str', 'path': 'str' } }
+
+##
+# @VNC_CONNECTED
+#
+# Emitted when a VNC client establishes a connection
+#
+# @server: server information
+#
+# @client: client information
+#
+# Note: This event is emitted before any authentication takes place, thus
+# the authentication ID is not provided
+#
+# Since: 0.13.0
+##
+{ 'event': 'VNC_CONNECTED',
+  'data': { 'server': 'VncServerInfo',
+            'client': 'VncBasicInfo' } }
+
+##
+# @VNC_INITIALIZED
+#
+# Emitted after authentication takes place (if any) and the VNC session is
+# made active
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.13.0
+##
+{ 'event': 'VNC_INITIALIZED',
+  'data': { 'server': 'VncServerInfo',
+            'client': 'VncClientInfo' } }
+
+##
+# @VNC_DISCONNECTED
+#
+# Emitted when the connection is closed
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.13.0
+##
+{ 'event': 'VNC_DISCONNECTED',
+  'data': { 'server': 'VncServerInfo',
+            'client': 'VncClientInfo' } }
+
+##
+# @SPICE_CONNECTED
+#
+# Emitted when a SPICE client establishes a connection
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.14.0
+##
+{ 'event': 'SPICE_CONNECTED',
+  'data': { 'server': 'SpiceBasicInfo',
+            'client': 'SpiceBasicInfo' } }
+
+##
+# @SPICE_INITIALIZED
+#
+# Emitted after initial handshake and authentication takes place (if any)
+# and the SPICE channel is up and running
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.14.0
+##
+{ 'event': 'SPICE_INITIALIZED',
+  'data': { 'server': 'SpiceServerInfo',
+            'client': 'SpiceChannel' } }
+
+##
+# @SPICE_DISCONNECTED
+#
+# Emitted when the SPICE connection is closed
+#
+# @server: server information
+#
+# @client: client information
+#
+# Since: 0.14.0
+##
+{ 'event': 'SPICE_DISCONNECTED',
+  'data': { 'server': 'SpiceBasicInfo',
+            'client': 'SpiceBasicInfo' } }
+
+##
+# @SPICE_MIGRATE_COMPLETED
+#
+# Emitted when SPICE migration has completed
+#
+# Since: 1.3
+##
+{ 'event': 'SPICE_MIGRATE_COMPLETED' }
+
+##
+# @ACPI_DEVICE_OST
+#
+# Emitted when guest executes ACPI _OST method.
+#
+# Since: 2.1
+#
+# @info: ACPIOSTInfo type as described in qapi-schema.json
+##
+{ 'event': 'ACPI_DEVICE_OST',
+     'data': { 'info': 'ACPIOSTInfo' } }
+
+##
+# @BALLOON_CHANGE
+#
+# Emitted when the guest changes the actual BALLOON level. This value is
+# equivalent to the @actual field return by the 'query-balloon' command
+#
+# @actual: actual level of the guest memory balloon in bytes
+#
+# Since: 1.2
+##
+{ 'event': 'BALLOON_CHANGE',
+  'data': { 'actual': 'int' } }
+
+##
+# @GUEST_PANICKED
+#
+# Emitted when guest OS panic is detected
+#
+# @action: action that has been taken, currently always "pause"
+#
+# Since: 1.5
+##
+{ 'event': 'GUEST_PANICKED',
+  'data': { 'action': 'GuestPanicAction' } }
+
+##
+# @QUORUM_FAILURE
+#
+# Emitted by the Quorum block driver if it fails to establish a quorum
+#
+# @reference: device name if defined else node name
+#
+# @sector-num: number of the first sector of the failed read operation
+#
+# @sector-count: failed read operation sector count
+#
+# Since: 2.0
+##
+{ 'event': 'QUORUM_FAILURE',
+  'data': { 'reference': 'str', 'sector-num': 'int', 'sector-count': 'int' } }
+
+##
+# @QUORUM_REPORT_BAD
+#
+# Emitted to report a corruption of a Quorum file
+#
+# @error: #optional, error message. Only present on failure. This field
+#         contains a human-readable error message. There are no semantics other
+#         than that the block layer reported an error and clients should not
+#         try to interpret the error string.
+#
+# @node-name: the graph node name of the block driver state
+#
+# @sector-num: number of the first sector of the failed read operation
+#
+# @sector-count: failed read operation sector count
+#
+# Since: 2.0
+##
+{ 'event': 'QUORUM_REPORT_BAD',
+  'data': { '*error': 'str', 'node-name': 'str',
+            'sector-num': 'int', 'sector-count': 'int' } }
diff --git a/qapi-schema.json b/qapi-schema.json
index 98350048f6..e7727a1153 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -630,21 +630,59 @@
 { 'command': 'query-iothreads', 'returns': ['IOThreadInfo'] }
 
 ##
-# @VncClientInfo:
+# @NetworkAddressFamily
 #
-# Information about a connected VNC client.
+# The network address family
+#
+# @ipv4: IPV4 family
+#
+# @ipv6: IPV6 family
+#
+# @unix: unix socket
 #
-# @host: The host name of the client.  QEMU tries to resolve this to a DNS name
-#        when possible.
+# @unknown: otherwise
+#
+# Since: 2.1
+##
+{ 'enum': 'NetworkAddressFamily',
+  'data': [ 'ipv4', 'ipv6', 'unix', 'unknown' ] }
+
+##
+# @VncBasicInfo
+#
+# The basic information for vnc network connection
+#
+# @host: IP address
+#
+# @service: The service name of vnc port. This may depend on the host system's
+#           service database so symbolic names should not be relied on.
+#
+# @family: address family
+#
+# Since: 2.1
+##
+{ 'type': 'VncBasicInfo',
+  'data': { 'host': 'str',
+            'service': 'str',
+            'family': 'NetworkAddressFamily' } }
+
+##
+# @VncServerInfo
 #
-# @family: 'ipv6' if the client is connected via IPv6 and TCP
-#          'ipv4' if the client is connected via IPv4 and TCP
-#          'unix' if the client is connected via a unix domain socket
-#          'unknown' otherwise
+# The network connection information for server
 #
-# @service: The service name of the client's port.  This may depends on the
-#           host system's service database so symbolic names should not be
-#           relied on.
+# @auth: #optional, authentication method
+#
+# Since: 2.1
+##
+{ 'type': 'VncServerInfo',
+  'base': 'VncBasicInfo',
+  'data': { '*auth': 'str' } }
+
+##
+# @VncClientInfo:
+#
+# Information about a connected VNC client.
 #
 # @x509_dname: #optional If x509 authentication is in use, the Distinguished
 #              Name of the client.
@@ -655,8 +693,8 @@
 # Since: 0.14.0
 ##
 { 'type': 'VncClientInfo',
-  'data': {'host': 'str', 'family': 'str', 'service': 'str',
-           '*x509_dname': 'str', '*sasl_username': 'str'} }
+  'base': 'VncBasicInfo',
+  'data': { '*x509_dname'   : 'str', '*sasl_username': 'str' } }
 
 ##
 # @VncInfo:
@@ -695,7 +733,8 @@
 # Since: 0.14.0
 ##
 { 'type': 'VncInfo',
-  'data': {'enabled': 'bool', '*host': 'str', '*family': 'str',
+  'data': {'enabled': 'bool', '*host': 'str',
+           '*family': 'NetworkAddressFamily',
            '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} }
 
 ##
@@ -710,19 +749,40 @@
 { 'command': 'query-vnc', 'returns': 'VncInfo' }
 
 ##
-# @SpiceChannel
+# @SpiceBasicInfo
 #
-# Information about a SPICE client channel.
+# The basic information for SPICE network connection
+#
+# @host: IP address
+#
+# @port: port number
+#
+# @family: address family
+#
+# Since: 2.1
+##
+{ 'type': 'SpiceBasicInfo',
+  'data': { 'host': 'str',
+            'port': 'str',
+            'family': 'NetworkAddressFamily' } }
+
+##
+# @SpiceServerInfo
 #
-# @host: The host name of the client.  QEMU tries to resolve this to a DNS name
-#        when possible.
+# Information about a SPICE server
 #
-# @family: 'ipv6' if the client is connected via IPv6 and TCP
-#          'ipv4' if the client is connected via IPv4 and TCP
-#          'unix' if the client is connected via a unix domain socket
-#          'unknown' otherwise
+# @auth: #optional, authentication method
 #
-# @port: The client's port number.
+# Since: 2.1
+##
+{ 'type': 'SpiceServerInfo',
+  'base': 'SpiceBasicInfo',
+  'data': { '*auth': 'str' } }
+
+##
+# @SpiceChannel
+#
+# Information about a SPICE client channel.
 #
 # @connection-id: SPICE connection id number.  All channels with the same id
 #                 belong to the same SPICE session.
@@ -740,8 +800,8 @@
 # Since: 0.14.0
 ##
 { 'type': 'SpiceChannel',
-  'data': {'host': 'str', 'family': 'str', 'port': 'str',
-           'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
+  'base': 'SpiceBasicInfo',
+  'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
            'tls': 'bool'} }
 
 ##
@@ -3158,19 +3218,19 @@
 ##
 # @Memdev:
 #
-# Information of memory device
+# Information about memory backend
 #
-# @size: memory device size
+# @size: memory backend size
 #
 # @merge: enables or disables memory merge support
 #
-# @dump: includes memory device's memory in a core dump or not
+# @dump: includes memory backend's memory in a core dump or not
 #
 # @prealloc: enables or disables memory preallocation
 #
 # @host-nodes: host nodes for its memory policy
 #
-# @policy: memory policy of memory device
+# @policy: memory policy of memory backend
 #
 # Since: 2.1
 ##
@@ -3187,13 +3247,15 @@
 ##
 # @query-memdev:
 #
-# Returns information for all memory devices.
+# Returns information for all memory backends.
 #
 # Returns: a list of @Memdev.
 #
 # Since: 2.1
 ##
 { 'command': 'query-memdev', 'returns': ['Memdev'] }
+
+##
 # @PCDIMMDeviceInfo:
 #
 # PCDIMMDevice state information
@@ -3286,3 +3348,55 @@
 # Since: 2.1
 ##
 { 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] }
+
+##
+# @WatchdogExpirationAction
+#
+# An enumeration of the actions taken when the watchdog device's timer is
+# expired
+#
+# @reset: system resets
+#
+# @shutdown: system shutdown, note that it is similar to @powerdown, which
+#            tries to set to system status and notify guest
+#
+# @poweroff: system poweroff, the emulator program exits
+#
+# @pause: system pauses, similar to @stop
+#
+# @debug: system enters debug state
+#
+# @none: nothing is done
+#
+# Since: 2.1
+##
+{ 'enum': 'WatchdogExpirationAction',
+  'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none' ] }
+
+##
+# @IoOperationType
+#
+# An enumeration of the I/O operation types
+#
+# @read: read operation
+#
+# @write: write operation
+#
+# Since: 2.1
+##
+{ 'enum': 'IoOperationType',
+  'data': [ 'read', 'write' ] }
+
+##
+# @GuestPanicAction
+#
+# An enumeration of the actions taken when guest OS panic is detected
+#
+# @pause: system pauses
+#
+# Since: 2.1
+##
+{ 'enum': 'GuestPanicAction',
+  'data': [ 'pause' ] }
+
+{ 'include': 'qapi-event.json' }
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
index 1f9c97342c..d14b769cff 100644
--- a/qapi/Makefile.objs
+++ b/qapi/Makefile.objs
@@ -3,3 +3,4 @@ util-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
 util-obj-y += string-input-visitor.o string-output-visitor.o
 
 util-obj-y += opts-visitor.o
+util-obj-y += qmp-event.o
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 7215e48130..af6b436540 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1410,3 +1410,153 @@
 ##
 { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
 
+
+##
+# @BlockErrorAction
+#
+# An enumeration of action that has been taken when a DISK I/O occurs
+#
+# @ignore: error has been ignored
+#
+# @report: error has been reported to the device
+#
+# @stop: error caused VM to be stopped
+#
+# Since: 2.1
+##
+{ 'enum': 'BlockErrorAction',
+  'data': [ 'ignore', 'report', 'stop' ] }
+
+
+##
+# @BLOCK_IMAGE_CORRUPTED
+#
+# Emitted when a disk image is being marked corrupt
+#
+# @device: device name
+#
+# @msg: informative message for human consumption, such as the kind of
+#       corruption being detected
+#
+# @offset: #optional, if the corruption resulted from an image access, this is
+#          the access offset into the image
+#
+# @size: #optional, if the corruption resulted from an image access, this is
+#        the access size
+#
+# Since: 1.7
+##
+{ 'event': 'BLOCK_IMAGE_CORRUPTED',
+  'data': { 'device' : 'str',
+            'msg'    : 'str',
+            '*offset': 'int',
+            '*size'  : 'int' } }
+
+##
+# @BLOCK_IO_ERROR
+#
+# Emitted when a disk I/O error occurs
+#
+# @device: device name
+#
+# @operation: I/O operation
+#
+# @action: action that has been taken
+#
+# Note: If action is "stop", a STOP event will eventually follow the
+# BLOCK_IO_ERROR event
+#
+# Since: 0.13.0
+##
+{ 'event': 'BLOCK_IO_ERROR',
+  'data': { 'device': 'str', 'operation': 'IoOperationType',
+            'action': 'BlockErrorAction' } }
+
+##
+# @BLOCK_JOB_COMPLETED
+#
+# Emitted when a block job has completed
+#
+# @type: job type
+#
+# @device: device name
+#
+# @len: maximum progress value
+#
+# @offset: current progress value. On success this is equal to len.
+#          On failure this is less than len
+#
+# @speed: rate limit, bytes per second
+#
+# @error: #optional, error message. Only present on failure. This field
+#         contains a human-readable error message. There are no semantics
+#         other than that streaming has failed and clients should not try to
+#         interpret the error string
+#
+# Since: 1.1
+##
+{ 'event': 'BLOCK_JOB_COMPLETED',
+  'data': { 'type'  : 'BlockJobType',
+            'device': 'str',
+            'len'   : 'int',
+            'offset': 'int',
+            'speed' : 'int',
+            '*error': 'str' } }
+
+##
+# @BLOCK_JOB_CANCELLED
+#
+# Emitted when a block job has been cancelled
+#
+# @type: job type
+#
+# @device: device name
+#
+# @len: maximum progress value
+#
+# @offset: current progress value. On success this is equal to len.
+#          On failure this is less than len
+#
+# @speed: rate limit, bytes per second
+#
+# Since: 1.1
+##
+{ 'event': 'BLOCK_JOB_CANCELLED',
+  'data': { 'type'  : 'BlockJobType',
+            'device': 'str',
+            'len'   : 'int',
+            'offset': 'int',
+            'speed' : 'int' } }
+
+##
+# @BLOCK_JOB_ERROR
+#
+# Emitted when a block job encounters an error
+#
+# @device: device name
+#
+# @operation: I/O operation
+#
+# @action: action that has been taken
+#
+# Since: 1.3
+##
+{ 'event': 'BLOCK_JOB_ERROR',
+  'data': { 'device'   : 'str',
+            'operation': 'IoOperationType',
+            'action'   : 'BlockdevOnError' } }
+
+##
+# @BLOCK_JOB_READY
+#
+# Emitted when a block job is ready to complete
+#
+# @device: device name
+#
+# Note: The "ready to complete" status is always reset by a @BLOCK_JOB_ERROR
+# event
+#
+# Since: 1.3
+##
+{ 'event': 'BLOCK_JOB_READY',
+  'data': { 'device': 'str' } }
diff --git a/qapi/block.json b/qapi/block.json
index 61c463ab05..e3134657b6 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -164,3 +164,17 @@
 ##
 { 'command': 'nbd-server-stop' }
 
+##
+# @DEVICE_TRAY_MOVED
+#
+# Emitted whenever the tray of a removable device is moved by the guest or by
+# HMP/QMP commands
+#
+# @device: device name
+#
+# @tray-open: true if the tray has been opened or false if it has been closed
+#
+# Since: 1.1
+##
+{ 'event': 'DEVICE_TRAY_MOVED',
+  'data': { 'device': 'str', 'tray-open': 'bool' } }
diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c
new file mode 100644
index 0000000000..0d1ce0bd18
--- /dev/null
+++ b/qapi/qmp-event.c
@@ -0,0 +1,74 @@
+/*
+ * QMP Event related
+ *
+ * Copyright (c) 2014 Wenchao Xia
+ *
+ * Authors:
+ *  Wenchao Xia   <wenchaoqemu@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <inttypes.h>
+
+#include "qemu-common.h"
+#include "qapi/qmp-event.h"
+#include "qapi/qmp/qstring.h"
+#include "qapi/qmp/qjson.h"
+
+#ifdef _WIN32
+#include "sysemu/os-win32.h"
+#endif
+
+#ifdef CONFIG_POSIX
+#include "sysemu/os-posix.h"
+#endif
+
+static QMPEventFuncEmit qmp_emit;
+
+void qmp_event_set_func_emit(QMPEventFuncEmit emit)
+{
+    qmp_emit = emit;
+}
+
+QMPEventFuncEmit qmp_event_get_func_emit(void)
+{
+    return qmp_emit;
+}
+
+static void timestamp_put(QDict *qdict)
+{
+    int err;
+    QObject *obj;
+    qemu_timeval tv;
+    int64_t sec, usec;
+
+    err = qemu_gettimeofday(&tv);
+    if (err < 0) {
+        /* Put -1 to indicate failure of getting host time */
+        sec = -1;
+        usec = -1;
+    } else {
+        sec = tv.tv_sec;
+        usec = tv.tv_usec;
+    }
+
+    obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
+                             "'microseconds': %" PRId64 " }",
+                             sec, usec);
+    qdict_put_obj(qdict, "timestamp", obj);
+}
+
+/*
+ * Build a QDict, then fill event name and time stamp, caller should free the
+ * QDict after usage.
+ */
+QDict *qmp_event_build_dict(const char *event_name)
+{
+    QDict *dict = qdict_new();
+    qdict_put(dict, "event", qstring_from_str(event_name));
+    timestamp_put(dict);
+    return dict;
+}
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index e9aca3bfdc..1ab8574585 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -98,7 +98,7 @@ static void format_string(StringOutputVisitor *sov, Range *r, bool next,
 {
     if (r->end - r->begin > 1) {
         if (human) {
-            g_string_append_printf(sov->string, "0x%" PRIx64 "-%" PRIx64,
+            g_string_append_printf(sov->string, "0x%" PRIx64 "-0x%" PRIx64,
                                    r->begin, r->end - 1);
 
         } else {
diff --git a/qemu-char.c b/qemu-char.c
index e4eb985b57..2e50a1093e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -91,6 +91,12 @@
 static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
     QTAILQ_HEAD_INITIALIZER(chardevs);
 
+CharDriverState *qemu_chr_alloc(void)
+{
+    CharDriverState *chr = g_malloc0(sizeof(CharDriverState));
+    return chr;
+}
+
 void qemu_chr_be_event(CharDriverState *s, int event)
 {
     /* Keep track if the char device is open */
@@ -115,7 +121,12 @@ void qemu_chr_be_generic_open(CharDriverState *s)
 
 int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len)
 {
-    return s->chr_write(s, buf, len);
+    int ret;
+
+    qemu_mutex_lock(&s->chr_write_lock);
+    ret = s->chr_write(s, buf, len);
+    qemu_mutex_unlock(&s->chr_write_lock);
+    return ret;
 }
 
 int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len)
@@ -123,6 +134,7 @@ int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len)
     int offset = 0;
     int res;
 
+    qemu_mutex_lock(&s->chr_write_lock);
     while (offset < len) {
         do {
             res = s->chr_write(s, buf + offset, len - offset);
@@ -131,17 +143,17 @@ int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len)
             }
         } while (res == -1 && errno == EAGAIN);
 
-        if (res == 0) {
+        if (res <= 0) {
             break;
         }
 
-        if (res < 0) {
-            return res;
-        }
-
         offset += res;
     }
+    qemu_mutex_unlock(&s->chr_write_lock);
 
+    if (res < 0) {
+        return res;
+    }
     return offset;
 }
 
@@ -204,7 +216,7 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len)
 int qemu_chr_fe_get_msgfd(CharDriverState *s)
 {
     int fd;
-    return (qemu_chr_fe_get_msgfds(s, &fd, 1) >= 0) ? fd : -1;
+    return (qemu_chr_fe_get_msgfds(s, &fd, 1) == 1) ? fd : -1;
 }
 
 int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int len)
@@ -282,7 +294,7 @@ static CharDriverState *qemu_chr_open_null(void)
 {
     CharDriverState *chr;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     chr->chr_write = null_chr_write;
     chr->explicit_be_open = true;
     return chr;
@@ -309,17 +321,20 @@ typedef struct {
     int prod[MAX_MUX];
     int cons[MAX_MUX];
     int timestamps;
+
+    /* Protected by the CharDriverState chr_write_lock.  */
     int linestart;
     int64_t timestamps_start;
 } MuxDriver;
 
 
+/* Called with chr_write_lock held.  */
 static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     MuxDriver *d = chr->opaque;
     int ret;
     if (!d->timestamps) {
-        ret = d->drv->chr_write(d->drv, buf, len);
+        ret = qemu_chr_fe_write(d->drv, buf, len);
     } else {
         int i;
 
@@ -341,10 +356,10 @@ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
                          (secs / 60) % 60,
                          secs % 60,
                          (int)(ti % 1000));
-                d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1));
+                qemu_chr_fe_write(d->drv, (uint8_t *)buf1, strlen(buf1));
                 d->linestart = 0;
             }
-            ret += d->drv->chr_write(d->drv, buf+i, 1);
+            ret += qemu_chr_fe_write(d->drv, buf+i, 1);
             if (buf[i] == '\n') {
                 d->linestart = 1;
             }
@@ -379,13 +394,13 @@ static void mux_print_help(CharDriverState *chr)
                  "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
                  term_escape_char);
     }
-    chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf));
+    qemu_chr_fe_write(chr, (uint8_t *)cbuf, strlen(cbuf));
     for (i = 0; mux_help[i] != NULL; i++) {
         for (j=0; mux_help[i][j] != '\0'; j++) {
             if (mux_help[i][j] == '%')
-                chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf));
+                qemu_chr_fe_write(chr, (uint8_t *)ebuf, strlen(ebuf));
             else
-                chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1);
+                qemu_chr_fe_write(chr, (uint8_t *)&mux_help[i][j], 1);
         }
     }
 }
@@ -410,7 +425,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
         case 'x':
             {
                  const char *term =  "QEMU: Terminated\n\r";
-                 chr->chr_write(chr,(uint8_t *)term,strlen(term));
+                 qemu_chr_fe_write(chr, (uint8_t *)term, strlen(term));
                  exit(0);
                  break;
             }
@@ -570,7 +585,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
     CharDriverState *chr;
     MuxDriver *d;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     d = g_malloc0(sizeof(MuxDriver));
 
     chr->opaque = d;
@@ -859,6 +874,7 @@ typedef struct FDCharDriver {
     QTAILQ_ENTRY(FDCharDriver) node;
 } FDCharDriver;
 
+/* Called with chr_write_lock held.  */
 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     FDCharDriver *s = chr->opaque;
@@ -945,7 +961,7 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     CharDriverState *chr;
     FDCharDriver *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     s = g_malloc0(sizeof(FDCharDriver));
     s->fd_in = io_channel_from_fd(fd_in);
     s->fd_out = io_channel_from_fd(fd_out);
@@ -1058,12 +1074,14 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
 
 typedef struct {
     GIOChannel *fd;
-    int connected;
     int read_bytes;
+
+    /* Protected by the CharDriverState chr_write_lock.  */
+    int connected;
     guint timer_tag;
 } PtyCharDriver;
 
-static void pty_chr_update_read_handler(CharDriverState *chr);
+static void pty_chr_update_read_handler_locked(CharDriverState *chr);
 static void pty_chr_state(CharDriverState *chr, int connected);
 
 static gboolean pty_chr_timer(gpointer opaque)
@@ -1071,14 +1089,17 @@ static gboolean pty_chr_timer(gpointer opaque)
     struct CharDriverState *chr = opaque;
     PtyCharDriver *s = chr->opaque;
 
+    qemu_mutex_lock(&chr->chr_write_lock);
     s->timer_tag = 0;
     if (!s->connected) {
         /* Next poll ... */
-        pty_chr_update_read_handler(chr);
+        pty_chr_update_read_handler_locked(chr);
     }
+    qemu_mutex_unlock(&chr->chr_write_lock);
     return FALSE;
 }
 
+/* Called with chr_write_lock held.  */
 static void pty_chr_rearm_timer(CharDriverState *chr, int ms)
 {
     PtyCharDriver *s = chr->opaque;
@@ -1095,13 +1116,38 @@ static void pty_chr_rearm_timer(CharDriverState *chr, int ms)
     }
 }
 
+/* Called with chr_write_lock held.  */
+static void pty_chr_update_read_handler_locked(CharDriverState *chr)
+{
+    PtyCharDriver *s = chr->opaque;
+    GPollFD pfd;
+
+    pfd.fd = g_io_channel_unix_get_fd(s->fd);
+    pfd.events = G_IO_OUT;
+    pfd.revents = 0;
+    g_poll(&pfd, 1, 0);
+    if (pfd.revents & G_IO_HUP) {
+        pty_chr_state(chr, 0);
+    } else {
+        pty_chr_state(chr, 1);
+    }
+}
+
+static void pty_chr_update_read_handler(CharDriverState *chr)
+{
+    qemu_mutex_lock(&chr->chr_write_lock);
+    pty_chr_update_read_handler_locked(chr);
+    qemu_mutex_unlock(&chr->chr_write_lock);
+}
+
+/* Called with chr_write_lock held.  */
 static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     PtyCharDriver *s = chr->opaque;
 
     if (!s->connected) {
         /* guest sends data, check for (re-)connect */
-        pty_chr_update_read_handler(chr);
+        pty_chr_update_read_handler_locked(chr);
         return 0;
     }
     return io_channel_send(s->fd, buf, len);
@@ -1147,22 +1193,7 @@ static gboolean pty_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
     return TRUE;
 }
 
-static void pty_chr_update_read_handler(CharDriverState *chr)
-{
-    PtyCharDriver *s = chr->opaque;
-    GPollFD pfd;
-
-    pfd.fd = g_io_channel_unix_get_fd(s->fd);
-    pfd.events = G_IO_OUT;
-    pfd.revents = 0;
-    g_poll(&pfd, 1, 0);
-    if (pfd.revents & G_IO_HUP) {
-        pty_chr_state(chr, 0);
-    } else {
-        pty_chr_state(chr, 1);
-    }
-}
-
+/* Called with chr_write_lock held.  */
 static void pty_chr_state(CharDriverState *chr, int connected)
 {
     PtyCharDriver *s = chr->opaque;
@@ -1222,7 +1253,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
 
     close(slave_fd);
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
 
     chr->filename = g_strdup_printf("pty:%s", pty_name);
     ret->pty = g_strdup(pty_name);
@@ -1584,7 +1615,7 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
     drv->fd = fd;
     drv->mode = IEEE1284_MODE_COMPAT;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
     chr->chr_close = pp_close;
@@ -1639,7 +1670,7 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
 {
     CharDriverState *chr;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     chr->opaque = (void *)(intptr_t)fd;
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
@@ -1653,9 +1684,12 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
 typedef struct {
     int max_size;
     HANDLE hcom, hrecv, hsend;
-    OVERLAPPED orecv, osend;
+    OVERLAPPED orecv;
     BOOL fpipe;
     DWORD len;
+
+    /* Protected by the CharDriverState chr_write_lock.  */
+    OVERLAPPED osend;
 } WinCharState;
 
 typedef struct {
@@ -1765,6 +1799,7 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
     return -1;
 }
 
+/* Called with chr_write_lock held.  */
 static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1)
 {
     WinCharState *s = chr->opaque;
@@ -1863,7 +1898,7 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
     CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     s = g_malloc0(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1962,7 +1997,7 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
     CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     s = g_malloc0(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1981,7 +2016,7 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     s = g_malloc0(sizeof(WinCharState));
     s->hcom = fd_out;
     chr->opaque = s;
@@ -2137,7 +2172,7 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
     DWORD              dwMode;
     int                is_console = 0;
 
-    chr   = g_malloc0(sizeof(CharDriverState));
+    chr   = qemu_chr_alloc();
     stdio = g_malloc0(sizeof(WinStdioCharState));
 
     stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
@@ -2207,6 +2242,7 @@ typedef struct {
     int max_size;
 } NetCharDriver;
 
+/* Called with chr_write_lock held.  */
 static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     NetCharDriver *s = chr->opaque;
@@ -2299,7 +2335,7 @@ static CharDriverState *qemu_chr_open_udp_fd(int fd)
     CharDriverState *chr = NULL;
     NetCharDriver *s = NULL;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     s = g_malloc0(sizeof(NetCharDriver));
 
     s->fd = fd;
@@ -2397,6 +2433,7 @@ static int unix_send_msgfds(CharDriverState *chr, const uint8_t *buf, int len)
 }
 #endif
 
+/* Called with chr_write_lock held.  */
 static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     TCPCharDriver *s = chr->opaque;
@@ -2481,8 +2518,15 @@ static int tcp_get_msgfds(CharDriverState *chr, int *fds, int num)
     int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
 
     if (to_copy) {
+        int i;
+
         memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
 
+        /* Close unused fds */
+        for (i = to_copy; i < s->read_msgfds_num; i++) {
+            close(s->read_msgfds[i]);
+        }
+
         g_free(s->read_msgfds);
         s->read_msgfds = 0;
         s->read_msgfds_num = 0;
@@ -2850,7 +2894,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
         return NULL;
     }
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     s = g_malloc0(sizeof(TCPCharDriver));
 
     s->connected = 0;
@@ -2994,6 +3038,7 @@ static size_t ringbuf_count(const CharDriverState *chr)
     return d->prod - d->cons;
 }
 
+/* Called with chr_write_lock held.  */
 static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     RingBufCharDriver *d = chr->opaque;
@@ -3018,9 +3063,11 @@ static int ringbuf_chr_read(CharDriverState *chr, uint8_t *buf, int len)
     RingBufCharDriver *d = chr->opaque;
     int i;
 
+    qemu_mutex_lock(&chr->chr_write_lock);
     for (i = 0; i < len && d->cons != d->prod; i++) {
         buf[i] = d->cbuf[d->cons++ & (d->size - 1)];
     }
+    qemu_mutex_unlock(&chr->chr_write_lock);
 
     return i;
 }
@@ -3040,7 +3087,7 @@ static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
     CharDriverState *chr;
     RingBufCharDriver *d;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     d = g_malloc(sizeof(*d));
 
     d->size = opts->has_size ? opts->size : 65536;
diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
index 440df60392..b19623e229 100644
--- a/qobject/json-lexer.c
+++ b/qobject/json-lexer.c
@@ -138,8 +138,8 @@ static const uint8_t json_lexer[][256] =  {
         ['n'] =  IN_SQ_STRING,
         ['r'] =  IN_SQ_STRING,
         ['t'] =  IN_SQ_STRING,
-        ['/'] = IN_DQ_STRING,
-        ['\\'] = IN_DQ_STRING,
+        ['/'] = IN_SQ_STRING,
+        ['\\'] = IN_SQ_STRING,
         ['\''] = IN_SQ_STRING,
         ['\"'] = IN_SQ_STRING,
         ['u'] = IN_SQ_UCODE0,
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 7d93d01ed2..053ba85b5f 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -29,9 +29,7 @@ def type_visitor(name):
 def generate_command_decl(name, args, ret_type):
     arglist=""
     for argname, argtype, optional, structured in parse_args(args):
-        argtype = c_type(argtype)
-        if argtype == "char *":
-            argtype = "const char *"
+        argtype = c_type(argtype, is_param=True)
         if optional:
             arglist += "bool has_%s, " % c_var(argname)
         arglist += "%s %s, " % (argtype, c_var(argname))
@@ -104,7 +102,7 @@ def gen_visitor_input_vars_decl(args):
 bool has_%(argname)s = false;
 ''',
                          argname=c_var(argname))
-        if c_type(argtype).endswith("*"):
+        if is_c_ptr(argtype):
             ret += mcgen('''
 %(argtype)s %(argname)s = NULL;
 ''',
@@ -229,7 +227,7 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
 ''')
 
     if ret_type:
-        if c_type(ret_type).endswith("*"):
+        if is_c_ptr(ret_type):
             retval = "    %s retval = NULL;" % c_type(ret_type)
         else:
             retval = "    %s retval;" % c_type(ret_type)
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
new file mode 100644
index 0000000000..3a1cd61914
--- /dev/null
+++ b/scripts/qapi-event.py
@@ -0,0 +1,369 @@
+#
+# QAPI event generator
+#
+# Copyright (c) 2014 Wenchao Xia
+#
+# Authors:
+#  Wenchao Xia <wenchaoqemu@gmail.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.
+# See the COPYING file in the top-level directory.
+
+from ordereddict import OrderedDict
+from qapi import *
+import sys
+import os
+import getopt
+import errno
+
+def _generate_event_api_name(event_name, params):
+    api_name = "void qapi_event_send_%s(" % c_fun(event_name).lower();
+    l = len(api_name)
+
+    if params:
+        for argname, argentry, optional, structured in parse_args(params):
+            if optional:
+                api_name += "bool has_%s,\n" % c_var(argname)
+                api_name += "".ljust(l)
+
+            if argentry == "str":
+                api_name += "const "
+            api_name += "%s %s,\n" % (c_type(argentry), c_var(argname))
+            api_name += "".ljust(l)
+
+    api_name += "Error **errp)"
+    return api_name;
+
+
+# Following are the core functions that generate C APIs to emit event.
+
+def generate_event_declaration(api_name):
+    return mcgen('''
+
+%(api_name)s;
+''',
+                 api_name = api_name)
+
+def generate_event_implement(api_name, event_name, params):
+    # step 1: declare any variables
+    ret = mcgen("""
+
+%(api_name)s
+{
+    QDict *qmp;
+    Error *local_err = NULL;
+    QMPEventFuncEmit emit;
+""",
+                api_name = api_name)
+
+    if params:
+        ret += mcgen("""
+    QmpOutputVisitor *qov;
+    Visitor *v;
+    QObject *obj;
+
+""")
+
+    # step 2: check emit function, create a dict
+    ret += mcgen("""
+    emit = qmp_event_get_func_emit();
+    if (!emit) {
+        return;
+    }
+
+    qmp = qmp_event_build_dict("%(event_name)s");
+
+""",
+                 event_name = event_name)
+
+    # step 3: visit the params if params != None
+    if params:
+        ret += mcgen("""
+    qov = qmp_output_visitor_new();
+    g_assert(qov);
+
+    v = qmp_output_get_visitor(qov);
+    g_assert(v);
+
+    /* Fake visit, as if all members are under a structure */
+    visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err);
+    if (local_err) {
+        goto clean;
+    }
+
+""",
+                event_name = event_name)
+
+        for argname, argentry, optional, structured in parse_args(params):
+            if optional:
+                ret += mcgen("""
+    if (has_%(var)s) {
+""",
+                             var = c_var(argname))
+                push_indent()
+
+            if argentry == "str":
+                var_type = "(char **)"
+            else:
+                var_type = ""
+
+            ret += mcgen("""
+    visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err);
+    if (local_err) {
+        goto clean;
+    }
+""",
+                         var_type = var_type,
+                         var = c_var(argname),
+                         type = type_name(argentry),
+                         name = argname)
+
+            if optional:
+                pop_indent()
+                ret += mcgen("""
+    }
+""")
+
+        ret += mcgen("""
+
+    visit_end_struct(v, &local_err);
+    if (local_err) {
+        goto clean;
+    }
+
+    obj = qmp_output_get_qobject(qov);
+    g_assert(obj != NULL);
+
+    qdict_put_obj(qmp, "data", obj);
+""")
+
+    # step 4: call qmp event api
+    ret += mcgen("""
+    emit(%(event_enum_value)s, qmp, &local_err);
+
+""",
+                 event_enum_value = event_enum_value)
+
+    # step 5: clean up
+    if params:
+        ret += mcgen("""
+ clean:
+    qmp_output_visitor_cleanup(qov);
+""")
+    ret += mcgen("""
+    error_propagate(errp, local_err);
+    QDECREF(qmp);
+}
+""")
+
+    return ret
+
+
+# Following are the functions that generate an enum type for all defined
+# events, similar to qapi-types.py. Here we already have enum name and
+# values which were generated before and recorded in event_enum_*. It also
+# works around the issue that "import qapi-types" can't work.
+
+def generate_event_enum_decl(event_enum_name, event_enum_values):
+    lookup_decl = mcgen('''
+
+extern const char *%(event_enum_name)s_lookup[];
+''',
+                        event_enum_name = event_enum_name)
+
+    enum_decl = mcgen('''
+typedef enum %(event_enum_name)s
+{
+''',
+                      event_enum_name = event_enum_name)
+
+    # append automatically generated _MAX value
+    enum_max_value = generate_enum_full_value(event_enum_name, "MAX")
+    enum_values = event_enum_values + [ enum_max_value ]
+
+    i = 0
+    for value in enum_values:
+        enum_decl += mcgen('''
+    %(value)s = %(i)d,
+''',
+                     value = value,
+                     i = i)
+        i += 1
+
+    enum_decl += mcgen('''
+} %(event_enum_name)s;
+''',
+                       event_enum_name = event_enum_name)
+
+    return lookup_decl + enum_decl
+
+def generate_event_enum_lookup(event_enum_name, event_enum_strings):
+    ret = mcgen('''
+
+const char *%(event_enum_name)s_lookup[] = {
+''',
+                event_enum_name = event_enum_name)
+
+    i = 0
+    for string in event_enum_strings:
+        ret += mcgen('''
+    "%(string)s",
+''',
+                     string = string)
+
+    ret += mcgen('''
+    NULL,
+};
+''')
+    return ret
+
+
+# Start the real job
+
+try:
+    opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:i:o:",
+                                   ["source", "header", "builtins", "prefix=",
+                                    "input-file=", "output-dir="])
+except getopt.GetoptError, err:
+    print str(err)
+    sys.exit(1)
+
+input_file = ""
+output_dir = ""
+prefix = ""
+c_file = 'qapi-event.c'
+h_file = 'qapi-event.h'
+
+do_c = False
+do_h = False
+do_builtins = False
+
+for o, a in opts:
+    if o in ("-p", "--prefix"):
+        prefix = a
+    elif o in ("-i", "--input-file"):
+        input_file = a
+    elif o in ("-o", "--output-dir"):
+        output_dir = a + "/"
+    elif o in ("-c", "--source"):
+        do_c = True
+    elif o in ("-h", "--header"):
+        do_h = True
+    elif o in ("-b", "--builtins"):
+        do_builtins = True
+
+if not do_c and not do_h:
+    do_c = True
+    do_h = True
+
+c_file = output_dir + prefix + c_file
+h_file = output_dir + prefix + h_file
+
+try:
+    os.makedirs(output_dir)
+except os.error, e:
+    if e.errno != errno.EEXIST:
+        raise
+
+def maybe_open(really, name, opt):
+    if really:
+        return open(name, opt)
+    else:
+        import StringIO
+        return StringIO.StringIO()
+
+fdef = maybe_open(do_c, c_file, 'w')
+fdecl = maybe_open(do_h, h_file, 'w')
+
+fdef.write(mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI event functions
+ *
+ * Copyright (c) 2014 Wenchao Xia
+ *
+ * Authors:
+ *  Wenchao Xia   <wenchaoqemu@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "%(header)s"
+#include "%(prefix)sqapi-visit.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/qmp-event.h"
+
+''',
+                 prefix=prefix, header=basename(h_file)))
+
+fdecl.write(mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI event functions
+ *
+ * Copyright (c) 2014 Wenchao Xia
+ *
+ * Authors:
+ *  Wenchao Xia  <wenchaoqemu@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef %(guard)s
+#define %(guard)s
+
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+#include "%(prefix)sqapi-types.h"
+
+''',
+                  prefix=prefix, guard=guardname(h_file)))
+
+exprs = parse_schema(input_file)
+
+event_enum_name = prefix.upper().replace('-', '_') + "QAPIEvent"
+event_enum_values = []
+event_enum_strings = []
+
+for expr in exprs:
+    if expr.has_key('event'):
+        event_name = expr['event']
+        params = expr.get('data')
+        if params and len(params) == 0:
+            params = None
+
+        api_name = _generate_event_api_name(event_name, params)
+        ret = generate_event_declaration(api_name)
+        fdecl.write(ret)
+
+        # We need an enum value per event
+        event_enum_value = generate_enum_full_value(event_enum_name,
+                                                    event_name)
+        ret = generate_event_implement(api_name, event_name, params)
+        fdef.write(ret)
+
+        # Record it, and generate enum later
+        event_enum_values.append(event_enum_value)
+        event_enum_strings.append(event_name)
+
+ret = generate_event_enum_decl(event_enum_name, event_enum_values)
+fdecl.write(ret)
+ret = generate_event_enum_lookup(event_enum_name, event_enum_strings)
+fdef.write(ret)
+
+fdecl.write('''
+#endif
+''')
+
+fdecl.flush()
+fdecl.close()
+
+fdef.flush()
+fdef.close()
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 06a79f1631..c12969721a 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -77,7 +77,7 @@ static void visit_type_%(full_name)s_field_%(c_name)s(Visitor *m, %(name)s **obj
 
     ret += mcgen('''
 
-static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error **errp)
+static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s **obj, Error **errp)
 {
     Error *err = NULL;
 ''',
@@ -186,7 +186,7 @@ def generate_visit_struct(expr):
 
     ret += mcgen('''
 
-void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
+void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
 {
 ''',
                 name=name)
@@ -201,7 +201,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
 def generate_visit_list(name, members):
     return mcgen('''
 
-void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
+void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp)
 {
     Error *err = NULL;
     GenericList *i, **prev;
@@ -230,7 +230,7 @@ out:
 def generate_visit_enum(name, members):
     return mcgen('''
 
-void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp)
+void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp)
 {
     visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp);
 }
@@ -240,7 +240,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e
 def generate_visit_anon_union(name, members):
     ret = mcgen('''
 
-void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
+void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
 {
     Error *err = NULL;
 
@@ -327,7 +327,7 @@ def generate_visit_union(expr):
 
     ret += mcgen('''
 
-void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
+void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
 {
     Error *err = NULL;
 
@@ -399,13 +399,13 @@ def generate_declaration(name, members, genlist=True, builtin_type=False):
     if not builtin_type:
         ret += mcgen('''
 
-void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
+void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp);
 ''',
                     name=name)
 
     if genlist:
         ret += mcgen('''
-void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp);
+void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp);
 ''',
                  name=name)
 
@@ -415,7 +415,7 @@ def generate_enum_declaration(name, members, genlist=True):
     ret = ""
     if genlist:
         ret += mcgen('''
-void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp);
+void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp);
 ''',
                      name=name)
 
@@ -424,7 +424,7 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name,
 def generate_decl_enum(name, members, genlist=True):
     return mcgen('''
 
-void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
+void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp);
 ''',
                 name=name)
 
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 86e96089af..54b97cb48e 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -248,6 +248,16 @@ def discriminator_find_enum_define(expr):
 
     return find_enum(discriminator_type)
 
+def check_event(expr, expr_info):
+    params = expr.get('data')
+    if params:
+        for argname, argentry, optional, structured in parse_args(params):
+            if structured:
+                raise QAPIExprError(expr_info,
+                                    "Nested structure define in event is not "
+                                    "supported now, event '%s', argname '%s'"
+                                    % (expr['event'], argname))
+
 def check_union(expr, expr_info):
     name = expr['union']
     base = expr.get('base')
@@ -311,6 +321,8 @@ def check_exprs(schema):
         expr = expr_elem['expr']
         if expr.has_key('union'):
             check_union(expr, expr_elem['info'])
+        if expr.has_key('event'):
+            check_event(expr, expr_elem['info'])
 
 def parse_schema(input_file):
     try:
@@ -470,9 +482,17 @@ def find_enum(name):
 def is_enum(name):
     return find_enum(name) != None
 
-def c_type(name):
+eatspace = '\033EATSPACE.'
+
+# A special suffix is added in c_type() for pointer types, and it's
+# stripped in mcgen(). So please notice this when you check the return
+# value of c_type() outside mcgen().
+def c_type(name, is_param=False):
     if name == 'str':
-        return 'char *'
+        if is_param:
+            return 'const char *' + eatspace
+        return 'char *' + eatspace
+
     elif name == 'int':
         return 'int64_t'
     elif (name == 'int8' or name == 'int16' or name == 'int32' or
@@ -486,15 +506,19 @@ def c_type(name):
     elif name == 'number':
         return 'double'
     elif type(name) == list:
-        return '%s *' % c_list_type(name[0])
+        return '%s *%s' % (c_list_type(name[0]), eatspace)
     elif is_enum(name):
         return name
     elif name == None or len(name) == 0:
         return 'void'
     elif name == name.upper():
-        return '%sEvent *' % camel_case(name)
+        return '%sEvent *%s' % (camel_case(name), eatspace)
     else:
-        return '%s *' % name
+        return '%s *%s' % (name, eatspace)
+
+def is_c_ptr(name):
+    suffix = "*" + eatspace
+    return c_type(name).endswith(suffix)
 
 def genindent(count):
     ret = ""
@@ -519,7 +543,8 @@ def cgen(code, **kwds):
     return '\n'.join(lines) % kwds + '\n'
 
 def mcgen(code, **kwds):
-    return cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
+    raw = cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
+    return re.sub(re.escape(eatspace) + ' *', '', raw)
 
 def basename(filename):
     return filename.split("/")[-1]
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 6624559952..4518a4d97d 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -268,7 +268,7 @@ static CharDriverState *chr_open(const char *subtype,
     CharDriverState *chr;
     SpiceCharDriver *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
     s = g_malloc0(sizeof(SpiceCharDriver));
     s->chr = chr;
     s->active = false;
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 997d68d5b9..528e1617b3 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -1,5 +1,6 @@
 stub-obj-y += arch-query-cpu-def.o
 stub-obj-y += bdrv-commit-all.o
+stub-obj-y += chr-baum-init.o
 stub-obj-y += chr-msmouse.o
 stub-obj-y += clock-warp.o
 stub-obj-y += cpu-get-clock.o
@@ -19,11 +20,11 @@ stub-obj-y += machine-init-done.o
 stub-obj-y += migr-blocker.o
 stub-obj-y += mon-is-qmp.o
 stub-obj-y += mon-printf.o
-stub-obj-y += mon-protocol-event.o
 stub-obj-y += mon-set-error.o
 stub-obj-y += monitor-init.o
 stub-obj-y += notify-event.o
 stub-obj-y += pci-drive-hot-add.o
+stub-obj-$(CONFIG_SPICE) += qemu-chr-open-spice.o
 stub-obj-y += qtest.o
 stub-obj-y += reset.o
 stub-obj-y += runstate-check.o
diff --git a/stubs/chr-baum-init.c b/stubs/chr-baum-init.c
new file mode 100644
index 0000000000..f5cc6ce1f8
--- /dev/null
+++ b/stubs/chr-baum-init.c
@@ -0,0 +1,7 @@
+#include "qemu-common.h"
+#include "sysemu/char.h"
+
+CharDriverState *chr_baum_init(void)
+{
+    return NULL;
+}
diff --git a/stubs/mon-protocol-event.c b/stubs/mon-protocol-event.c
deleted file mode 100644
index 0946e94724..0000000000
--- a/stubs/mon-protocol-event.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "qemu-common.h"
-#include "monitor/monitor.h"
-
-void monitor_protocol_event(MonitorEvent event, QObject *data)
-{
-}
diff --git a/stubs/qemu-chr-open-spice.c b/stubs/qemu-chr-open-spice.c
new file mode 100644
index 0000000000..f1c4849d9c
--- /dev/null
+++ b/stubs/qemu-chr-open-spice.c
@@ -0,0 +1,14 @@
+#include "qemu-common.h"
+#include "ui/qemu-spice.h"
+
+CharDriverState *qemu_chr_open_spice_vmc(const char *type)
+{
+    return NULL;
+}
+
+#if SPICE_SERVER_VERSION >= 0x000c02
+CharDriverState *qemu_chr_open_spice_port(const char *name)
+{
+    return NULL;
+}
+#endif
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a1a4cc2cab..a6e587b589 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -39,6 +39,7 @@
 #include "monitor/monitor.h"
 #include "exec/gdbstub.h"
 #include "trace.h"
+#include "qapi-event.h"
 
 /* #define DEBUG_KVM */
 
@@ -1029,12 +1030,8 @@ static bool is_special_wait_psw(CPUState *cs)
 
 static void guest_panicked(void)
 {
-    QObject *data;
-
-    data = qobject_from_jsonf("{ 'action': %s }", "pause");
-    monitor_protocol_event(QEVENT_GUEST_PANICKED, data);
-    qobject_decref(data);
-
+    qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
+                                   &error_abort);
     vm_stop(RUN_STATE_GUEST_PANICKED);
 }
 
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 436b65bffb..c83fd9fdc0 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -24,27 +24,71 @@
 
 #include "tcg-be-ldst.h"
 
-static tcg_insn_unit *tb_ret_addr;
-
 #if defined _CALL_DARWIN || defined __APPLE__
 #define TCG_TARGET_CALL_DARWIN
 #endif
+#ifdef _CALL_SYSV
+# define TCG_TARGET_CALL_ALIGN_ARGS   1
+#endif
 
-#ifdef TCG_TARGET_CALL_DARWIN
-#define LINKAGE_AREA_SIZE 24
-#define LR_OFFSET 8
-#elif defined _CALL_AIX
-#define LINKAGE_AREA_SIZE 52
-#define LR_OFFSET 8
+/* For some memory operations, we need a scratch that isn't R0.  For the AIX
+   calling convention, we can re-use the TOC register since we'll be reloading
+   it at every call.  Otherwise R12 will do nicely as neither a call-saved
+   register nor a parameter register.  */
+#ifdef _CALL_AIX
+# define TCG_REG_TMP1   TCG_REG_R2
 #else
-#define LINKAGE_AREA_SIZE 8
-#define LR_OFFSET 4
+# define TCG_REG_TMP1   TCG_REG_R12
 #endif
 
+/* For the 64-bit target, we don't like the 5 insn sequence needed to build
+   full 64-bit addresses.  Better to have a base register to which we can
+   apply a 32-bit displacement.
+
+   There are generally three items of interest:
+   (1) helper functions in the main executable,
+   (2) TranslationBlock data structures,
+   (3) the return address in the epilogue.
+
+   For user-only, we USE_STATIC_CODE_GEN_BUFFER, so the code_gen_buffer
+   will be inside the main executable, and thus near enough to make a
+   pointer to the epilogue be within 2GB of all helper functions.
+
+   For softmmu, we'll let the kernel choose the address of code_gen_buffer,
+   and odds are it'll be somewhere close to the main malloc arena, and so
+   a pointer to the epilogue will be within 2GB of the TranslationBlocks.
+
+   For --enable-pie, everything will be kinda near everything else,
+   somewhere in high memory.
+
+   Thus we choose to keep the return address in a call-saved register.  */
+#define TCG_REG_RA     TCG_REG_R31
+#define USE_REG_RA     (TCG_TARGET_REG_BITS == 64)
+
+/* Shorthand for size of a pointer.  Avoid promotion to unsigned.  */
+#define SZP  ((int)sizeof(void *))
+
+/* Shorthand for size of a register.  */
+#define SZR  (TCG_TARGET_REG_BITS / 8)
+
+#define TCG_CT_CONST_S16  0x100
+#define TCG_CT_CONST_U16  0x200
+#define TCG_CT_CONST_S32  0x400
+#define TCG_CT_CONST_U32  0x800
+#define TCG_CT_CONST_ZERO 0x1000
+#define TCG_CT_CONST_MONE 0x2000
+
+static tcg_insn_unit *tb_ret_addr;
+
 #ifndef GUEST_BASE
 #define GUEST_BASE 0
 #endif
 
+#include "elf.h"
+static bool have_isa_2_06;
+#define HAVE_ISA_2_06  have_isa_2_06
+#define HAVE_ISEL      have_isa_2_06
+
 #ifdef CONFIG_USE_GUEST_BASE
 #define TCG_GUEST_BASE_REG 30
 #else
@@ -89,7 +133,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 #endif
 
 static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_R14,
+    TCG_REG_R14,  /* call saved registers */
     TCG_REG_R15,
     TCG_REG_R16,
     TCG_REG_R17,
@@ -99,32 +143,26 @@ static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R21,
     TCG_REG_R22,
     TCG_REG_R23,
+    TCG_REG_R24,
+    TCG_REG_R25,
+    TCG_REG_R26,
+    TCG_REG_R27,
     TCG_REG_R28,
     TCG_REG_R29,
     TCG_REG_R30,
     TCG_REG_R31,
-#ifdef TCG_TARGET_CALL_DARWIN
-    TCG_REG_R2,
-#endif
-    TCG_REG_R3,
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-#ifndef TCG_TARGET_CALL_DARWIN
+    TCG_REG_R12,  /* call clobbered, non-arguments */
     TCG_REG_R11,
-#endif
-    TCG_REG_R12,
-#ifndef _CALL_SYSV
+    TCG_REG_R2,
     TCG_REG_R13,
-#endif
-    TCG_REG_R24,
-    TCG_REG_R25,
-    TCG_REG_R26,
-    TCG_REG_R27
+    TCG_REG_R10,  /* call clobbered, arguments */
+    TCG_REG_R9,
+    TCG_REG_R8,
+    TCG_REG_R7,
+    TCG_REG_R6,
+    TCG_REG_R5,
+    TCG_REG_R4,
+    TCG_REG_R3,
 };
 
 static const int tcg_target_call_iarg_regs[] = {
@@ -138,7 +176,7 @@ static const int tcg_target_call_iarg_regs[] = {
     TCG_REG_R10
 };
 
-static const int tcg_target_call_oarg_regs[2] = {
+static const int tcg_target_call_oarg_regs[] = {
     TCG_REG_R3,
     TCG_REG_R4
 };
@@ -146,10 +184,6 @@ static const int tcg_target_call_oarg_regs[2] = {
 static const int tcg_target_callee_save_regs[] = {
 #ifdef TCG_TARGET_CALL_DARWIN
     TCG_REG_R11,
-    TCG_REG_R13,
-#endif
-#ifdef _CALL_AIX
-    TCG_REG_R13,
 #endif
     TCG_REG_R14,
     TCG_REG_R15,
@@ -173,7 +207,7 @@ static const int tcg_target_callee_save_regs[] = {
 
 static inline bool in_range_b(tcg_target_long target)
 {
-    return target == sextract32(target, 0, 26);
+    return target == sextract64(target, 0, 26);
 }
 
 static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
@@ -200,6 +234,18 @@ static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
     *pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target);
 }
 
+static inline void tcg_out_b_noaddr(TCGContext *s, int insn)
+{
+    unsigned retrans = *s->code_ptr & 0x3fffffc;
+    tcg_out32(s, insn | retrans);
+}
+
+static inline void tcg_out_bc_noaddr(TCGContext *s, int insn)
+{
+    unsigned retrans = *s->code_ptr & 0xfffc;
+    tcg_out32(s, insn | retrans);
+}
+
 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
                         intptr_t value, intptr_t addend)
 {
@@ -233,59 +279,43 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
         break;
-#ifdef CONFIG_SOFTMMU
     case 'L':                   /* qemu_ld constraint */
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
+#ifdef CONFIG_SOFTMMU
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
-#if TARGET_LONG_BITS == 64
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
-#endif
 #endif
         break;
-    case 'K':                   /* qemu_st[8..32] constraint */
+    case 'S':                   /* qemu_st constraint */
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
+#ifdef CONFIG_SOFTMMU
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
-#if TARGET_LONG_BITS == 64
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R8);
-#endif
 #endif
         break;
-    case 'M':                   /* qemu_st64 constraint */
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R8);
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R9);
-#endif
+    case 'I':
+        ct->ct |= TCG_CT_CONST_S16;
         break;
-#else
-    case 'L':
-    case 'K':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
+    case 'J':
+        ct->ct |= TCG_CT_CONST_U16;
         break;
     case 'M':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
+        ct->ct |= TCG_CT_CONST_MONE;
+        break;
+    case 'T':
+        ct->ct |= TCG_CT_CONST_S32;
+        break;
+    case 'U':
+        ct->ct |= TCG_CT_CONST_U32;
+        break;
+    case 'Z':
+        ct->ct |= TCG_CT_CONST_ZERO;
         break;
-#endif
     default:
         return -1;
     }
@@ -298,48 +328,86 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 static int tcg_target_const_match(tcg_target_long val, TCGType type,
                                   const TCGArgConstraint *arg_ct)
 {
-    int ct;
+    int ct = arg_ct->ct;
+    if (ct & TCG_CT_CONST) {
+        return 1;
+    }
+
+    /* The only 32-bit constraint we use aside from
+       TCG_CT_CONST is TCG_CT_CONST_S16.  */
+    if (type == TCG_TYPE_I32) {
+        val = (int32_t)val;
+    }
 
-    ct = arg_ct->ct;
-    if (ct & TCG_CT_CONST)
+    if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
+        return 1;
+    } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
+        return 1;
+    } else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
+        return 1;
+    } else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
+        return 1;
+    } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
         return 1;
+    } else if ((ct & TCG_CT_CONST_MONE) && val == -1) {
+        return 1;
+    }
     return 0;
 }
 
 #define OPCD(opc) ((opc)<<26)
-#define XO31(opc) (OPCD(31)|((opc)<<1))
 #define XO19(opc) (OPCD(19)|((opc)<<1))
-
-#define B      OPCD(18)
-#define BC     OPCD(16)
-#define LBZ    OPCD(34)
-#define LHZ    OPCD(40)
-#define LHA    OPCD(42)
-#define LWZ    OPCD(32)
-#define STB    OPCD(38)
-#define STH    OPCD(44)
-#define STW    OPCD(36)
-
-#define ADDIC  OPCD(12)
-#define ADDI   OPCD(14)
-#define ADDIS  OPCD(15)
-#define ORI    OPCD(24)
-#define ORIS   OPCD(25)
-#define XORI   OPCD(26)
-#define XORIS  OPCD(27)
-#define ANDI   OPCD(28)
-#define ANDIS  OPCD(29)
-#define MULLI  OPCD( 7)
-#define CMPLI  OPCD(10)
-#define CMPI   OPCD(11)
+#define MD30(opc) (OPCD(30)|((opc)<<2))
+#define MDS30(opc) (OPCD(30)|((opc)<<1))
+#define XO31(opc) (OPCD(31)|((opc)<<1))
+#define XO58(opc) (OPCD(58)|(opc))
+#define XO62(opc) (OPCD(62)|(opc))
+
+#define B      OPCD( 18)
+#define BC     OPCD( 16)
+#define LBZ    OPCD( 34)
+#define LHZ    OPCD( 40)
+#define LHA    OPCD( 42)
+#define LWZ    OPCD( 32)
+#define STB    OPCD( 38)
+#define STH    OPCD( 44)
+#define STW    OPCD( 36)
+
+#define STD    XO62(  0)
+#define STDU   XO62(  1)
+#define STDX   XO31(149)
+
+#define LD     XO58(  0)
+#define LDX    XO31( 21)
+#define LDU    XO58(  1)
+#define LWA    XO58(  2)
+#define LWAX   XO31(341)
+
+#define ADDIC  OPCD( 12)
+#define ADDI   OPCD( 14)
+#define ADDIS  OPCD( 15)
+#define ORI    OPCD( 24)
+#define ORIS   OPCD( 25)
+#define XORI   OPCD( 26)
+#define XORIS  OPCD( 27)
+#define ANDI   OPCD( 28)
+#define ANDIS  OPCD( 29)
+#define MULLI  OPCD(  7)
+#define CMPLI  OPCD( 10)
+#define CMPI   OPCD( 11)
 #define SUBFIC OPCD( 8)
 
-#define LWZU   OPCD(33)
-#define STWU   OPCD(37)
+#define LWZU   OPCD( 33)
+#define STWU   OPCD( 37)
+
+#define RLWIMI OPCD( 20)
+#define RLWINM OPCD( 21)
+#define RLWNM  OPCD( 23)
 
-#define RLWIMI OPCD(20)
-#define RLWINM OPCD(21)
-#define RLWNM  OPCD(23)
+#define RLDICL MD30(  0)
+#define RLDICR MD30(  1)
+#define RLDIMI MD30(  3)
+#define RLDCL  MDS30( 8)
 
 #define BCLR   XO19( 16)
 #define BCCTR  XO19(528)
@@ -351,16 +419,22 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
 
 #define EXTSB  XO31(954)
 #define EXTSH  XO31(922)
+#define EXTSW  XO31(986)
 #define ADD    XO31(266)
 #define ADDE   XO31(138)
+#define ADDME  XO31(234)
+#define ADDZE  XO31(202)
 #define ADDC   XO31( 10)
 #define AND    XO31( 28)
 #define SUBF   XO31( 40)
 #define SUBFC  XO31(  8)
 #define SUBFE  XO31(136)
+#define SUBFME XO31(232)
+#define SUBFZE XO31(200)
 #define OR     XO31(444)
 #define XOR    XO31(316)
 #define MULLW  XO31(235)
+#define MULHW  XO31( 75)
 #define MULHWU XO31( 11)
 #define DIVW   XO31(491)
 #define DIVWU  XO31(459)
@@ -368,21 +442,31 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
 #define CMPL   XO31( 32)
 #define LHBRX  XO31(790)
 #define LWBRX  XO31(534)
+#define LDBRX  XO31(532)
 #define STHBRX XO31(918)
 #define STWBRX XO31(662)
+#define STDBRX XO31(660)
 #define MFSPR  XO31(339)
 #define MTSPR  XO31(467)
 #define SRAWI  XO31(824)
 #define NEG    XO31(104)
 #define MFCR   XO31( 19)
-#define CNTLZW XO31( 26)
+#define MFOCRF (MFCR | (1u << 20))
 #define NOR    XO31(124)
+#define CNTLZW XO31( 26)
+#define CNTLZD XO31( 58)
 #define ANDC   XO31( 60)
 #define ORC    XO31(412)
 #define EQV    XO31(284)
 #define NAND   XO31(476)
 #define ISEL   XO31( 15)
 
+#define MULLD  XO31(233)
+#define MULHD  XO31( 73)
+#define MULHDU XO31(  9)
+#define DIVD   XO31(489)
+#define DIVDU  XO31(457)
+
 #define LBZX   XO31( 87)
 #define LHZX   XO31(279)
 #define LHAX   XO31(343)
@@ -391,7 +475,7 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
 #define STHX   XO31(407)
 #define STWX   XO31(151)
 
-#define SPR(a,b) ((((a)<<5)|(b))<<11)
+#define SPR(a, b) ((((a)<<5)|(b))<<11)
 #define LR     SPR(8, 0)
 #define CTR    SPR(9, 0)
 
@@ -399,8 +483,15 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
 #define SRW    XO31(536)
 #define SRAW   XO31(792)
 
-#define TW     XO31(4)
-#define TRAP   (TW | TO (31))
+#define SLD    XO31( 27)
+#define SRD    XO31(539)
+#define SRAD   XO31(794)
+#define SRADI  XO31(413<<1)
+
+#define TW     XO31( 4)
+#define TRAP   (TW | TO(31))
+
+#define NOP    ORI  /* ori 0,0,0 */
 
 #define RT(r) ((r)<<21)
 #define RS(r) ((r)<<21)
@@ -411,21 +502,26 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type,
 #define MB(b) ((b)<<6)
 #define ME(e) ((e)<<1)
 #define BO(o) ((o)<<21)
+#define MB64(b) ((b)<<5)
+#define FXM(b) (1 << (19 - (b)))
 
 #define LK    1
 
-#define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
-#define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
+#define TAB(t, a, b) (RT(t) | RA(a) | RB(b))
+#define SAB(s, a, b) (RS(s) | RA(a) | RB(b))
+#define TAI(s, a, i) (RT(s) | RA(a) | ((i) & 0xffff))
+#define SAI(s, a, i) (RS(s) | RA(a) | ((i) & 0xffff))
 
 #define BF(n)    ((n)<<23)
 #define BI(n, c) (((c)+((n)*4))<<16)
 #define BT(n, c) (((c)+((n)*4))<<21)
 #define BA(n, c) (((c)+((n)*4))<<16)
 #define BB(n, c) (((c)+((n)*4))<<11)
+#define BC_(n, c) (((c)+((n)*4))<<6)
 
-#define BO_COND_TRUE  BO (12)
-#define BO_COND_FALSE BO (4)
-#define BO_ALWAYS     BO (20)
+#define BO_COND_TRUE  BO(12)
+#define BO_COND_FALSE BO( 4)
+#define BO_ALWAYS     BO(20)
 
 enum {
     CR_LT,
@@ -435,557 +531,348 @@ enum {
 };
 
 static const uint32_t tcg_to_bc[] = {
-    [TCG_COND_EQ]  = BC | BI (7, CR_EQ) | BO_COND_TRUE,
-    [TCG_COND_NE]  = BC | BI (7, CR_EQ) | BO_COND_FALSE,
-    [TCG_COND_LT]  = BC | BI (7, CR_LT) | BO_COND_TRUE,
-    [TCG_COND_GE]  = BC | BI (7, CR_LT) | BO_COND_FALSE,
-    [TCG_COND_LE]  = BC | BI (7, CR_GT) | BO_COND_FALSE,
-    [TCG_COND_GT]  = BC | BI (7, CR_GT) | BO_COND_TRUE,
-    [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
-    [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
-    [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
-    [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
+    [TCG_COND_EQ]  = BC | BI(7, CR_EQ) | BO_COND_TRUE,
+    [TCG_COND_NE]  = BC | BI(7, CR_EQ) | BO_COND_FALSE,
+    [TCG_COND_LT]  = BC | BI(7, CR_LT) | BO_COND_TRUE,
+    [TCG_COND_GE]  = BC | BI(7, CR_LT) | BO_COND_FALSE,
+    [TCG_COND_LE]  = BC | BI(7, CR_GT) | BO_COND_FALSE,
+    [TCG_COND_GT]  = BC | BI(7, CR_GT) | BO_COND_TRUE,
+    [TCG_COND_LTU] = BC | BI(7, CR_LT) | BO_COND_TRUE,
+    [TCG_COND_GEU] = BC | BI(7, CR_LT) | BO_COND_FALSE,
+    [TCG_COND_LEU] = BC | BI(7, CR_GT) | BO_COND_FALSE,
+    [TCG_COND_GTU] = BC | BI(7, CR_GT) | BO_COND_TRUE,
 };
 
+/* The low bit here is set if the RA and RB fields must be inverted.  */
+static const uint32_t tcg_to_isel[] = {
+    [TCG_COND_EQ]  = ISEL | BC_(7, CR_EQ),
+    [TCG_COND_NE]  = ISEL | BC_(7, CR_EQ) | 1,
+    [TCG_COND_LT]  = ISEL | BC_(7, CR_LT),
+    [TCG_COND_GE]  = ISEL | BC_(7, CR_LT) | 1,
+    [TCG_COND_LE]  = ISEL | BC_(7, CR_GT) | 1,
+    [TCG_COND_GT]  = ISEL | BC_(7, CR_GT),
+    [TCG_COND_LTU] = ISEL | BC_(7, CR_LT),
+    [TCG_COND_GEU] = ISEL | BC_(7, CR_LT) | 1,
+    [TCG_COND_LEU] = ISEL | BC_(7, CR_GT) | 1,
+    [TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
+};
+
+static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
+                             TCGReg base, tcg_target_long offset);
+
 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
+    tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
     if (ret != arg) {
         tcg_out32(s, OR | SAB(arg, ret, arg));
     }
 }
 
-static void tcg_out_movi(TCGContext *s, TCGType type,
-                         TCGReg ret, tcg_target_long arg)
+static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
+                               int sh, int mb)
 {
-    if (arg == (int16_t) arg)
-        tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
-    else {
-        tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
-        if (arg & 0xffff)
-            tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
-    }
+    assert(TCG_TARGET_REG_BITS == 64);
+    sh = SH(sh & 0x1f) | (((sh >> 5) & 1) << 1);
+    mb = MB64((mb >> 5) | ((mb << 1) & 0x3f));
+    tcg_out32(s, op | RA(ra) | RS(rs) | sh | mb);
 }
 
-static void tcg_out_ldst (TCGContext *s, int ret, int addr,
-                          int offset, int op1, int op2)
+static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
+                               int sh, int mb, int me)
 {
-    if (offset == (int16_t) offset)
-        tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
-    else {
-        tcg_out_movi (s, TCG_TYPE_I32, 0, offset);
-        tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
-    }
+    tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
 }
 
-static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
+static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
 {
-    ptrdiff_t disp = tcg_pcrel_diff(s, target);
-    if (in_range_b(disp)) {
-        tcg_out32(s, B | (disp & 0x3fffffc) | mask);
-    } else {
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, (uintptr_t)target);
-        tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
-        tcg_out32(s, BCCTR | BO_ALWAYS | mask);
-    }
+    tcg_out_rld(s, RLDICL, dst, src, 0, 32);
 }
 
-static void tcg_out_call1(TCGContext *s, tcg_insn_unit *target, int lk)
+static inline void tcg_out_shli32(TCGContext *s, TCGReg dst, TCGReg src, int c)
 {
-#ifdef _CALL_AIX
-    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, (uintptr_t)target);
-    tcg_out32(s, LWZ | RT(TCG_REG_R0) | RA(reg));
-    tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
-    tcg_out32(s, LWZ | RT(TCG_REG_R2) | RA(reg) | 4);
-    tcg_out32(s, BCCTR | BO_ALWAYS | lk);
-#else
-    tcg_out_b(s, lk, target);
-#endif
+    tcg_out_rlw(s, RLWINM, dst, src, c, 0, 31 - c);
 }
 
-static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
+static inline void tcg_out_shli64(TCGContext *s, TCGReg dst, TCGReg src, int c)
 {
-    tcg_out_call1(s, target, LK);
+    tcg_out_rld(s, RLDICR, dst, src, c, 63 - c);
 }
 
-#if defined(CONFIG_SOFTMMU)
-
-static void add_qemu_ldst_label (TCGContext *s,
-                                 bool is_ld,
-                                 TCGMemOp opc,
-                                 int data_reg,
-                                 int data_reg2,
-                                 int addrlo_reg,
-                                 int addrhi_reg,
-                                 int mem_index,
-                                 tcg_insn_unit *raddr,
-                                 tcg_insn_unit *label_ptr)
+static inline void tcg_out_shri32(TCGContext *s, TCGReg dst, TCGReg src, int c)
 {
-    TCGLabelQemuLdst *label = new_ldst_label(s);
-
-    label->is_ld = is_ld;
-    label->opc = opc;
-    label->datalo_reg = data_reg;
-    label->datahi_reg = data_reg2;
-    label->addrlo_reg = addrlo_reg;
-    label->addrhi_reg = addrhi_reg;
-    label->mem_index = mem_index;
-    label->raddr = raddr;
-    label->label_ptr[0] = label_ptr;
+    tcg_out_rlw(s, RLWINM, dst, src, 32 - c, c, 31);
 }
 
-/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
- *                                     int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_ld_helpers[16] = {
-    [MO_UB]   = helper_ret_ldub_mmu,
-    [MO_LEUW] = helper_le_lduw_mmu,
-    [MO_LEUL] = helper_le_ldul_mmu,
-    [MO_LEQ]  = helper_le_ldq_mmu,
-    [MO_BEUW] = helper_be_lduw_mmu,
-    [MO_BEUL] = helper_be_ldul_mmu,
-    [MO_BEQ]  = helper_be_ldq_mmu,
-};
-
-/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
- *                                     uintxx_t val, int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_st_helpers[16] = {
-    [MO_UB]   = helper_ret_stb_mmu,
-    [MO_LEUW] = helper_le_stw_mmu,
-    [MO_LEUL] = helper_le_stl_mmu,
-    [MO_LEQ]  = helper_le_stq_mmu,
-    [MO_BEUW] = helper_be_stw_mmu,
-    [MO_BEUL] = helper_be_stl_mmu,
-    [MO_BEQ]  = helper_be_stq_mmu,
-};
-
-static tcg_insn_unit *ld_trampolines[16];
-static tcg_insn_unit *st_trampolines[16];
-
-/* Perform the TLB load and compare.  Branches to the slow path, placing the
-   address of the branch in *LABEL_PTR.  Loads the addend of the TLB into R0.
-   Clobbers R1 and R2.  */
-
-static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
-                              TCGReg addrlo, TCGReg addrhi, TCGMemOp s_bits,
-                              int mem_index, int is_load,
-                              tcg_insn_unit **label_ptr)
+static inline void tcg_out_shri64(TCGContext *s, TCGReg dst, TCGReg src, int c)
 {
-    int cmp_off =
-        (is_load
-         ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
-         : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
-    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
-    tcg_insn_unit retranst;
-    TCGReg base = TCG_AREG0;
-
-    /* Extract the page index, shifted into place for tlb index.  */
-    tcg_out32(s, (RLWINM
-                  | RA(r0)
-                  | RS(addrlo)
-                  | SH(32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
-                  | MB(32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
-                  | ME(31 - CPU_TLB_ENTRY_BITS)));
-
-    /* Compensate for very large offsets.  */
-    if (add_off >= 0x8000) {
-        /* Most target env are smaller than 32k; none are larger than 64k.
-           Simplify the logic here merely to offset by 0x7ff0, giving us a
-           range just shy of 64k.  Check this assumption.  */
-        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
-                                   tlb_table[NB_MMU_MODES - 1][1])
-                          > 0x7ff0 + 0x7fff);
-        tcg_out32(s, ADDI | RT(r1) | RA(base) | 0x7ff0);
-        base = r1;
-        cmp_off -= 0x7ff0;
-        add_off -= 0x7ff0;
-    }
-
-    /* Clear the non-page, non-alignment bits from the address.  */
-    tcg_out32(s, (RLWINM
-                  | RA(r2)
-                  | RS(addrlo)
-                  | SH(0)
-                  | MB((32 - s_bits) & 31)
-                  | ME(31 - TARGET_PAGE_BITS)));
-
-    tcg_out32(s, ADD | RT(r0) | RA(r0) | RB(base));
-    base = r0;
-
-    /* Load the tlb comparator.  */
-    tcg_out32(s, LWZ | RT(r1) | RA(base) | (cmp_off & 0xffff));
-
-    tcg_out32(s, CMP | BF(7) | RA(r2) | RB(r1));
-
-    if (TARGET_LONG_BITS == 64) {
-        tcg_out32(s, LWZ | RT(r1) | RA(base) | ((cmp_off + 4) & 0xffff));
-    }
-
-    /* Load the tlb addend for use on the fast path.
-       Do this asap to minimize load delay.  */
-    tcg_out32(s, LWZ | RT(r0) | RA(base) | (add_off & 0xffff));
+    tcg_out_rld(s, RLDICL, dst, src, 64 - c, c);
+}
 
-    if (TARGET_LONG_BITS == 64) {
-        tcg_out32(s, CMP | BF(6) | RA(addrhi) | RB(r1));
-        tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
+{
+    if (arg == (int16_t) arg) {
+        tcg_out32(s, ADDI | TAI(ret, 0, arg));
+    } else {
+        tcg_out32(s, ADDIS | TAI(ret, 0, arg >> 16));
+        if (arg & 0xffff) {
+            tcg_out32(s, ORI | SAI(ret, ret, arg));
+        }
     }
-
-    /* Use a conditional branch-and-link so that we load a pointer to
-       somewhere within the current opcode, for passing on to the helper.
-       This address cannot be used for a tail call, but it's shorter
-       than forming an address from scratch.  */
-    *label_ptr = s->code_ptr;
-    retranst = *s->code_ptr & 0xfffc;
-    tcg_out32(s, BC | BI(7, CR_EQ) | retranst | BO_COND_FALSE | LK);
 }
-#endif
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
+static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
+                         tcg_target_long arg)
 {
-    TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
-    TCGMemOp opc, bswap;
-#ifdef CONFIG_SOFTMMU
-    int mem_index;
-    tcg_insn_unit *label_ptr;
-#endif
-
-    datalo = *args++;
-    datahi = (is64 ? *args++ : 0);
-    addrlo = *args++;
-    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-    opc = *args++;
-    bswap = opc & MO_BSWAP;
+    tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
+    if (type == TCG_TYPE_I32 || arg == (int32_t)arg) {
+        tcg_out_movi32(s, ret, arg);
+    } else if (arg == (uint32_t)arg && !(arg & 0x8000)) {
+        tcg_out32(s, ADDI | TAI(ret, 0, arg));
+        tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
+    } else {
+        int32_t high;
 
-#ifdef CONFIG_SOFTMMU
-    mem_index = *args;
-    tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
-                      addrhi, opc & MO_SIZE, mem_index, 0, &label_ptr);
-    rbase = TCG_REG_R3;
-#else  /* !CONFIG_SOFTMMU */
-    rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
-#endif
+        if (USE_REG_RA) {
+            intptr_t diff = arg - (intptr_t)tb_ret_addr;
+            if (diff == (int32_t)diff) {
+                tcg_out_mem_long(s, ADDI, ADD, ret, TCG_REG_RA, diff);
+                return;
+            }
+        }
 
-    switch (opc & MO_SSIZE) {
-    default:
-    case MO_UB:
-        tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
-        break;
-    case MO_SB:
-        tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
-        tcg_out32(s, EXTSB | RA(datalo) | RS(datalo));
-        break;
-    case MO_UW:
-        tcg_out32(s, (bswap ? LHBRX : LHZX) | TAB(datalo, rbase, addrlo));
-        break;
-    case MO_SW:
-        if (bswap) {
-            tcg_out32(s, LHBRX | TAB(datalo, rbase, addrlo));
-            tcg_out32(s, EXTSH | RA(datalo) | RS(datalo));
-        } else {
-            tcg_out32(s, LHAX | TAB(datalo, rbase, addrlo));
+        high = arg >> 31 >> 1;
+        tcg_out_movi32(s, ret, high);
+        if (high) {
+            tcg_out_shli64(s, ret, ret, 32);
         }
-        break;
-    case MO_UL:
-        tcg_out32(s, (bswap ? LWBRX : LWZX) | TAB(datalo, rbase, addrlo));
-        break;
-    case MO_Q:
-        if (bswap) {
-            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
-            tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
-            tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0));
-        } else if (rbase != 0) {
-            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
-            tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo));
-            tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0));
-        } else if (addrlo == datahi) {
-            tcg_out32(s, LWZ | RT(datalo) | RA(addrlo) | 4);
-            tcg_out32(s, LWZ | RT(datahi) | RA(addrlo));
-        } else {
-            tcg_out32(s, LWZ | RT(datahi) | RA(addrlo));
-            tcg_out32(s, LWZ | RT(datalo) | RA(addrlo) | 4);
+        if (arg & 0xffff0000) {
+            tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
+        }
+        if (arg & 0xffff) {
+            tcg_out32(s, ORI | SAI(ret, ret, arg));
         }
-        break;
     }
-#ifdef CONFIG_SOFTMMU
-    add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo,
-                        addrhi, mem_index, s->code_ptr, label_ptr);
-#endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
+static bool mask_operand(uint32_t c, int *mb, int *me)
 {
-    TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
-    TCGMemOp opc, bswap, s_bits;
-#ifdef CONFIG_SOFTMMU
-    int mem_index;
-    tcg_insn_unit *label_ptr;
-#endif
+    uint32_t lsb, test;
+
+    /* Accept a bit pattern like:
+           0....01....1
+           1....10....0
+           0..01..10..0
+       Keep track of the transitions.  */
+    if (c == 0 || c == -1) {
+        return false;
+    }
+    test = c;
+    lsb = test & -test;
+    test += lsb;
+    if (test & (test - 1)) {
+        return false;
+    }
 
-    datalo = *args++;
-    datahi = (is64 ? *args++ : 0);
-    addrlo = *args++;
-    addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-    opc = *args++;
-    bswap = opc & MO_BSWAP;
-    s_bits = opc & MO_SIZE;
+    *me = clz32(lsb);
+    *mb = test ? clz32(test & -test) + 1 : 0;
+    return true;
+}
 
-#ifdef CONFIG_SOFTMMU
-    mem_index = *args;
-    tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
-                      addrhi, s_bits, mem_index, 0, &label_ptr);
-    rbase = TCG_REG_R3;
-#else  /* !CONFIG_SOFTMMU */
-    rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
-#endif
+static bool mask64_operand(uint64_t c, int *mb, int *me)
+{
+    uint64_t lsb;
 
-    switch (s_bits) {
-    case MO_8:
-        tcg_out32(s, STBX | SAB(datalo, rbase, addrlo));
-        break;
-    case MO_16:
-        tcg_out32(s, (bswap ? STHBRX : STHX) | SAB(datalo, rbase, addrlo));
-        break;
-    case MO_32:
-    default:
-        tcg_out32(s, (bswap ? STWBRX : STWX) | SAB(datalo, rbase, addrlo));
-        break;
-    case MO_64:
-        if (bswap) {
-            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
-            tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
-            tcg_out32(s, STWBRX | SAB(datahi, rbase, TCG_REG_R0));
-        } else if (rbase != 0) {
-            tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
-            tcg_out32(s, STWX | SAB(datahi, rbase, addrlo));
-            tcg_out32(s, STWX | SAB(datalo, rbase, TCG_REG_R0));
-        } else {
-            tcg_out32(s, STW | RS(datahi) | RA(addrlo));
-            tcg_out32(s, STW | RS(datalo) | RA(addrlo) | 4);
-        }
-        break;
+    if (c == 0) {
+        return false;
     }
 
-#ifdef CONFIG_SOFTMMU
-    add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
-                        mem_index, s->code_ptr, label_ptr);
-#endif
+    lsb = c & -c;
+    /* Accept 1..10..0.  */
+    if (c == -lsb) {
+        *mb = 0;
+        *me = clz64(lsb);
+        return true;
+    }
+    /* Accept 0..01..1.  */
+    if (lsb == 1 && (c & (c + 1)) == 0) {
+        *mb = clz64(c + 1) + 1;
+        *me = 63;
+        return true;
+    }
+    return false;
 }
 
-#if defined(CONFIG_SOFTMMU)
-static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
 {
-    TCGReg ir, datalo, datahi;
-    TCGMemOp opc = l->opc;
+    int mb, me;
 
-    reloc_pc14(l->label_ptr[0], s->code_ptr);
-
-    ir = TCG_REG_R4;
-    if (TARGET_LONG_BITS == 32) {
-        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrlo_reg);
+    if ((c & 0xffff) == c) {
+        tcg_out32(s, ANDI | SAI(src, dst, c));
+        return;
+    } else if ((c & 0xffff0000) == c) {
+        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
+        return;
+    } else if (mask_operand(c, &mb, &me)) {
+        tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
     } else {
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
-        ir |= 1;
-#endif
-        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrhi_reg);
-        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->addrlo_reg);
+        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R0, c);
+        tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
     }
-    tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
-    tcg_out32(s, MFSPR | RT(ir++) | LR);
-    tcg_out_b(s, LK, ld_trampolines[opc & ~MO_SIGN]);
+}
 
-    datalo = l->datalo_reg;
-    switch (opc & MO_SSIZE) {
-    case MO_SB:
-        tcg_out32(s, EXTSB | RA(datalo) | RS(TCG_REG_R3));
-        break;
-    case MO_SW:
-        tcg_out32(s, EXTSH | RA(datalo) | RS(TCG_REG_R3));
-        break;
-    default:
-        tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R3);
-        break;
-    case MO_Q:
-        datahi = l->datahi_reg;
-        if (datalo != TCG_REG_R3) {
-            tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
-            tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
-        } else if (datahi != TCG_REG_R4) {
-            tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
-            tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
+static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
+{
+    int mb, me;
+
+    assert(TCG_TARGET_REG_BITS == 64);
+    if ((c & 0xffff) == c) {
+        tcg_out32(s, ANDI | SAI(src, dst, c));
+        return;
+    } else if ((c & 0xffff0000) == c) {
+        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
+        return;
+    } else if (mask64_operand(c, &mb, &me)) {
+        if (mb == 0) {
+            tcg_out_rld(s, RLDICR, dst, src, 0, me);
         } else {
-            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R0, TCG_REG_R4);
-            tcg_out_mov(s, TCG_TYPE_I32, datahi, TCG_REG_R3);
-            tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R0);
+            tcg_out_rld(s, RLDICL, dst, src, 0, mb);
         }
-        break;
+    } else {
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, c);
+        tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
     }
-    tcg_out_b(s, 0, l->raddr);
 }
 
-static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
+                           int op_lo, int op_hi)
 {
-    TCGReg ir, datalo;
-    TCGMemOp opc = l->opc;
-
-    reloc_pc14(l->label_ptr[0], s->code_ptr);
-
-    ir = TCG_REG_R4;
-    if (TARGET_LONG_BITS == 32) {
-        tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrlo_reg);
-    } else {
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
-        ir |= 1;
-#endif
-        tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrhi_reg);
-        tcg_out_mov (s, TCG_TYPE_I32, ir++, l->addrlo_reg);
+    if (c >> 16) {
+        tcg_out32(s, op_hi | SAI(src, dst, c >> 16));
+        src = dst;
     }
-
-    datalo = l->datalo_reg;
-    switch (opc & MO_SIZE) {
-    case MO_8:
-        tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
-                      | SH (0) | MB (24) | ME (31)));
-        break;
-    case MO_16:
-        tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
-                      | SH (0) | MB (16) | ME (31)));
-        break;
-    default:
-        tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
-        break;
-    case MO_64:
-#ifdef TCG_TARGET_CALL_ALIGN_ARGS
-        ir |= 1;
-#endif
-        tcg_out_mov(s, TCG_TYPE_I32, ir++, l->datahi_reg);
-        tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
-        break;
+    if (c & 0xffff) {
+        tcg_out32(s, op_lo | SAI(src, dst, c));
+        src = dst;
     }
-    ir++;
-
-    tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
-    tcg_out32(s, MFSPR | RT(ir++) | LR);
-    tcg_out_b(s, LK, st_trampolines[opc]);
-    tcg_out_b(s, 0, l->raddr);
 }
-#endif
 
-#ifdef CONFIG_SOFTMMU
-static void emit_ldst_trampoline(TCGContext *s, tcg_insn_unit *ptr)
+static void tcg_out_ori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
 {
-    tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
-    tcg_out_call1(s, ptr, 0);
+    tcg_out_zori32(s, dst, src, c, ORI, ORIS);
 }
-#endif
 
-static void tcg_target_qemu_prologue (TCGContext *s)
+static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
 {
-    int i, frame_size;
-
-    frame_size = 0
-        + LINKAGE_AREA_SIZE
-        + TCG_STATIC_CALL_ARGS_SIZE
-        + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
-        + CPU_TEMP_BUF_NLONGS * sizeof(long)
-        ;
-    frame_size = (frame_size + 15) & ~15;
-
-    tcg_set_frame(s, TCG_REG_CALL_STACK, frame_size
-                  - CPU_TEMP_BUF_NLONGS * sizeof(long),
-                  CPU_TEMP_BUF_NLONGS * sizeof(long));
+    tcg_out_zori32(s, dst, src, c, XORI, XORIS);
+}
 
-#ifdef _CALL_AIX
-    {
-        uintptr_t addr;
+static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
+{
+    ptrdiff_t disp = tcg_pcrel_diff(s, target);
+    if (in_range_b(disp)) {
+        tcg_out32(s, B | (disp & 0x3fffffc) | mask);
+    } else {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, (uintptr_t)target);
+        tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
+        tcg_out32(s, BCCTR | BO_ALWAYS | mask);
+    }
+}
 
-        /* First emit adhoc function descriptor */
-        addr = (uintptr_t)s->code_ptr + 12;
-        tcg_out32(s, addr);        /* entry point */
-        tcg_out32(s, 0);           /* toc */
-        tcg_out32(s, 0);           /* environment pointer */
+static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
+                             TCGReg base, tcg_target_long offset)
+{
+    tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
+    bool is_store = false;
+    TCGReg rs = TCG_REG_TMP1;
+
+    switch (opi) {
+    case LD: case LWA:
+        align = 3;
+        /* FALLTHRU */
+    default:
+        if (rt != TCG_REG_R0) {
+            rs = rt;
+            break;
+        }
+        break;
+    case STD:
+        align = 3;
+        /* FALLTHRU */
+    case STB: case STH: case STW:
+        is_store = true;
+        break;
     }
-#endif
-    tcg_out32 (s, MFSPR | RT (0) | LR);
-    tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
-    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
-        tcg_out32 (s, (STW
-                       | RS (tcg_target_callee_save_regs[i])
-                       | RA (1)
-                       | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
-                       )
-            );
-    tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + LR_OFFSET));
 
-#ifdef CONFIG_USE_GUEST_BASE
-    if (GUEST_BASE) {
-        tcg_out_movi (s, TCG_TYPE_I32, TCG_GUEST_BASE_REG, GUEST_BASE);
-        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+    /* For unaligned, or very large offsets, use the indexed form.  */
+    if (offset & align || offset != (int32_t)offset) {
+        tcg_debug_assert(rs != base && (!is_store || rs != rt));
+        tcg_out_movi(s, TCG_TYPE_PTR, rs, orig);
+        tcg_out32(s, opx | TAB(rt, base, rs));
+        return;
     }
-#endif
 
-    tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
-    tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
-    tcg_out32 (s, BCCTR | BO_ALWAYS);
-    tb_ret_addr = s->code_ptr;
-
-    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
-        tcg_out32 (s, (LWZ
-                       | RT (tcg_target_callee_save_regs[i])
-                       | RA (1)
-                       | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
-                       )
-            );
-    tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + LR_OFFSET));
-    tcg_out32 (s, MTSPR | RS (0) | LR);
-    tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
-    tcg_out32 (s, BCLR | BO_ALWAYS);
+    l0 = (int16_t)offset;
+    offset = (offset - l0) >> 16;
+    l1 = (int16_t)offset;
 
-#ifdef CONFIG_SOFTMMU
-    for (i = 0; i < 16; ++i) {
-        if (qemu_ld_helpers[i]) {
-            ld_trampolines[i] = s->code_ptr;
-            emit_ldst_trampoline(s, qemu_ld_helpers[i]);
-        }
-        if (qemu_st_helpers[i]) {
-            st_trampolines[i] = s->code_ptr;
-            emit_ldst_trampoline(s, qemu_st_helpers[i]);
-        }
+    if (l1 < 0 && orig >= 0) {
+        extra = 0x4000;
+        l1 = (int16_t)(offset - 0x4000);
+    }
+    if (l1) {
+        tcg_out32(s, ADDIS | TAI(rs, base, l1));
+        base = rs;
+    }
+    if (extra) {
+        tcg_out32(s, ADDIS | TAI(rs, base, extra));
+        base = rs;
+    }
+    if (opi != ADDI || base != rt || l0 != 0) {
+        tcg_out32(s, opi | TAI(rt, base, l0));
     }
-#endif
 }
 
-static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
-                       intptr_t arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, intptr_t arg2)
 {
-    tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
-}
+    int opi, opx;
 
-static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
-                       intptr_t arg2)
-{
-    tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
+    assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
+    if (type == TCG_TYPE_I32) {
+        opi = LWZ, opx = LWZX;
+    } else {
+        opi = LD, opx = LDX;
+    }
+    tcg_out_mem_long(s, opi, opx, ret, arg1, arg2);
 }
 
-static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+                              TCGReg arg1, intptr_t arg2)
 {
-    if (!si && rt == ra)
-        return;
+    int opi, opx;
 
-    if (si == (int16_t) si)
-        tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
-    else {
-        uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
-        tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
-        tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
+    assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
+    if (type == TCG_TYPE_I32) {
+        opi = STW, opx = STWX;
+    } else {
+        opi = STD, opx = STDX;
     }
+    tcg_out_mem_long(s, opi, opx, arg, arg1, arg2);
 }
 
-static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
-                         int const_arg2, int cr)
+static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
+                        int const_arg2, int cr, TCGType type)
 {
     int imm;
     uint32_t op;
 
+    tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
+
+    /* Simplify the comparisons below wrt CMPI.  */
+    if (type == TCG_TYPE_I32) {
+        arg2 = (int32_t)arg2;
+    }
+
     switch (cond) {
     case TCG_COND_EQ:
     case TCG_COND_NE:
@@ -994,8 +881,7 @@ static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
                 op = CMPI;
                 imm = 1;
                 break;
-            }
-            else if ((uint16_t) arg2 == arg2) {
+            } else if ((uint16_t) arg2 == arg2) {
                 op = CMPLI;
                 imm = 1;
                 break;
@@ -1036,148 +922,144 @@ static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
         break;
 
     default:
-        tcg_abort ();
+        tcg_abort();
     }
-    op |= BF (cr);
+    op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
 
-    if (imm)
-        tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
-    else {
+    if (imm) {
+        tcg_out32(s, op | RA(arg1) | (arg2 & 0xffff));
+    } else {
         if (const_arg2) {
-            tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
-            tcg_out32 (s, op | RA (arg1) | RB (0));
+            tcg_out_movi(s, type, TCG_REG_R0, arg2);
+            arg2 = TCG_REG_R0;
         }
-        else
-            tcg_out32 (s, op | RA (arg1) | RB (arg2));
+        tcg_out32(s, op | RA(arg1) | RB(arg2));
     }
-
 }
 
-static void tcg_out_bc(TCGContext *s, int bc, int label_index)
+static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
+                                TCGReg dst, TCGReg src)
 {
-    TCGLabel *l = &s->labels[label_index];
-
-    if (l->has_value) {
-        tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
+    if (type == TCG_TYPE_I32) {
+        tcg_out32(s, CNTLZW | RS(src) | RA(dst));
+        tcg_out_shri32(s, dst, dst, 5);
     } else {
-        /* Thanks to Andrzej Zaborowski */
-        tcg_insn_unit retrans = *s->code_ptr & 0xfffc;
-        tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
-        tcg_out32(s, bc | retrans);
+        tcg_out32(s, CNTLZD | RS(src) | RA(dst));
+        tcg_out_shri64(s, dst, dst, 6);
     }
 }
 
-static void tcg_out_cr7eq_from_cond (TCGContext *s, const TCGArg *args,
-                                     const int *const_args)
+static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
 {
-    TCGCond cond = args[4];
-    int op;
-    struct { int bit1; int bit2; int cond2; } bits[] = {
-        [TCG_COND_LT ] = { CR_LT, CR_LT, TCG_COND_LT  },
-        [TCG_COND_LE ] = { CR_LT, CR_GT, TCG_COND_LT  },
-        [TCG_COND_GT ] = { CR_GT, CR_GT, TCG_COND_GT  },
-        [TCG_COND_GE ] = { CR_GT, CR_LT, TCG_COND_GT  },
-        [TCG_COND_LTU] = { CR_LT, CR_LT, TCG_COND_LTU },
-        [TCG_COND_LEU] = { CR_LT, CR_GT, TCG_COND_LTU },
-        [TCG_COND_GTU] = { CR_GT, CR_GT, TCG_COND_GTU },
-        [TCG_COND_GEU] = { CR_GT, CR_LT, TCG_COND_GTU },
-    }, *b = &bits[cond];
+    /* X != 0 implies X + -1 generates a carry.  Extra addition
+       trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C.  */
+    if (dst != src) {
+        tcg_out32(s, ADDIC | TAI(dst, src, -1));
+        tcg_out32(s, SUBFE | TAB(dst, dst, src));
+    } else {
+        tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
+        tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
+    }
+}
 
-    switch (cond) {
-    case TCG_COND_EQ:
-    case TCG_COND_NE:
-        op = (cond == TCG_COND_EQ) ? CRAND : CRNAND;
-        tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 6);
-        tcg_out_cmp (s, cond, args[1], args[3], const_args[3], 7);
-        tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
-        break;
-    case TCG_COND_LT:
-    case TCG_COND_LE:
-    case TCG_COND_GT:
-    case TCG_COND_GE:
-    case TCG_COND_LTU:
-    case TCG_COND_LEU:
-    case TCG_COND_GTU:
-    case TCG_COND_GEU:
-        op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
-        tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
-        tcg_out_cmp (s, tcg_unsigned_cond (cond), args[0], args[2],
-                     const_args[2], 7);
-        tcg_out32 (s, op | BT (7, CR_EQ) | BA (5, CR_EQ) | BB (7, b->bit2));
-        tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
-        break;
-    default:
-        tcg_abort();
+static TCGReg tcg_gen_setcond_xor(TCGContext *s, TCGReg arg1, TCGArg arg2,
+                                  bool const_arg2)
+{
+    if (const_arg2) {
+        if ((uint32_t)arg2 == arg2) {
+            tcg_out_xori32(s, TCG_REG_R0, arg1, arg2);
+        } else {
+            tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, arg2);
+            tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, TCG_REG_R0));
+        }
+    } else {
+        tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, arg2));
     }
+    return TCG_REG_R0;
 }
 
-static void tcg_out_setcond (TCGContext *s, TCGCond cond, TCGArg arg0,
-                             TCGArg arg1, TCGArg arg2, int const_arg2)
+static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
+                            TCGArg arg0, TCGArg arg1, TCGArg arg2,
+                            int const_arg2)
 {
-    int crop, sh, arg;
+    int crop, sh;
 
-    switch (cond) {
-    case TCG_COND_EQ:
-        if (const_arg2) {
-            if (!arg2) {
-                arg = arg1;
-            }
-            else {
-                arg = 0;
-                if ((uint16_t) arg2 == arg2) {
-                    tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
-                }
-                else {
-                    tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
-                    tcg_out32 (s, XOR | SAB (arg1, 0, 0));
-                }
-            }
-        }
-        else {
-            arg = 0;
-            tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
-        }
-        tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
-        tcg_out32 (s, (RLWINM
-                       | RA (arg0)
-                       | RS (0)
-                       | SH (27)
-                       | MB (5)
-                       | ME (31)
-                       )
-            );
-        break;
+    assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
 
-    case TCG_COND_NE:
-        if (const_arg2) {
-            if (!arg2) {
-                arg = arg1;
+    /* Ignore high bits of a potential constant arg2.  */
+    if (type == TCG_TYPE_I32) {
+        arg2 = (uint32_t)arg2;
+    }
+
+    /* Handle common and trivial cases before handling anything else.  */
+    if (arg2 == 0) {
+        switch (cond) {
+        case TCG_COND_EQ:
+            tcg_out_setcond_eq0(s, type, arg0, arg1);
+            return;
+        case TCG_COND_NE:
+            if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
+                tcg_out_ext32u(s, TCG_REG_R0, arg1);
+                arg1 = TCG_REG_R0;
             }
-            else {
-                arg = 0;
-                if ((uint16_t) arg2 == arg2) {
-                    tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
-                }
-                else {
-                    tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
-                    tcg_out32 (s, XOR | SAB (arg1, 0, 0));
-                }
+            tcg_out_setcond_ne0(s, arg0, arg1);
+            return;
+        case TCG_COND_GE:
+            tcg_out32(s, NOR | SAB(arg1, arg0, arg1));
+            arg1 = arg0;
+            /* FALLTHRU */
+        case TCG_COND_LT:
+            /* Extract the sign bit.  */
+            if (type == TCG_TYPE_I32) {
+                tcg_out_shri32(s, arg0, arg1, 31);
+            } else {
+                tcg_out_shri64(s, arg0, arg1, 63);
             }
+            return;
+        default:
+            break;
         }
-        else {
-            arg = 0;
-            tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
-        }
+    }
+
+    /* If we have ISEL, we can implement everything with 3 or 4 insns.
+       All other cases below are also at least 3 insns, so speed up the
+       code generator by not considering them and always using ISEL.  */
+    if (HAVE_ISEL) {
+        int isel, tab;
+
+        tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
 
-        if (arg == arg1 && arg1 == arg0) {
-            tcg_out32 (s, ADDIC | RT (0) | RA (arg) | 0xffff);
-            tcg_out32 (s, SUBFE | TAB (arg0, 0, arg));
+        isel = tcg_to_isel[cond];
+
+        tcg_out_movi(s, type, arg0, 1);
+        if (isel & 1) {
+            /* arg0 = (bc ? 0 : 1) */
+            tab = TAB(arg0, 0, arg0);
+            isel &= ~1;
+        } else {
+            /* arg0 = (bc ? 1 : 0) */
+            tcg_out_movi(s, type, TCG_REG_R0, 0);
+            tab = TAB(arg0, arg0, TCG_REG_R0);
         }
-        else {
-            tcg_out32 (s, ADDIC | RT (arg0) | RA (arg) | 0xffff);
-            tcg_out32 (s, SUBFE | TAB (arg0, arg0, arg));
+        tcg_out32(s, isel | tab);
+        return;
+    }
+
+    switch (cond) {
+    case TCG_COND_EQ:
+        arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
+        tcg_out_setcond_eq0(s, type, arg0, arg1);
+        return;
+
+    case TCG_COND_NE:
+        arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
+        /* Discard the high bits only once, rather than both inputs.  */
+        if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
+            tcg_out_ext32u(s, TCG_REG_R0, arg1);
+            arg1 = TCG_REG_R0;
         }
-        break;
+        tcg_out_setcond_ne0(s, arg0, arg1);
+        return;
 
     case TCG_COND_GT:
     case TCG_COND_GTU:
@@ -1194,176 +1076,788 @@ static void tcg_out_setcond (TCGContext *s, TCGCond cond, TCGArg arg0,
     case TCG_COND_GE:
     case TCG_COND_GEU:
         sh = 31;
-        crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
+        crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT);
         goto crtest;
 
     case TCG_COND_LE:
     case TCG_COND_LEU:
         sh = 31;
-        crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
+        crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
     crtest:
-        tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
-        if (crop) tcg_out32 (s, crop);
-        tcg_out32 (s, MFCR | RT (0));
-        tcg_out32 (s, (RLWINM
-                       | RA (arg0)
-                       | RS (0)
-                       | SH (sh)
-                       | MB (31)
-                       | ME (31)
-                       )
-            );
+        tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+        if (crop) {
+            tcg_out32(s, crop);
+        }
+        tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
+        tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31);
         break;
 
     default:
-        tcg_abort ();
+        tcg_abort();
     }
 }
 
-static void tcg_out_setcond2 (TCGContext *s, const TCGArg *args,
-                              const int *const_args)
+static void tcg_out_bc(TCGContext *s, int bc, int label_index)
 {
-    tcg_out_cr7eq_from_cond (s, args + 1, const_args + 1);
-    tcg_out32 (s, MFCR | RT (0));
-    tcg_out32 (s, (RLWINM
-                   | RA (args[0])
-                   | RS (0)
-                   | SH (31)
-                   | MB (31)
-                   | ME (31)
-                   )
-        );
+    TCGLabel *l = &s->labels[label_index];
+
+    if (l->has_value) {
+        tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
+    } else {
+        tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
+        tcg_out_bc_noaddr(s, bc);
+    }
 }
 
-static void tcg_out_movcond (TCGContext *s, TCGCond cond,
-                             TCGArg dest,
-                             TCGArg c1, TCGArg c2,
-                             TCGArg v1, TCGArg v2,
-                             int const_c2)
+static void tcg_out_brcond(TCGContext *s, TCGCond cond,
+                           TCGArg arg1, TCGArg arg2, int const_arg2,
+                           int label_index, TCGType type)
 {
-    tcg_out_cmp (s, cond, c1, c2, const_c2, 7);
+    tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+    tcg_out_bc(s, tcg_to_bc[cond], label_index);
+}
+
+static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
+                            TCGArg dest, TCGArg c1, TCGArg c2, TCGArg v1,
+                            TCGArg v2, bool const_c2)
+{
+    /* If for some reason both inputs are zero, don't produce bad code.  */
+    if (v1 == 0 && v2 == 0) {
+        tcg_out_movi(s, type, dest, 0);
+        return;
+    }
+
+    tcg_out_cmp(s, cond, c1, c2, const_c2, 7, type);
+
+    if (HAVE_ISEL) {
+        int isel = tcg_to_isel[cond];
 
-    if (1) {
-        /* At least here on 7747A bit twiddling hacks are outperformed
-           by jumpy code (the testing was not scientific) */
+        /* Swap the V operands if the operation indicates inversion.  */
+        if (isel & 1) {
+            int t = v1;
+            v1 = v2;
+            v2 = t;
+            isel &= ~1;
+        }
+        /* V1 == 0 is handled by isel; V2 == 0 must be handled by hand.  */
+        if (v2 == 0) {
+            tcg_out_movi(s, type, TCG_REG_R0, 0);
+        }
+        tcg_out32(s, isel | TAB(dest, v1, v2));
+    } else {
         if (dest == v2) {
-            cond = tcg_invert_cond (cond);
+            cond = tcg_invert_cond(cond);
             v2 = v1;
-        }
-        else {
-            if (dest != v1) {
-                tcg_out_mov (s, TCG_TYPE_I32, dest, v1);
+        } else if (dest != v1) {
+            if (v1 == 0) {
+                tcg_out_movi(s, type, dest, 0);
+            } else {
+                tcg_out_mov(s, type, dest, v1);
             }
         }
         /* Branch forward over one insn */
-        tcg_out32 (s, tcg_to_bc[cond] | 8);
-        tcg_out_mov (s, TCG_TYPE_I32, dest, v2);
+        tcg_out32(s, tcg_to_bc[cond] | 8);
+        if (v2 == 0) {
+            tcg_out_movi(s, type, dest, 0);
+        } else {
+            tcg_out_mov(s, type, dest, v2);
+        }
     }
-    else {
-        /* isel version, "if (1)" above should be replaced once a way
-           to figure out availability of isel on the underlying
-           hardware is found */
-        int tab, bc;
+}
 
-        switch (cond) {
-        case TCG_COND_EQ:
-            tab = TAB (dest, v1, v2);
-            bc = CR_EQ;
-            break;
-        case TCG_COND_NE:
-            tab = TAB (dest, v2, v1);
-            bc = CR_EQ;
-            break;
-        case TCG_COND_LTU:
-        case TCG_COND_LT:
-            tab = TAB (dest, v1, v2);
-            bc = CR_LT;
-            break;
-        case TCG_COND_GEU:
-        case TCG_COND_GE:
-            tab = TAB (dest, v2, v1);
-            bc = CR_LT;
-            break;
-        case TCG_COND_LEU:
-        case TCG_COND_LE:
-            tab = TAB (dest, v2, v1);
-            bc = CR_GT;
-            break;
-        case TCG_COND_GTU:
-        case TCG_COND_GT:
-            tab = TAB (dest, v1, v2);
-            bc = CR_GT;
-            break;
-        default:
-            tcg_abort ();
-        }
-        tcg_out32 (s, ISEL | tab | ((bc + 28) << 6));
+static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
+                         const int *const_args)
+{
+    static const struct { uint8_t bit1, bit2; } bits[] = {
+        [TCG_COND_LT ] = { CR_LT, CR_LT },
+        [TCG_COND_LE ] = { CR_LT, CR_GT },
+        [TCG_COND_GT ] = { CR_GT, CR_GT },
+        [TCG_COND_GE ] = { CR_GT, CR_LT },
+        [TCG_COND_LTU] = { CR_LT, CR_LT },
+        [TCG_COND_LEU] = { CR_LT, CR_GT },
+        [TCG_COND_GTU] = { CR_GT, CR_GT },
+        [TCG_COND_GEU] = { CR_GT, CR_LT },
+    };
+
+    TCGCond cond = args[4], cond2;
+    TCGArg al, ah, bl, bh;
+    int blconst, bhconst;
+    int op, bit1, bit2;
+
+    al = args[0];
+    ah = args[1];
+    bl = args[2];
+    bh = args[3];
+    blconst = const_args[2];
+    bhconst = const_args[3];
+
+    switch (cond) {
+    case TCG_COND_EQ:
+        op = CRAND;
+        goto do_equality;
+    case TCG_COND_NE:
+        op = CRNAND;
+    do_equality:
+        tcg_out_cmp(s, cond, al, bl, blconst, 6, TCG_TYPE_I32);
+        tcg_out_cmp(s, cond, ah, bh, bhconst, 7, TCG_TYPE_I32);
+        tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+        break;
+
+    case TCG_COND_LT:
+    case TCG_COND_LE:
+    case TCG_COND_GT:
+    case TCG_COND_GE:
+    case TCG_COND_LTU:
+    case TCG_COND_LEU:
+    case TCG_COND_GTU:
+    case TCG_COND_GEU:
+        bit1 = bits[cond].bit1;
+        bit2 = bits[cond].bit2;
+        op = (bit1 != bit2 ? CRANDC : CRAND);
+        cond2 = tcg_unsigned_cond(cond);
+
+        tcg_out_cmp(s, cond, ah, bh, bhconst, 6, TCG_TYPE_I32);
+        tcg_out_cmp(s, cond2, al, bl, blconst, 7, TCG_TYPE_I32);
+        tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, bit2));
+        tcg_out32(s, CROR | BT(7, CR_EQ) | BA(6, bit1) | BB(7, CR_EQ));
+        break;
+
+    default:
+        tcg_abort();
     }
 }
 
-static void tcg_out_brcond (TCGContext *s, TCGCond cond,
-                            TCGArg arg1, TCGArg arg2, int const_arg2,
-                            int label_index)
+static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
+                             const int *const_args)
 {
-    tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
-    tcg_out_bc (s, tcg_to_bc[cond], label_index);
+    tcg_out_cmp2(s, args + 1, const_args + 1);
+    tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
+    tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, 31, 31, 31);
 }
 
-/* XXX: we implement it at the target level to avoid having to
-   handle cross basic blocks temporaries */
 static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
                              const int *const_args)
 {
-    tcg_out_cr7eq_from_cond (s, args, const_args);
-    tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), args[5]);
+    tcg_out_cmp2(s, args, const_args);
+    tcg_out_bc(s, BC | BI(7, CR_EQ) | BO_COND_TRUE, args[5]);
+}
+
+void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
+{
+    TCGContext s;
+
+    s.code_buf = s.code_ptr = (tcg_insn_unit *)jmp_addr;
+    tcg_out_b(&s, 0, (tcg_insn_unit *)addr);
+    flush_icache_range(jmp_addr, jmp_addr + tcg_current_code_size(&s));
+}
+
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
+{
+#ifdef _CALL_AIX
+    /* Look through the descriptor.  If the branch is in range, and we
+       don't have to spend too much effort on building the toc.  */
+    void *tgt = ((void **)target)[0];
+    uintptr_t toc = ((uintptr_t *)target)[1];
+    intptr_t diff = tcg_pcrel_diff(s, tgt);
+
+    if (in_range_b(diff) && toc == (uint32_t)toc) {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, toc);
+        tcg_out_b(s, LK, tgt);
+    } else {
+        /* Fold the low bits of the constant into the addresses below.  */
+        intptr_t arg = (intptr_t)target;
+        int ofs = (int16_t)arg;
+
+        if (ofs + 8 < 0x8000) {
+            arg -= ofs;
+        } else {
+            ofs = 0;
+        }
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, arg);
+        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_TMP1, ofs);
+        tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
+        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_TMP1, ofs + SZP);
+        tcg_out32(s, BCCTR | BO_ALWAYS | LK);
+    }
+#elif defined(_CALL_ELF) && _CALL_ELF == 2
+    intptr_t diff;
+
+    /* In the ELFv2 ABI, we have to set up r12 to contain the destination
+       address, which the callee uses to compute its TOC address.  */
+    /* FIXME: when the branch is in range, we could avoid r12 load if we
+       knew that the destination uses the same TOC, and what its local
+       entry point offset is.  */
+    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R12, (intptr_t)target);
+
+    diff = tcg_pcrel_diff(s, target);
+    if (in_range_b(diff)) {
+        tcg_out_b(s, LK, target);
+    } else {
+        tcg_out32(s, MTSPR | RS(TCG_REG_R12) | CTR);
+        tcg_out32(s, BCCTR | BO_ALWAYS | LK);
+    }
+#else
+    tcg_out_b(s, LK, target);
+#endif
+}
+
+static const uint32_t qemu_ldx_opc[16] = {
+    [MO_UB] = LBZX,
+    [MO_UW] = LHZX,
+    [MO_UL] = LWZX,
+    [MO_Q]  = LDX,
+    [MO_SW] = LHAX,
+    [MO_SL] = LWAX,
+    [MO_BSWAP | MO_UB] = LBZX,
+    [MO_BSWAP | MO_UW] = LHBRX,
+    [MO_BSWAP | MO_UL] = LWBRX,
+    [MO_BSWAP | MO_Q]  = LDBRX,
+};
+
+static const uint32_t qemu_stx_opc[16] = {
+    [MO_UB] = STBX,
+    [MO_UW] = STHX,
+    [MO_UL] = STWX,
+    [MO_Q]  = STDX,
+    [MO_BSWAP | MO_UB] = STBX,
+    [MO_BSWAP | MO_UW] = STHBRX,
+    [MO_BSWAP | MO_UL] = STWBRX,
+    [MO_BSWAP | MO_Q]  = STDBRX,
+};
+
+static const uint32_t qemu_exts_opc[4] = {
+    EXTSB, EXTSH, EXTSW, 0
+};
+
+#if defined (CONFIG_SOFTMMU)
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+ *                                 int mmu_idx, uintptr_t ra)
+ */
+static void * const qemu_ld_helpers[16] = {
+    [MO_UB]   = helper_ret_ldub_mmu,
+    [MO_LEUW] = helper_le_lduw_mmu,
+    [MO_LEUL] = helper_le_ldul_mmu,
+    [MO_LEQ]  = helper_le_ldq_mmu,
+    [MO_BEUW] = helper_be_lduw_mmu,
+    [MO_BEUL] = helper_be_ldul_mmu,
+    [MO_BEQ]  = helper_be_ldq_mmu,
+};
+
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+ *                                 uintxx_t val, int mmu_idx, uintptr_t ra)
+ */
+static void * const qemu_st_helpers[16] = {
+    [MO_UB]   = helper_ret_stb_mmu,
+    [MO_LEUW] = helper_le_stw_mmu,
+    [MO_LEUL] = helper_le_stl_mmu,
+    [MO_LEQ]  = helper_le_stq_mmu,
+    [MO_BEUW] = helper_be_stw_mmu,
+    [MO_BEUL] = helper_be_stl_mmu,
+    [MO_BEQ]  = helper_be_stq_mmu,
+};
+
+/* Perform the TLB load and compare.  Places the result of the comparison
+   in CR7, loads the addend of the TLB into R3, and returns the register
+   containing the guest address (zero-extended into R4).  Clobbers R0 and R2. */
+
+static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits,
+                               TCGReg addrlo, TCGReg addrhi,
+                               int mem_index, bool is_read)
+{
+    int cmp_off
+        = (is_read
+           ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
+           : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
+    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
+    TCGReg base = TCG_AREG0;
+
+    /* Extract the page index, shifted into place for tlb index.  */
+    if (TCG_TARGET_REG_BITS == 64) {
+        if (TARGET_LONG_BITS == 32) {
+            /* Zero-extend the address into a place helpful for further use. */
+            tcg_out_ext32u(s, TCG_REG_R4, addrlo);
+            addrlo = TCG_REG_R4;
+        } else {
+            tcg_out_rld(s, RLDICL, TCG_REG_R3, addrlo,
+                        64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
+        }
+    }
+
+    /* Compensate for very large offsets.  */
+    if (add_off >= 0x8000) {
+        /* Most target env are smaller than 32k; none are larger than 64k.
+           Simplify the logic here merely to offset by 0x7ff0, giving us a
+           range just shy of 64k.  Check this assumption.  */
+        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
+                                   tlb_table[NB_MMU_MODES - 1][1])
+                          > 0x7ff0 + 0x7fff);
+        tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, base, 0x7ff0));
+        base = TCG_REG_TMP1;
+        cmp_off -= 0x7ff0;
+        add_off -= 0x7ff0;
+    }
+
+    /* Extraction and shifting, part 2.  */
+    if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) {
+        tcg_out_rlw(s, RLWINM, TCG_REG_R3, addrlo,
+                    32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
+                    32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
+                    31 - CPU_TLB_ENTRY_BITS);
+    } else {
+        tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS);
+    }
+
+    tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
+
+    /* Load the tlb comparator.  */
+    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+        tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R4, TCG_REG_R3, cmp_off);
+        tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP1, TCG_REG_R3, cmp_off + 4);
+    } else {
+        tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP1, TCG_REG_R3, cmp_off);
+    }
+
+    /* Load the TLB addend for use on the fast path.  Do this asap
+       to minimize any load use delay.  */
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_REG_R3, add_off);
+
+    /* Clear the non-page, non-alignment bits from the address.  */
+    if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) {
+        tcg_out_rlw(s, RLWINM, TCG_REG_R0, addrlo, 0,
+                    (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
+    } else if (!s_bits) {
+        tcg_out_rld(s, RLDICR, TCG_REG_R0, addrlo,
+                    0, 63 - TARGET_PAGE_BITS);
+    } else {
+        tcg_out_rld(s, RLDICL, TCG_REG_R0, addrlo,
+                    64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
+        tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
+    }
+
+    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+        tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,
+                    0, 7, TCG_TYPE_I32);
+        tcg_out_cmp(s, TCG_COND_EQ, addrhi, TCG_REG_R4, 0, 6, TCG_TYPE_I32);
+        tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+    } else {
+        tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,
+                    0, 7, TCG_TYPE_TL);
+    }
+
+    return addrlo;
+}
+
+/* Record the context of a call to the out of line helper code for the slow
+   path for a load or store, so that we can later generate the correct
+   helper code.  */
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
+                                TCGReg datalo_reg, TCGReg datahi_reg,
+                                TCGReg addrlo_reg, TCGReg addrhi_reg,
+                                int mem_index, tcg_insn_unit *raddr,
+                                tcg_insn_unit *lptr)
+{
+    TCGLabelQemuLdst *label = new_ldst_label(s);
+
+    label->is_ld = is_ld;
+    label->opc = opc;
+    label->datalo_reg = datalo_reg;
+    label->datahi_reg = datahi_reg;
+    label->addrlo_reg = addrlo_reg;
+    label->addrhi_reg = addrhi_reg;
+    label->mem_index = mem_index;
+    label->raddr = raddr;
+    label->label_ptr[0] = lptr;
+}
+
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+    TCGMemOp opc = lb->opc;
+    TCGReg hi, lo, arg = TCG_REG_R3;
+
+    reloc_pc14(lb->label_ptr[0], s->code_ptr);
+
+    tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
+
+    lo = lb->addrlo_reg;
+    hi = lb->addrhi_reg;
+    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+#ifdef TCG_TARGET_CALL_ALIGN_ARGS
+        arg |= 1;
+#endif
+        tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
+        tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
+    } else {
+        /* If the address needed to be zero-extended, we'll have already
+           placed it in R4.  The only remaining case is 64-bit guest.  */
+        tcg_out_mov(s, TCG_TYPE_TL, arg++, lo);
+    }
+
+    tcg_out_movi(s, TCG_TYPE_I32, arg++, lb->mem_index);
+    tcg_out32(s, MFSPR | RT(arg) | LR);
+
+    tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
+
+    lo = lb->datalo_reg;
+    hi = lb->datahi_reg;
+    if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
+        tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_REG_R4);
+        tcg_out_mov(s, TCG_TYPE_I32, hi, TCG_REG_R3);
+    } else if (opc & MO_SIGN) {
+        uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
+        tcg_out32(s, insn | RA(lo) | RS(TCG_REG_R3));
+    } else {
+        tcg_out_mov(s, TCG_TYPE_REG, lo, TCG_REG_R3);
+    }
+
+    tcg_out_b(s, 0, lb->raddr);
+}
+
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+    TCGMemOp opc = lb->opc;
+    TCGMemOp s_bits = opc & MO_SIZE;
+    TCGReg hi, lo, arg = TCG_REG_R3;
+
+    reloc_pc14(lb->label_ptr[0], s->code_ptr);
+
+    tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
+
+    lo = lb->addrlo_reg;
+    hi = lb->addrhi_reg;
+    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
+#ifdef TCG_TARGET_CALL_ALIGN_ARGS
+        arg |= 1;
+#endif
+        tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
+        tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
+    } else {
+        /* If the address needed to be zero-extended, we'll have already
+           placed it in R4.  The only remaining case is 64-bit guest.  */
+        tcg_out_mov(s, TCG_TYPE_TL, arg++, lo);
+    }
+
+    lo = lb->datalo_reg;
+    hi = lb->datahi_reg;
+    if (TCG_TARGET_REG_BITS == 32) {
+        switch (s_bits) {
+        case MO_64:
+#ifdef TCG_TARGET_CALL_ALIGN_ARGS
+            arg |= 1;
+#endif
+            tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
+            /* FALLTHRU */
+        case MO_32:
+            tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
+            break;
+        default:
+            tcg_out_rlw(s, RLWINM, arg++, lo, 0, 32 - (8 << s_bits), 31);
+            break;
+        }
+    } else {
+        if (s_bits == MO_64) {
+            tcg_out_mov(s, TCG_TYPE_I64, arg++, lo);
+        } else {
+            tcg_out_rld(s, RLDICL, arg++, lo, 0, 64 - (8 << s_bits));
+        }
+    }
+
+    tcg_out_movi(s, TCG_TYPE_I32, arg++, lb->mem_index);
+    tcg_out32(s, MFSPR | RT(arg) | LR);
+
+    tcg_out_call(s, qemu_st_helpers[opc]);
+
+    tcg_out_b(s, 0, lb->raddr);
+}
+#endif /* SOFTMMU */
+
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
+{
+    TCGReg datalo, datahi, addrlo, rbase;
+    TCGReg addrhi __attribute__((unused));
+    TCGMemOp opc, s_bits;
+#ifdef CONFIG_SOFTMMU
+    int mem_index;
+    tcg_insn_unit *label_ptr;
+#endif
+
+    datalo = *args++;
+    datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
+    addrlo = *args++;
+    addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
+    opc = *args++;
+    s_bits = opc & MO_SIZE;
+
+#ifdef CONFIG_SOFTMMU
+    mem_index = *args;
+    addrlo = tcg_out_tlb_read(s, s_bits, addrlo, addrhi, mem_index, true);
+
+    /* Load a pointer into the current opcode w/conditional branch-link. */
+    label_ptr = s->code_ptr;
+    tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
+
+    rbase = TCG_REG_R3;
+#else  /* !CONFIG_SOFTMMU */
+    rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
+    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
+        tcg_out_ext32u(s, TCG_REG_TMP1, addrlo);
+        addrlo = TCG_REG_TMP1;
+    }
+#endif
+
+    if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
+        if (opc & MO_BSWAP) {
+            tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+            tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
+            tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0));
+        } else if (rbase != 0) {
+            tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+            tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo));
+            tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0));
+        } else if (addrlo == datahi) {
+            tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
+            tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
+        } else {
+            tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
+            tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
+        }
+    } else {
+        uint32_t insn = qemu_ldx_opc[opc];
+        if (!HAVE_ISA_2_06 && insn == LDBRX) {
+            tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+            tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
+            tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
+            tcg_out_rld(s, RLDIMI, datalo, TCG_REG_R0, 32, 0);
+        } else if (insn) {
+            tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
+        } else {
+            insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
+            tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
+            insn = qemu_exts_opc[s_bits];
+            tcg_out32(s, insn | RA(datalo) | RS(datalo));
+        }
+    }
+
+#ifdef CONFIG_SOFTMMU
+    add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo, addrhi,
+                        mem_index, s->code_ptr, label_ptr);
+#endif
 }
 
-void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
 {
-    uint32_t *ptr;
-    long disp = addr - jmp_addr;
-    unsigned long patch_size;
-
-    ptr = (uint32_t *)jmp_addr;
-
-    if ((disp << 6) >> 6 != disp) {
-        ptr[0] = 0x3c000000 | (addr >> 16);    /* lis 0,addr@ha */
-        ptr[1] = 0x60000000 | (addr & 0xffff); /* la  0,addr@l(0) */
-        ptr[2] = 0x7c0903a6;                   /* mtctr 0 */
-        ptr[3] = 0x4e800420;                   /* brctr */
-        patch_size = 16;
+    TCGReg datalo, datahi, addrlo, rbase;
+    TCGReg addrhi __attribute__((unused));
+    TCGMemOp opc, s_bits;
+#ifdef CONFIG_SOFTMMU
+    int mem_index;
+    tcg_insn_unit *label_ptr;
+#endif
+
+    datalo = *args++;
+    datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
+    addrlo = *args++;
+    addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
+    opc = *args++;
+    s_bits = opc & MO_SIZE;
+
+#ifdef CONFIG_SOFTMMU
+    mem_index = *args;
+    addrlo = tcg_out_tlb_read(s, s_bits, addrlo, addrhi, mem_index, false);
+
+    /* Load a pointer into the current opcode w/conditional branch-link. */
+    label_ptr = s->code_ptr;
+    tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
+
+    rbase = TCG_REG_R3;
+#else  /* !CONFIG_SOFTMMU */
+    rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
+    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
+        tcg_out_ext32u(s, TCG_REG_TMP1, addrlo);
+        addrlo = TCG_REG_TMP1;
+    }
+#endif
+
+    if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
+        if (opc & MO_BSWAP) {
+            tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+            tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
+            tcg_out32(s, STWBRX | SAB(datahi, rbase, TCG_REG_R0));
+        } else if (rbase != 0) {
+            tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
+            tcg_out32(s, STWX | SAB(datahi, rbase, addrlo));
+            tcg_out32(s, STWX | SAB(datalo, rbase, TCG_REG_R0));
+        } else {
+            tcg_out32(s, STW | TAI(datahi, addrlo, 0));
+            tcg_out32(s, STW | TAI(datalo, addrlo, 4));
+        }
     } else {
-        /* patch the branch destination */
-        if (disp != 16) {
-            *ptr = 0x48000000 | (disp & 0x03fffffc); /* b disp */
-            patch_size = 4;
+        uint32_t insn = qemu_stx_opc[opc];
+        if (!HAVE_ISA_2_06 && insn == STDBRX) {
+            tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
+            tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, addrlo, 4));
+            tcg_out_shri64(s, TCG_REG_R0, datalo, 32);
+            tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_TMP1));
         } else {
-            ptr[0] = 0x60000000; /* nop */
-            ptr[1] = 0x60000000;
-            ptr[2] = 0x60000000;
-            ptr[3] = 0x60000000;
-            patch_size = 16;
+            tcg_out32(s, insn | SAB(datalo, rbase, addrlo));
         }
     }
-    /* flush icache */
-    flush_icache_range(jmp_addr, jmp_addr + patch_size);
+
+#ifdef CONFIG_SOFTMMU
+    add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
+                        mem_index, s->code_ptr, label_ptr);
+#endif
+}
+
+/* Parameters for function call generation, used in tcg.c.  */
+#define TCG_TARGET_STACK_ALIGN       16
+#define TCG_TARGET_EXTEND_ARGS       1
+
+#ifdef _CALL_AIX
+# define LINK_AREA_SIZE                (6 * SZR)
+# define LR_OFFSET                     (1 * SZR)
+# define TCG_TARGET_CALL_STACK_OFFSET  (LINK_AREA_SIZE + 8 * SZR)
+#elif TCG_TARGET_REG_BITS == 64
+# if defined(_CALL_ELF) && _CALL_ELF == 2
+#  define LINK_AREA_SIZE               (4 * SZR)
+#  define LR_OFFSET                    (1 * SZR)
+# endif
+#else /* TCG_TARGET_REG_BITS == 32 */
+# if defined(_CALL_SYSV)
+#  define LINK_AREA_SIZE               (2 * SZR)
+#  define LR_OFFSET                    (1 * SZR)
+# elif defined(TCG_TARGET_CALL_DARWIN)
+#  define LINK_AREA_SIZE               24
+#  define LR_OFFSET                    8
+# endif
+#endif
+#ifndef LR_OFFSET
+# error "Unhandled abi"
+#endif
+#ifndef TCG_TARGET_CALL_STACK_OFFSET
+# define TCG_TARGET_CALL_STACK_OFFSET  LINK_AREA_SIZE
+#endif
+
+#define CPU_TEMP_BUF_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
+#define REG_SAVE_SIZE      ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * SZR)
+
+#define FRAME_SIZE ((TCG_TARGET_CALL_STACK_OFFSET   \
+                     + TCG_STATIC_CALL_ARGS_SIZE    \
+                     + CPU_TEMP_BUF_SIZE            \
+                     + REG_SAVE_SIZE                \
+                     + TCG_TARGET_STACK_ALIGN - 1)  \
+                    & -TCG_TARGET_STACK_ALIGN)
+
+#define REG_SAVE_BOT (FRAME_SIZE - REG_SAVE_SIZE)
+
+static void tcg_target_qemu_prologue(TCGContext *s)
+{
+    int i;
+
+#ifdef _CALL_AIX
+    void **desc = (void **)s->code_ptr;
+    desc[0] = desc + 2;                   /* entry point */
+    desc[1] = 0;                          /* environment pointer */
+    s->code_ptr = (void *)(desc + 2);     /* skip over descriptor */
+#endif
+
+    tcg_set_frame(s, TCG_REG_CALL_STACK, REG_SAVE_BOT - CPU_TEMP_BUF_SIZE,
+                  CPU_TEMP_BUF_SIZE);
+
+    /* Prologue */
+    tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
+    tcg_out32(s, (SZR == 8 ? STDU : STWU)
+              | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
+
+    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
+        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+                   TCG_REG_R1, REG_SAVE_BOT + i * SZR);
+    }
+    tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
+
+#ifdef CONFIG_USE_GUEST_BASE
+    if (GUEST_BASE) {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
+        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+    }
+#endif
+
+    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+    tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
+
+    if (USE_REG_RA) {
+#ifdef _CALL_AIX
+        /* Make the caller load the value as the TOC into R2.  */
+        tb_ret_addr = s->code_ptr + 2;
+        desc[1] = tb_ret_addr;
+        tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_RA, TCG_REG_R2);
+        tcg_out32(s, BCCTR | BO_ALWAYS);
+#elif defined(_CALL_ELF) && _CALL_ELF == 2
+        /* Compute from the incoming R12 value.  */
+        tb_ret_addr = s->code_ptr + 2;
+        tcg_out32(s, ADDI | TAI(TCG_REG_RA, TCG_REG_R12,
+                                tcg_ptr_byte_diff(tb_ret_addr, s->code_buf)));
+        tcg_out32(s, BCCTR | BO_ALWAYS);
+#else
+        /* Reserve max 5 insns for the constant load.  */
+        tb_ret_addr = s->code_ptr + 6;
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)tb_ret_addr);
+        tcg_out32(s, BCCTR | BO_ALWAYS);
+        while (s->code_ptr < tb_ret_addr) {
+            tcg_out32(s, NOP);
+        }
+#endif
+    } else {
+        tcg_out32(s, BCCTR | BO_ALWAYS);
+        tb_ret_addr = s->code_ptr;
+    }
+
+    /* Epilogue */
+    assert(tb_ret_addr == s->code_ptr);
+
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
+    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
+        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+                   TCG_REG_R1, REG_SAVE_BOT + i * SZR);
+    }
+    tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
+    tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
+    tcg_out32(s, BCLR | BO_ALWAYS);
 }
 
 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                        const int *const_args)
 {
+    TCGArg a0, a1, a2;
+    int c;
+
     switch (opc) {
     case INDEX_op_exit_tb:
-        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
+        if (USE_REG_RA) {
+            ptrdiff_t disp = tcg_pcrel_diff(s, tb_ret_addr);
+
+            /* If we can use a direct branch, otherwise use the value in RA.
+               Note that the direct branch is always forward.  If it's in
+               range now, it'll still be in range after the movi.  Don't
+               bother about the 20 bytes where the test here fails but it
+               would succeed below.  */
+            if (!in_range_b(disp)) {
+                tcg_out32(s, MTSPR | RS(TCG_REG_RA) | CTR);
+                tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]);
+                tcg_out32(s, BCCTR | BO_ALWAYS);
+                break;
+            }
+        }
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]);
         tcg_out_b(s, 0, tb_ret_addr);
         break;
     case INDEX_op_goto_tb:
         if (s->tb_jmp_offset) {
-            /* direct jump method */
+            /* Direct jump method.  */
             s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
-            s->code_ptr += 4;
+            s->code_ptr += 7;
         } else {
-            tcg_abort ();
+            /* Indirect jump method.  */
+            tcg_abort();
         }
         s->tb_next_offset[args[0]] = tcg_current_code_size(s);
         break;
@@ -1374,451 +1868,519 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
             if (l->has_value) {
                 tcg_out_b(s, 0, l->u.value_ptr);
             } else {
-                /* Thanks to Andrzej Zaborowski */
-                tcg_insn_unit retrans = *s->code_ptr & 0x3fffffc;
                 tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, args[0], 0);
-                tcg_out32(s, B | retrans);
+                tcg_out_b_noaddr(s, B);
             }
         }
         break;
     case INDEX_op_ld8u_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
+    case INDEX_op_ld8u_i64:
+        tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld8s_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
-        tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
+    case INDEX_op_ld8s_i64:
+        tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
+        tcg_out32(s, EXTSB | RS(args[0]) | RA(args[0]));
         break;
     case INDEX_op_ld16u_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
+    case INDEX_op_ld16u_i64:
+        tcg_out_mem_long(s, LHZ, LHZX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld16s_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
+    case INDEX_op_ld16s_i64:
+        tcg_out_mem_long(s, LHA, LHAX, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
+    case INDEX_op_ld32u_i64:
+        tcg_out_mem_long(s, LWZ, LWZX, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_ld32s_i64:
+        tcg_out_mem_long(s, LWA, LWAX, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_ld_i64:
+        tcg_out_mem_long(s, LD, LDX, args[0], args[1], args[2]);
         break;
     case INDEX_op_st8_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
+    case INDEX_op_st8_i64:
+        tcg_out_mem_long(s, STB, STBX, args[0], args[1], args[2]);
         break;
     case INDEX_op_st16_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
+    case INDEX_op_st16_i64:
+        tcg_out_mem_long(s, STH, STHX, args[0], args[1], args[2]);
         break;
     case INDEX_op_st_i32:
-        tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
+    case INDEX_op_st32_i64:
+        tcg_out_mem_long(s, STW, STWX, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_st_i64:
+        tcg_out_mem_long(s, STD, STDX, args[0], args[1], args[2]);
         break;
 
     case INDEX_op_add_i32:
-        if (const_args[2])
-            ppc_addi (s, args[0], args[1], args[2]);
-        else
-            tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[2]) {
+        do_addi_32:
+            tcg_out_mem_long(s, ADDI, ADD, a0, a1, (int32_t)a2);
+        } else {
+            tcg_out32(s, ADD | TAB(a0, a1, a2));
+        }
         break;
     case INDEX_op_sub_i32:
-        if (const_args[2])
-            ppc_addi (s, args[0], args[1], -args[2]);
-        else
-            tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[1]) {
+            if (const_args[2]) {
+                tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2);
+            } else {
+                tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
+            }
+        } else if (const_args[2]) {
+            a2 = -a2;
+            goto do_addi_32;
+        } else {
+            tcg_out32(s, SUBF | TAB(a0, a2, a1));
+        }
         break;
 
     case INDEX_op_and_i32:
+        a0 = args[0], a1 = args[1], a2 = args[2];
         if (const_args[2]) {
-            uint32_t c;
-
-            c = args[2];
-
-            if (!c) {
-                tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
-                break;
-            }
-#ifdef __PPU__
-            uint32_t t, n;
-            int mb, me;
-
-            n = c ^ -(c & 1);
-            t = n + (n & -n);
-
-            if ((t & (t - 1)) == 0) {
-                int lzc, tzc;
-
-                if ((c & 0x80000001) == 0x80000001) {
-                    lzc = clz32 (n);
-                    tzc = ctz32 (n);
-
-                    mb = 32 - tzc;
-                    me = lzc - 1;
-                }
-                else {
-                    lzc = clz32 (c);
-                    tzc = ctz32 (c);
-
-                    mb = lzc;
-                    me = 31 - tzc;
-                }
-
-                tcg_out32 (s, (RLWINM
-                               | RA (args[0])
-                               | RS (args[1])
-                               | SH (0)
-                               | MB (mb)
-                               | ME (me)
-                               )
-                    );
-            }
-            else
-#endif /* !__PPU__ */
-            {
-                if ((c & 0xffff) == c)
-                    tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | c);
-                else if ((c & 0xffff0000) == c)
-                    tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
-                               | ((c >> 16) & 0xffff));
-                else {
-                    tcg_out_movi (s, TCG_TYPE_I32, 0, c);
-                    tcg_out32 (s, AND | SAB (args[1], args[0], 0));
-                }
-            }
+            tcg_out_andi32(s, a0, a1, a2);
+        } else {
+            tcg_out32(s, AND | SAB(a1, a0, a2));
         }
-        else
-            tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
         break;
+    case INDEX_op_and_i64:
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[2]) {
+            tcg_out_andi64(s, a0, a1, a2);
+        } else {
+            tcg_out32(s, AND | SAB(a1, a0, a2));
+        }
+        break;
+    case INDEX_op_or_i64:
     case INDEX_op_or_i32:
+        a0 = args[0], a1 = args[1], a2 = args[2];
         if (const_args[2]) {
-            if (args[2] & 0xffff) {
-                tcg_out32 (s, ORI | RS (args[1])  | RA (args[0])
-                           | (args[2] & 0xffff));
-                if (args[2] >> 16)
-                    tcg_out32 (s, ORIS | RS (args[0])  | RA (args[0])
-                               | ((args[2] >> 16) & 0xffff));
-            }
-            else {
-                tcg_out32 (s, ORIS | RS (args[1])  | RA (args[0])
-                           | ((args[2] >> 16) & 0xffff));
-            }
+            tcg_out_ori32(s, a0, a1, a2);
+        } else {
+            tcg_out32(s, OR | SAB(a1, a0, a2));
         }
-        else
-            tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
         break;
+    case INDEX_op_xor_i64:
     case INDEX_op_xor_i32:
+        a0 = args[0], a1 = args[1], a2 = args[2];
         if (const_args[2]) {
-            if ((args[2] & 0xffff) == args[2])
-                tcg_out32 (s, XORI | RS (args[1])  | RA (args[0])
-                           | (args[2] & 0xffff));
-            else if ((args[2] & 0xffff0000) == args[2])
-                tcg_out32 (s, XORIS | RS (args[1])  | RA (args[0])
-                           | ((args[2] >> 16) & 0xffff));
-            else {
-                tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
-                tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
-            }
+            tcg_out_xori32(s, a0, a1, a2);
+        } else {
+            tcg_out32(s, XOR | SAB(a1, a0, a2));
         }
-        else
-            tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
         break;
     case INDEX_op_andc_i32:
-        tcg_out32 (s, ANDC | SAB (args[1], args[0], args[2]));
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[2]) {
+            tcg_out_andi32(s, a0, a1, ~a2);
+        } else {
+            tcg_out32(s, ANDC | SAB(a1, a0, a2));
+        }
+        break;
+    case INDEX_op_andc_i64:
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[2]) {
+            tcg_out_andi64(s, a0, a1, ~a2);
+        } else {
+            tcg_out32(s, ANDC | SAB(a1, a0, a2));
+        }
         break;
     case INDEX_op_orc_i32:
-        tcg_out32 (s, ORC | SAB (args[1], args[0], args[2]));
+        if (const_args[2]) {
+            tcg_out_ori32(s, args[0], args[1], ~args[2]);
+            break;
+        }
+        /* FALLTHRU */
+    case INDEX_op_orc_i64:
+        tcg_out32(s, ORC | SAB(args[1], args[0], args[2]));
         break;
     case INDEX_op_eqv_i32:
-        tcg_out32 (s, EQV | SAB (args[1], args[0], args[2]));
+        if (const_args[2]) {
+            tcg_out_xori32(s, args[0], args[1], ~args[2]);
+            break;
+        }
+        /* FALLTHRU */
+    case INDEX_op_eqv_i64:
+        tcg_out32(s, EQV | SAB(args[1], args[0], args[2]));
         break;
     case INDEX_op_nand_i32:
-        tcg_out32 (s, NAND | SAB (args[1], args[0], args[2]));
+    case INDEX_op_nand_i64:
+        tcg_out32(s, NAND | SAB(args[1], args[0], args[2]));
         break;
     case INDEX_op_nor_i32:
-        tcg_out32 (s, NOR | SAB (args[1], args[0], args[2]));
+    case INDEX_op_nor_i64:
+        tcg_out32(s, NOR | SAB(args[1], args[0], args[2]));
         break;
 
     case INDEX_op_mul_i32:
+        a0 = args[0], a1 = args[1], a2 = args[2];
         if (const_args[2]) {
-            if (args[2] == (int16_t) args[2])
-                tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
-                           | (args[2] & 0xffff));
-            else {
-                tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
-                tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
-            }
+            tcg_out32(s, MULLI | TAI(a0, a1, a2));
+        } else {
+            tcg_out32(s, MULLW | TAB(a0, a1, a2));
         }
-        else
-            tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
         break;
 
     case INDEX_op_div_i32:
-        tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
+        tcg_out32(s, DIVW | TAB(args[0], args[1], args[2]));
         break;
 
     case INDEX_op_divu_i32:
-        tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
-        break;
-
-    case INDEX_op_mulu2_i32:
-        if (args[0] == args[2] || args[0] == args[3]) {
-            tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
-            tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
-            tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
-        }
-        else {
-            tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
-            tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
-        }
+        tcg_out32(s, DIVWU | TAB(args[0], args[1], args[2]));
         break;
 
     case INDEX_op_shl_i32:
         if (const_args[2]) {
-            tcg_out32 (s, (RLWINM
-                           | RA (args[0])
-                           | RS (args[1])
-                           | SH (args[2])
-                           | MB (0)
-                           | ME (31 - args[2])
-                           )
-                );
-        }
-        else
-            tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
+            tcg_out_shli32(s, args[0], args[1], args[2]);
+        } else {
+            tcg_out32(s, SLW | SAB(args[1], args[0], args[2]));
+        }
         break;
     case INDEX_op_shr_i32:
         if (const_args[2]) {
-            tcg_out32 (s, (RLWINM
-                           | RA (args[0])
-                           | RS (args[1])
-                           | SH (32 - args[2])
-                           | MB (args[2])
-                           | ME (31)
-                           )
-                );
-        }
-        else
-            tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
+            tcg_out_shri32(s, args[0], args[1], args[2]);
+        } else {
+            tcg_out32(s, SRW | SAB(args[1], args[0], args[2]));
+        }
         break;
     case INDEX_op_sar_i32:
-        if (const_args[2])
-            tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
-        else
-            tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
+        if (const_args[2]) {
+            tcg_out32(s, SRAWI | RS(args[1]) | RA(args[0]) | SH(args[2]));
+        } else {
+            tcg_out32(s, SRAW | SAB(args[1], args[0], args[2]));
+        }
         break;
     case INDEX_op_rotl_i32:
-        {
-            int op = 0
-                | RA (args[0])
-                | RS (args[1])
-                | MB (0)
-                | ME (31)
-                | (const_args[2] ? RLWINM | SH (args[2])
-                                 : RLWNM | RB (args[2]))
-                ;
-            tcg_out32 (s, op);
+        if (const_args[2]) {
+            tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31);
+        } else {
+            tcg_out32(s, RLWNM | SAB(args[1], args[0], args[2])
+                         | MB(0) | ME(31));
         }
         break;
     case INDEX_op_rotr_i32:
         if (const_args[2]) {
-            if (!args[2]) {
-                tcg_out_mov (s, TCG_TYPE_I32, args[0], args[1]);
-            }
-            else {
-                tcg_out32 (s, RLWINM
-                           | RA (args[0])
-                           | RS (args[1])
-                           | SH (32 - args[2])
-                           | MB (0)
-                           | ME (31)
-                    );
-            }
-        }
-        else {
-            tcg_out32 (s, SUBFIC | RT (0) | RA (args[2]) | 32);
-            tcg_out32 (s, RLWNM
-                       | RA (args[0])
-                       | RS (args[1])
-                       | RB (0)
-                       | MB (0)
-                       | ME (31)
-                );
-        }
-        break;
-
-    case INDEX_op_add2_i32:
-        if (args[0] == args[3] || args[0] == args[5]) {
-            tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
-            tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
-            tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
-        }
-        else {
-            tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
-            tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
-        }
-        break;
-    case INDEX_op_sub2_i32:
-        if (args[0] == args[3] || args[0] == args[5]) {
-            tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
-            tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
-            tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
-        }
-        else {
-            tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
-            tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
+            tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], 0, 31);
+        } else {
+            tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 32));
+            tcg_out32(s, RLWNM | SAB(args[1], args[0], TCG_REG_R0)
+                         | MB(0) | ME(31));
         }
         break;
 
     case INDEX_op_brcond_i32:
-        /*
-          args[0] = r0
-          args[1] = r1
-          args[2] = cond
-          args[3] = r1 is const
-          args[4] = label_index
-        */
-        tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
+        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
+                       args[3], TCG_TYPE_I32);
+        break;
+    case INDEX_op_brcond_i64:
+        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
+                       args[3], TCG_TYPE_I64);
         break;
     case INDEX_op_brcond2_i32:
         tcg_out_brcond2(s, args, const_args);
         break;
 
     case INDEX_op_neg_i32:
-        tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
+    case INDEX_op_neg_i64:
+        tcg_out32(s, NEG | RT(args[0]) | RA(args[1]));
         break;
 
     case INDEX_op_not_i32:
-        tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
+    case INDEX_op_not_i64:
+        tcg_out32(s, NOR | SAB(args[1], args[0], args[1]));
+        break;
+
+    case INDEX_op_add_i64:
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[2]) {
+        do_addi_64:
+            tcg_out_mem_long(s, ADDI, ADD, a0, a1, a2);
+        } else {
+            tcg_out32(s, ADD | TAB(a0, a1, a2));
+        }
+        break;
+    case INDEX_op_sub_i64:
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[1]) {
+            if (const_args[2]) {
+                tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2);
+            } else {
+                tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
+            }
+        } else if (const_args[2]) {
+            a2 = -a2;
+            goto do_addi_64;
+        } else {
+            tcg_out32(s, SUBF | TAB(a0, a2, a1));
+        }
+        break;
+
+    case INDEX_op_shl_i64:
+        if (const_args[2]) {
+            tcg_out_shli64(s, args[0], args[1], args[2]);
+        } else {
+            tcg_out32(s, SLD | SAB(args[1], args[0], args[2]));
+        }
+        break;
+    case INDEX_op_shr_i64:
+        if (const_args[2]) {
+            tcg_out_shri64(s, args[0], args[1], args[2]);
+        } else {
+            tcg_out32(s, SRD | SAB(args[1], args[0], args[2]));
+        }
+        break;
+    case INDEX_op_sar_i64:
+        if (const_args[2]) {
+            int sh = SH(args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
+            tcg_out32(s, SRADI | RA(args[0]) | RS(args[1]) | sh);
+        } else {
+            tcg_out32(s, SRAD | SAB(args[1], args[0], args[2]));
+        }
+        break;
+    case INDEX_op_rotl_i64:
+        if (const_args[2]) {
+            tcg_out_rld(s, RLDICL, args[0], args[1], args[2], 0);
+        } else {
+            tcg_out32(s, RLDCL | SAB(args[1], args[0], args[2]) | MB64(0));
+        }
+        break;
+    case INDEX_op_rotr_i64:
+        if (const_args[2]) {
+            tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 0);
+        } else {
+            tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 64));
+            tcg_out32(s, RLDCL | SAB(args[1], args[0], TCG_REG_R0) | MB64(0));
+        }
+        break;
+
+    case INDEX_op_mul_i64:
+        a0 = args[0], a1 = args[1], a2 = args[2];
+        if (const_args[2]) {
+            tcg_out32(s, MULLI | TAI(a0, a1, a2));
+        } else {
+            tcg_out32(s, MULLD | TAB(a0, a1, a2));
+        }
+        break;
+    case INDEX_op_div_i64:
+        tcg_out32(s, DIVD | TAB(args[0], args[1], args[2]));
+        break;
+    case INDEX_op_divu_i64:
+        tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
         break;
 
     case INDEX_op_qemu_ld_i32:
-        tcg_out_qemu_ld(s, args, 0);
+        tcg_out_qemu_ld(s, args, false);
         break;
     case INDEX_op_qemu_ld_i64:
-        tcg_out_qemu_ld(s, args, 1);
+        tcg_out_qemu_ld(s, args, true);
         break;
     case INDEX_op_qemu_st_i32:
-        tcg_out_qemu_st(s, args, 0);
+        tcg_out_qemu_st(s, args, false);
         break;
     case INDEX_op_qemu_st_i64:
-        tcg_out_qemu_st(s, args, 1);
+        tcg_out_qemu_st(s, args, true);
         break;
 
     case INDEX_op_ext8s_i32:
-        tcg_out32 (s, EXTSB | RS (args[1]) | RA (args[0]));
-        break;
-    case INDEX_op_ext8u_i32:
-        tcg_out32 (s, RLWINM
-                   | RA (args[0])
-                   | RS (args[1])
-                   | SH (0)
-                   | MB (24)
-                   | ME (31)
-            );
-        break;
+    case INDEX_op_ext8s_i64:
+        c = EXTSB;
+        goto gen_ext;
     case INDEX_op_ext16s_i32:
-        tcg_out32 (s, EXTSH | RS (args[1]) | RA (args[0]));
-        break;
-    case INDEX_op_ext16u_i32:
-        tcg_out32 (s, RLWINM
-                   | RA (args[0])
-                   | RS (args[1])
-                   | SH (0)
-                   | MB (16)
-                   | ME (31)
-            );
+    case INDEX_op_ext16s_i64:
+        c = EXTSH;
+        goto gen_ext;
+    case INDEX_op_ext32s_i64:
+        c = EXTSW;
+        goto gen_ext;
+    gen_ext:
+        tcg_out32(s, c | RS(args[1]) | RA(args[0]));
         break;
 
     case INDEX_op_setcond_i32:
-        tcg_out_setcond (s, args[3], args[0], args[1], args[2], const_args[2]);
+        tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
+                        const_args[2]);
+        break;
+    case INDEX_op_setcond_i64:
+        tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
+                        const_args[2]);
         break;
     case INDEX_op_setcond2_i32:
-        tcg_out_setcond2 (s, args, const_args);
+        tcg_out_setcond2(s, args, const_args);
         break;
 
     case INDEX_op_bswap16_i32:
-        /* Stolen from gcc's builtin_bswap16 */
-
+    case INDEX_op_bswap16_i64:
+        a0 = args[0], a1 = args[1];
         /* a1 = abcd */
-
-        /* r0 = (a1 << 8) & 0xff00 # 00d0 */
-        tcg_out32 (s, RLWINM
-                   | RA (0)
-                   | RS (args[1])
-                   | SH (8)
-                   | MB (16)
-                   | ME (23)
-            );
-
-        /* a0 = rotate_left (a1, 24) & 0xff # 000c */
-        tcg_out32 (s, RLWINM
-                   | RA (args[0])
-                   | RS (args[1])
-                   | SH (24)
-                   | MB (24)
-                   | ME (31)
-            );
-
-        /* a0 = a0 | r0 # 00dc */
-        tcg_out32 (s, OR | SAB (0, args[0], args[0]));
+        if (a0 != a1) {
+            /* a0 = (a1 r<< 24) & 0xff # 000c */
+            tcg_out_rlw(s, RLWINM, a0, a1, 24, 24, 31);
+            /* a0 = (a0 & ~0xff00) | (a1 r<< 8) & 0xff00 # 00dc */
+            tcg_out_rlw(s, RLWIMI, a0, a1, 8, 16, 23);
+        } else {
+            /* r0 = (a1 r<< 8) & 0xff00 # 00d0 */
+            tcg_out_rlw(s, RLWINM, TCG_REG_R0, a1, 8, 16, 23);
+            /* a0 = (a1 r<< 24) & 0xff # 000c */
+            tcg_out_rlw(s, RLWINM, a0, a1, 24, 24, 31);
+            /* a0 = a0 | r0 # 00dc */
+            tcg_out32(s, OR | SAB(TCG_REG_R0, a0, a0));
+        }
         break;
 
     case INDEX_op_bswap32_i32:
+    case INDEX_op_bswap32_i64:
         /* Stolen from gcc's builtin_bswap32 */
-        {
-            int a0 = args[0];
-
-            /* a1 = args[1] # abcd */
+        a1 = args[1];
+        a0 = args[0] == a1 ? TCG_REG_R0 : args[0];
+
+        /* a1 = args[1] # abcd */
+        /* a0 = rotate_left (a1, 8) # bcda */
+        tcg_out_rlw(s, RLWINM, a0, a1, 8, 0, 31);
+        /* a0 = (a0 & ~0xff000000) | ((a1 r<< 24) & 0xff000000) # dcda */
+        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 0, 7);
+        /* a0 = (a0 & ~0x0000ff00) | ((a1 r<< 24) & 0x0000ff00) # dcba */
+        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 16, 23);
+
+        if (a0 == TCG_REG_R0) {
+            tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
+        }
+        break;
 
-            if (a0 == args[1]) {
-                a0 = 0;
-            }
+    case INDEX_op_bswap64_i64:
+        a0 = args[0], a1 = args[1], a2 = TCG_REG_R0;
+        if (a0 == a1) {
+            a0 = TCG_REG_R0;
+            a2 = a1;
+        }
 
-            /* a0 = rotate_left (a1, 8) # bcda */
-            tcg_out32 (s, RLWINM
-                       | RA (a0)
-                       | RS (args[1])
-                       | SH (8)
-                       | MB (0)
-                       | ME (31)
-                );
-
-            /* a0 = (a0 & ~0xff000000) | ((a1 << 24) & 0xff000000) # dcda */
-            tcg_out32 (s, RLWIMI
-                       | RA (a0)
-                       | RS (args[1])
-                       | SH (24)
-                       | MB (0)
-                       | ME (7)
-                );
-
-            /* a0 = (a0 & ~0x0000ff00) | ((a1 << 24) & 0x0000ff00) # dcba */
-            tcg_out32 (s, RLWIMI
-                       | RA (a0)
-                       | RS (args[1])
-                       | SH (24)
-                       | MB (16)
-                       | ME (23)
-                );
-
-            if (!a0) {
-                tcg_out_mov (s, TCG_TYPE_I32, args[0], a0);
-            }
+        /* a1 = # abcd efgh */
+        /* a0 = rl32(a1, 8) # 0000 fghe */
+        tcg_out_rlw(s, RLWINM, a0, a1, 8, 0, 31);
+        /* a0 = dep(a0, rl32(a1, 24), 0xff000000) # 0000 hghe */
+        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 0, 7);
+        /* a0 = dep(a0, rl32(a1, 24), 0x0000ff00) # 0000 hgfe */
+        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 16, 23);
+
+        /* a0 = rl64(a0, 32) # hgfe 0000 */
+        /* a2 = rl64(a1, 32) # efgh abcd */
+        tcg_out_rld(s, RLDICL, a0, a0, 32, 0);
+        tcg_out_rld(s, RLDICL, a2, a1, 32, 0);
+
+        /* a0 = dep(a0, rl32(a2, 8), 0xffffffff)  # hgfe bcda */
+        tcg_out_rlw(s, RLWIMI, a0, a2, 8, 0, 31);
+        /* a0 = dep(a0, rl32(a2, 24), 0xff000000) # hgfe dcda */
+        tcg_out_rlw(s, RLWIMI, a0, a2, 24, 0, 7);
+        /* a0 = dep(a0, rl32(a2, 24), 0x0000ff00) # hgfe dcba */
+        tcg_out_rlw(s, RLWIMI, a0, a2, 24, 16, 23);
+
+        if (a0 == 0) {
+            tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
         }
         break;
 
     case INDEX_op_deposit_i32:
-        tcg_out32 (s, RLWIMI
-                   | RA (args[0])
-                   | RS (args[2])
-                   | SH (args[3])
-                   | MB (32 - args[3] - args[4])
-                   | ME (31 - args[3])
-            );
+        if (const_args[2]) {
+            uint32_t mask = ((2u << (args[4] - 1)) - 1) << args[3];
+            tcg_out_andi32(s, args[0], args[0], ~mask);
+        } else {
+            tcg_out_rlw(s, RLWIMI, args[0], args[2], args[3],
+                        32 - args[3] - args[4], 31 - args[3]);
+        }
+        break;
+    case INDEX_op_deposit_i64:
+        if (const_args[2]) {
+            uint64_t mask = ((2ull << (args[4] - 1)) - 1) << args[3];
+            tcg_out_andi64(s, args[0], args[0], ~mask);
+        } else {
+            tcg_out_rld(s, RLDIMI, args[0], args[2], args[3],
+                        64 - args[3] - args[4]);
+        }
         break;
 
     case INDEX_op_movcond_i32:
-        tcg_out_movcond (s, args[5], args[0],
-                         args[1], args[2],
-                         args[3], args[4],
-                         const_args[2]);
+        tcg_out_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], args[2],
+                        args[3], args[4], const_args[2]);
+        break;
+    case INDEX_op_movcond_i64:
+        tcg_out_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1], args[2],
+                        args[3], args[4], const_args[2]);
+        break;
+
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_add2_i64:
+#else
+    case INDEX_op_add2_i32:
+#endif
+        /* Note that the CA bit is defined based on the word size of the
+           environment.  So in 64-bit mode it's always carry-out of bit 63.
+           The fallback code using deposit works just as well for 32-bit.  */
+        a0 = args[0], a1 = args[1];
+        if (a0 == args[3] || (!const_args[5] && a0 == args[5])) {
+            a0 = TCG_REG_R0;
+        }
+        if (const_args[4]) {
+            tcg_out32(s, ADDIC | TAI(a0, args[2], args[4]));
+        } else {
+            tcg_out32(s, ADDC | TAB(a0, args[2], args[4]));
+        }
+        if (const_args[5]) {
+            tcg_out32(s, (args[5] ? ADDME : ADDZE) | RT(a1) | RA(args[3]));
+        } else {
+            tcg_out32(s, ADDE | TAB(a1, args[3], args[5]));
+        }
+        if (a0 != args[0]) {
+            tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
+        }
         break;
 
-    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
-    case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
-    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_sub2_i64:
+#else
+    case INDEX_op_sub2_i32:
+#endif
+        a0 = args[0], a1 = args[1];
+        if (a0 == args[5] || (!const_args[3] && a0 == args[3])) {
+            a0 = TCG_REG_R0;
+        }
+        if (const_args[2]) {
+            tcg_out32(s, SUBFIC | TAI(a0, args[4], args[2]));
+        } else {
+            tcg_out32(s, SUBFC | TAB(a0, args[4], args[2]));
+        }
+        if (const_args[3]) {
+            tcg_out32(s, (args[3] ? SUBFME : SUBFZE) | RT(a1) | RA(args[5]));
+        } else {
+            tcg_out32(s, SUBFE | TAB(a1, args[5], args[3]));
+        }
+        if (a0 != args[0]) {
+            tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
+        }
+        break;
+
+    case INDEX_op_muluh_i32:
+        tcg_out32(s, MULHWU | TAB(args[0], args[1], args[2]));
+        break;
+    case INDEX_op_mulsh_i32:
+        tcg_out32(s, MULHW | TAB(args[0], args[1], args[2]));
+        break;
+    case INDEX_op_muluh_i64:
+        tcg_out32(s, MULHDU | TAB(args[0], args[1], args[2]));
+        break;
+    case INDEX_op_mulsh_i64:
+        tcg_out32(s, MULHD | TAB(args[0], args[1], args[2]));
+        break;
+
+    case INDEX_op_mov_i32:   /* Always emitted via tcg_out_mov.  */
+    case INDEX_op_mov_i64:
+    case INDEX_op_movi_i32:  /* Always emitted via tcg_out_movi.  */
+    case INDEX_op_movi_i64:
+    case INDEX_op_call:      /* Always emitted via tcg_out_call.  */
     default:
         tcg_abort();
     }
@@ -1834,79 +2396,146 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { INDEX_op_ld16u_i32, { "r", "r" } },
     { INDEX_op_ld16s_i32, { "r", "r" } },
     { INDEX_op_ld_i32, { "r", "r" } },
+
     { INDEX_op_st8_i32, { "r", "r" } },
     { INDEX_op_st16_i32, { "r", "r" } },
     { INDEX_op_st_i32, { "r", "r" } },
 
     { INDEX_op_add_i32, { "r", "r", "ri" } },
-    { INDEX_op_mul_i32, { "r", "r", "ri" } },
+    { INDEX_op_mul_i32, { "r", "r", "rI" } },
     { INDEX_op_div_i32, { "r", "r", "r" } },
     { INDEX_op_divu_i32, { "r", "r", "r" } },
-    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
-    { INDEX_op_sub_i32, { "r", "r", "ri" } },
+    { INDEX_op_sub_i32, { "r", "rI", "ri" } },
     { INDEX_op_and_i32, { "r", "r", "ri" } },
     { INDEX_op_or_i32, { "r", "r", "ri" } },
     { INDEX_op_xor_i32, { "r", "r", "ri" } },
+    { INDEX_op_andc_i32, { "r", "r", "ri" } },
+    { INDEX_op_orc_i32, { "r", "r", "ri" } },
+    { INDEX_op_eqv_i32, { "r", "r", "ri" } },
+    { INDEX_op_nand_i32, { "r", "r", "r" } },
+    { INDEX_op_nor_i32, { "r", "r", "r" } },
 
     { INDEX_op_shl_i32, { "r", "r", "ri" } },
     { INDEX_op_shr_i32, { "r", "r", "ri" } },
     { INDEX_op_sar_i32, { "r", "r", "ri" } },
-
     { INDEX_op_rotl_i32, { "r", "r", "ri" } },
     { INDEX_op_rotr_i32, { "r", "r", "ri" } },
 
-    { INDEX_op_brcond_i32, { "r", "ri" } },
-
-    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
-    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
-    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
-
     { INDEX_op_neg_i32, { "r", "r" } },
     { INDEX_op_not_i32, { "r", "r" } },
+    { INDEX_op_ext8s_i32, { "r", "r" } },
+    { INDEX_op_ext16s_i32, { "r", "r" } },
+    { INDEX_op_bswap16_i32, { "r", "r" } },
+    { INDEX_op_bswap32_i32, { "r", "r" } },
 
-    { INDEX_op_andc_i32, { "r", "r", "r" } },
-    { INDEX_op_orc_i32, { "r", "r", "r" } },
-    { INDEX_op_eqv_i32, { "r", "r", "r" } },
-    { INDEX_op_nand_i32, { "r", "r", "r" } },
-    { INDEX_op_nor_i32, { "r", "r", "r" } },
-
+    { INDEX_op_brcond_i32, { "r", "ri" } },
     { INDEX_op_setcond_i32, { "r", "r", "ri" } },
+    { INDEX_op_movcond_i32, { "r", "r", "ri", "rZ", "rZ" } },
+
+    { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
+
+    { INDEX_op_muluh_i32, { "r", "r", "r" } },
+    { INDEX_op_mulsh_i32, { "r", "r", "r" } },
+
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_ld8u_i64, { "r", "r" } },
+    { INDEX_op_ld8s_i64, { "r", "r" } },
+    { INDEX_op_ld16u_i64, { "r", "r" } },
+    { INDEX_op_ld16s_i64, { "r", "r" } },
+    { INDEX_op_ld32u_i64, { "r", "r" } },
+    { INDEX_op_ld32s_i64, { "r", "r" } },
+    { INDEX_op_ld_i64, { "r", "r" } },
+
+    { INDEX_op_st8_i64, { "r", "r" } },
+    { INDEX_op_st16_i64, { "r", "r" } },
+    { INDEX_op_st32_i64, { "r", "r" } },
+    { INDEX_op_st_i64, { "r", "r" } },
+
+    { INDEX_op_add_i64, { "r", "r", "rT" } },
+    { INDEX_op_sub_i64, { "r", "rI", "rT" } },
+    { INDEX_op_and_i64, { "r", "r", "ri" } },
+    { INDEX_op_or_i64, { "r", "r", "rU" } },
+    { INDEX_op_xor_i64, { "r", "r", "rU" } },
+    { INDEX_op_andc_i64, { "r", "r", "ri" } },
+    { INDEX_op_orc_i64, { "r", "r", "r" } },
+    { INDEX_op_eqv_i64, { "r", "r", "r" } },
+    { INDEX_op_nand_i64, { "r", "r", "r" } },
+    { INDEX_op_nor_i64, { "r", "r", "r" } },
+
+    { INDEX_op_shl_i64, { "r", "r", "ri" } },
+    { INDEX_op_shr_i64, { "r", "r", "ri" } },
+    { INDEX_op_sar_i64, { "r", "r", "ri" } },
+    { INDEX_op_rotl_i64, { "r", "r", "ri" } },
+    { INDEX_op_rotr_i64, { "r", "r", "ri" } },
+
+    { INDEX_op_mul_i64, { "r", "r", "rI" } },
+    { INDEX_op_div_i64, { "r", "r", "r" } },
+    { INDEX_op_divu_i64, { "r", "r", "r" } },
+
+    { INDEX_op_neg_i64, { "r", "r" } },
+    { INDEX_op_not_i64, { "r", "r" } },
+    { INDEX_op_ext8s_i64, { "r", "r" } },
+    { INDEX_op_ext16s_i64, { "r", "r" } },
+    { INDEX_op_ext32s_i64, { "r", "r" } },
+    { INDEX_op_bswap16_i64, { "r", "r" } },
+    { INDEX_op_bswap32_i64, { "r", "r" } },
+    { INDEX_op_bswap64_i64, { "r", "r" } },
+
+    { INDEX_op_brcond_i64, { "r", "ri" } },
+    { INDEX_op_setcond_i64, { "r", "r", "ri" } },
+    { INDEX_op_movcond_i64, { "r", "r", "ri", "rZ", "rZ" } },
+
+    { INDEX_op_deposit_i64, { "r", "0", "rZ" } },
+
+    { INDEX_op_mulsh_i64, { "r", "r", "r" } },
+    { INDEX_op_muluh_i64, { "r", "r", "r" } },
+#endif
+
+#if TCG_TARGET_REG_BITS == 32
+    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
     { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
+#endif
 
-    { INDEX_op_bswap16_i32, { "r", "r" } },
-    { INDEX_op_bswap32_i32, { "r", "r" } },
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } },
+    { INDEX_op_sub2_i64, { "r", "r", "rI", "rZM", "r", "r" } },
+#else
+    { INDEX_op_add2_i32, { "r", "r", "r", "r", "rI", "rZM" } },
+    { INDEX_op_sub2_i32, { "r", "r", "rI", "rZM", "r", "r" } },
+#endif
 
-#if TARGET_LONG_BITS == 32
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_qemu_ld_i32, { "r", "L" } },
+    { INDEX_op_qemu_st_i32, { "S", "S" } },
+    { INDEX_op_qemu_ld_i64, { "r", "L" } },
+    { INDEX_op_qemu_st_i64, { "S", "S" } },
+#elif TARGET_LONG_BITS == 32
     { INDEX_op_qemu_ld_i32, { "r", "L" } },
+    { INDEX_op_qemu_st_i32, { "S", "S" } },
     { INDEX_op_qemu_ld_i64, { "L", "L", "L" } },
-    { INDEX_op_qemu_st_i32, { "K", "K" } },
-    { INDEX_op_qemu_st_i64, { "M", "M", "M" } },
+    { INDEX_op_qemu_st_i64, { "S", "S", "S" } },
 #else
     { INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
+    { INDEX_op_qemu_st_i32, { "S", "S", "S" } },
     { INDEX_op_qemu_ld_i64, { "L", "L", "L", "L" } },
-    { INDEX_op_qemu_st_i32, { "K", "K", "K" } },
-    { INDEX_op_qemu_st_i64, { "M", "M", "M", "M" } },
+    { INDEX_op_qemu_st_i64, { "S", "S", "S", "S" } },
 #endif
 
-    { INDEX_op_ext8s_i32, { "r", "r" } },
-    { INDEX_op_ext8u_i32, { "r", "r" } },
-    { INDEX_op_ext16s_i32, { "r", "r" } },
-    { INDEX_op_ext16u_i32, { "r", "r" } },
-
-    { INDEX_op_deposit_i32, { "r", "0", "r" } },
-    { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "r" } },
-
     { -1 },
 };
 
 static void tcg_target_init(TCGContext *s)
 {
+    unsigned long hwcap = qemu_getauxval(AT_HWCAP);
+    if (hwcap & PPC_FEATURE_ARCH_2_06) {
+        have_isa_2_06 = true;
+    }
+
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                      (1 << TCG_REG_R0) |
-#ifdef TCG_TARGET_CALL_DARWIN
                      (1 << TCG_REG_R2) |
-#endif
                      (1 << TCG_REG_R3) |
                      (1 << TCG_REG_R4) |
                      (1 << TCG_REG_R5) |
@@ -1916,18 +2545,173 @@ static void tcg_target_init(TCGContext *s)
                      (1 << TCG_REG_R9) |
                      (1 << TCG_REG_R10) |
                      (1 << TCG_REG_R11) |
-                     (1 << TCG_REG_R12)
-        );
+                     (1 << TCG_REG_R12));
 
     tcg_regset_clear(s->reserved_regs);
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
-#ifndef TCG_TARGET_CALL_DARWIN
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* tcg temp */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* stack pointer */
+#if defined(_CALL_SYSV)
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* toc pointer */
 #endif
-#ifdef _CALL_SYSV
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13);
+#if defined(_CALL_SYSV) || TCG_TARGET_REG_BITS == 64
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
 #endif
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); /* mem temp */
+    if (USE_REG_RA) {
+        tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);  /* return addr */
+    }
 
     tcg_add_target_add_op_defs(ppc_op_defs);
 }
+
+#ifdef __ELF__
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDEHeader fde;
+    uint8_t fde_def_cfa[4];
+    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2 + 3];
+} DebugFrame;
+
+/* We're expecting a 2 byte uleb128 encoded value.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
+
+#if TCG_TARGET_REG_BITS == 64
+# define ELF_HOST_MACHINE EM_PPC64
+#else
+# define ELF_HOST_MACHINE EM_PPC
+#endif
+
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = (-SZR & 0x7f),         /* sleb128 -SZR */
+    .cie.return_column = 65,
+
+    /* Total FDE size does not include the "len" member.  */
+    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+    .fde_def_cfa = {
+        12, TCG_REG_R1,                 /* DW_CFA_def_cfa r1, ... */
+        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
+        (FRAME_SIZE >> 7)
+    },
+    .fde_reg_ofs = {
+        /* DW_CFA_offset_extended_sf, lr, LR_OFFSET */
+        0x11, 65, (LR_OFFSET / -SZR) & 0x7f,
+    }
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    uint8_t *p = &debug_frame.fde_reg_ofs[3];
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i, p += 2) {
+        p[0] = 0x80 + tcg_target_callee_save_regs[i];
+        p[1] = (FRAME_SIZE - (REG_SAVE_BOT + i * SZR)) / SZR;
+    }
+
+    debug_frame.fde.func_start = (uintptr_t)buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
+#endif /* __ELF__ */
+
+static size_t dcache_bsize = 16;
+static size_t icache_bsize = 16;
+
+void flush_icache_range(uintptr_t start, uintptr_t stop)
+{
+    uintptr_t p, start1, stop1;
+    size_t dsize = dcache_bsize;
+    size_t isize = icache_bsize;
+
+    start1 = start & ~(dsize - 1);
+    stop1 = (stop + dsize - 1) & ~(dsize - 1);
+    for (p = start1; p < stop1; p += dsize) {
+        asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
+    }
+    asm volatile ("sync" : : : "memory");
+
+    start &= start & ~(isize - 1);
+    stop1 = (stop + isize - 1) & ~(isize - 1);
+    for (p = start1; p < stop1; p += isize) {
+        asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
+    }
+    asm volatile ("sync" : : : "memory");
+    asm volatile ("isync" : : : "memory");
+}
+
+#if defined _AIX
+#include <sys/systemcfg.h>
+
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+    icache_bsize = _system_configuration.icache_line;
+    dcache_bsize = _system_configuration.dcache_line;
+}
+
+#elif defined __linux__
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+    unsigned long dsize = qemu_getauxval(AT_DCACHEBSIZE);
+    unsigned long isize = qemu_getauxval(AT_ICACHEBSIZE);
+
+    if (dsize == 0 || isize == 0) {
+        if (dsize == 0) {
+            fprintf(stderr, "getauxval AT_DCACHEBSIZE failed\n");
+        }
+        if (isize == 0) {
+            fprintf(stderr, "getauxval AT_ICACHEBSIZE failed\n");
+        }
+        exit(1);
+    }
+    dcache_bsize = dsize;
+    icache_bsize = isize;
+}
+
+#elif defined __APPLE__
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+    size_t len;
+    unsigned cacheline;
+    int name[2] = { CTL_HW, HW_CACHELINE };
+
+    len = sizeof(cacheline);
+    if (sysctl(name, 2, &cacheline, &len, NULL, 0)) {
+        perror("sysctl CTL_HW HW_CACHELINE failed");
+        exit(1);
+    }
+    dcache_bsize = cacheline;
+    icache_bsize = cacheline;
+}
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+static void __attribute__((constructor)) tcg_cache_init(void)
+{
+    size_t len = 4;
+    unsigned cacheline;
+
+    if (sysctlbyname ("machdep.cacheline_size", &cacheline, &len, NULL, 0)) {
+        fprintf(stderr, "sysctlbyname machdep.cacheline_size failed: %s\n",
+                strerror(errno));
+        exit(1);
+    }
+    dcache_bsize = cacheline;
+    icache_bsize = cacheline;
+}
+#endif
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 05069ae2d8..32ac4424db 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -21,60 +21,35 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#ifndef TCG_TARGET_PPC 
-#define TCG_TARGET_PPC 1
+#ifndef TCG_TARGET_PPC64 
+#define TCG_TARGET_PPC64 1
+
+#ifdef _ARCH_PPC64
+# define TCG_TARGET_REG_BITS  64
+#else
+# define TCG_TARGET_REG_BITS  32
+#endif
 
 #define TCG_TARGET_NB_REGS 32
 #define TCG_TARGET_INSN_UNIT_SIZE 4
 
 typedef enum {
-    TCG_REG_R0 = 0,
-    TCG_REG_R1,
-    TCG_REG_R2,
-    TCG_REG_R3,
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-    TCG_REG_R11,
-    TCG_REG_R12,
-    TCG_REG_R13,
-    TCG_REG_R14,
-    TCG_REG_R15,
-    TCG_REG_R16,
-    TCG_REG_R17,
-    TCG_REG_R18,
-    TCG_REG_R19,
-    TCG_REG_R20,
-    TCG_REG_R21,
-    TCG_REG_R22,
-    TCG_REG_R23,
-    TCG_REG_R24,
-    TCG_REG_R25,
-    TCG_REG_R26,
-    TCG_REG_R27,
-    TCG_REG_R28,
-    TCG_REG_R29,
-    TCG_REG_R30,
-    TCG_REG_R31
+    TCG_REG_R0,  TCG_REG_R1,  TCG_REG_R2,  TCG_REG_R3,
+    TCG_REG_R4,  TCG_REG_R5,  TCG_REG_R6,  TCG_REG_R7,
+    TCG_REG_R8,  TCG_REG_R9,  TCG_REG_R10, TCG_REG_R11,
+    TCG_REG_R12, TCG_REG_R13, TCG_REG_R14, TCG_REG_R15,
+    TCG_REG_R16, TCG_REG_R17, TCG_REG_R18, TCG_REG_R19,
+    TCG_REG_R20, TCG_REG_R21, TCG_REG_R22, TCG_REG_R23,
+    TCG_REG_R24, TCG_REG_R25, TCG_REG_R26, TCG_REG_R27,
+    TCG_REG_R28, TCG_REG_R29, TCG_REG_R30, TCG_REG_R31,
+
+    TCG_REG_CALL_STACK = TCG_REG_R1,
+    TCG_AREG0 = TCG_REG_R27
 } TCGReg;
 
-/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_R1
-#define TCG_TARGET_STACK_ALIGN 16
-#if defined _CALL_DARWIN || defined __APPLE__
-#define TCG_TARGET_CALL_STACK_OFFSET 24
-#elif defined _CALL_AIX
-#define TCG_TARGET_CALL_STACK_OFFSET 52
-#elif defined _CALL_SYSV
-#define TCG_TARGET_CALL_ALIGN_ARGS 1
-#define TCG_TARGET_CALL_STACK_OFFSET 8
-#else
-#error Unsupported system
-#endif
+/* optional instructions automatically implemented */
+#define TCG_TARGET_HAS_ext8u_i32        0 /* andi */
+#define TCG_TARGET_HAS_ext16u_i32       0
 
 /* optional instructions */
 #define TCG_TARGET_HAS_div_i32          1
@@ -82,8 +57,6 @@ typedef enum {
 #define TCG_TARGET_HAS_rot_i32          1
 #define TCG_TARGET_HAS_ext8s_i32        1
 #define TCG_TARGET_HAS_ext16s_i32       1
-#define TCG_TARGET_HAS_ext8u_i32        1
-#define TCG_TARGET_HAS_ext16u_i32       1
 #define TCG_TARGET_HAS_bswap16_i32      1
 #define TCG_TARGET_HAS_bswap32_i32      1
 #define TCG_TARGET_HAS_not_i32          1
@@ -95,15 +68,44 @@ typedef enum {
 #define TCG_TARGET_HAS_nor_i32          1
 #define TCG_TARGET_HAS_deposit_i32      1
 #define TCG_TARGET_HAS_movcond_i32      1
-#define TCG_TARGET_HAS_mulu2_i32        1
+#define TCG_TARGET_HAS_mulu2_i32        0
 #define TCG_TARGET_HAS_muls2_i32        0
-#define TCG_TARGET_HAS_muluh_i32        0
-#define TCG_TARGET_HAS_mulsh_i32        0
+#define TCG_TARGET_HAS_muluh_i32        1
+#define TCG_TARGET_HAS_mulsh_i32        1
 
-#define TCG_AREG0 TCG_REG_R27
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_add2_i32         0
+#define TCG_TARGET_HAS_sub2_i32         0
+#define TCG_TARGET_HAS_trunc_shr_i32    0
+#define TCG_TARGET_HAS_div_i64          1
+#define TCG_TARGET_HAS_rem_i64          0
+#define TCG_TARGET_HAS_rot_i64          1
+#define TCG_TARGET_HAS_ext8s_i64        1
+#define TCG_TARGET_HAS_ext16s_i64       1
+#define TCG_TARGET_HAS_ext32s_i64       1
+#define TCG_TARGET_HAS_ext8u_i64        0
+#define TCG_TARGET_HAS_ext16u_i64       0
+#define TCG_TARGET_HAS_ext32u_i64       0
+#define TCG_TARGET_HAS_bswap16_i64      1
+#define TCG_TARGET_HAS_bswap32_i64      1
+#define TCG_TARGET_HAS_bswap64_i64      1
+#define TCG_TARGET_HAS_not_i64          1
+#define TCG_TARGET_HAS_neg_i64          1
+#define TCG_TARGET_HAS_andc_i64         1
+#define TCG_TARGET_HAS_orc_i64          1
+#define TCG_TARGET_HAS_eqv_i64          1
+#define TCG_TARGET_HAS_nand_i64         1
+#define TCG_TARGET_HAS_nor_i64          1
+#define TCG_TARGET_HAS_deposit_i64      1
+#define TCG_TARGET_HAS_movcond_i64      1
+#define TCG_TARGET_HAS_add2_i64         1
+#define TCG_TARGET_HAS_sub2_i64         1
+#define TCG_TARGET_HAS_mulu2_i64        0
+#define TCG_TARGET_HAS_muls2_i64        0
+#define TCG_TARGET_HAS_muluh_i64        1
+#define TCG_TARGET_HAS_mulsh_i64        1
+#endif
 
-#define tcg_qemu_tb_exec(env, tb_ptr) \
-    ((uintptr_t __attribute__ ((longcall)) \
-      (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, tb_ptr)
+void flush_icache_range(uintptr_t start, uintptr_t stop);
 
 #endif
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
deleted file mode 100644
index c90ddcd03a..0000000000
--- a/tcg/ppc64/tcg-target.c
+++ /dev/null
@@ -1,2186 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "tcg-be-ldst.h"
-
-#define TCG_CT_CONST_S16  0x100
-#define TCG_CT_CONST_U16  0x200
-#define TCG_CT_CONST_S32  0x400
-#define TCG_CT_CONST_U32  0x800
-#define TCG_CT_CONST_ZERO 0x1000
-#define TCG_CT_CONST_MONE 0x2000
-
-static tcg_insn_unit *tb_ret_addr;
-
-#if TARGET_LONG_BITS == 32
-#define LD_ADDR LWZ
-#define CMP_L 0
-#else
-#define LD_ADDR LD
-#define CMP_L (1<<21)
-#endif
-
-#ifndef GUEST_BASE
-#define GUEST_BASE 0
-#endif
-
-#include "elf.h"
-static bool have_isa_2_06;
-#define HAVE_ISA_2_06  have_isa_2_06
-#define HAVE_ISEL      have_isa_2_06
-
-#ifdef CONFIG_USE_GUEST_BASE
-#define TCG_GUEST_BASE_REG 30
-#else
-#define TCG_GUEST_BASE_REG 0
-#endif
-
-#ifndef NDEBUG
-static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
-    "r0",
-    "r1",
-    "r2",
-    "r3",
-    "r4",
-    "r5",
-    "r6",
-    "r7",
-    "r8",
-    "r9",
-    "r10",
-    "r11",
-    "r12",
-    "r13",
-    "r14",
-    "r15",
-    "r16",
-    "r17",
-    "r18",
-    "r19",
-    "r20",
-    "r21",
-    "r22",
-    "r23",
-    "r24",
-    "r25",
-    "r26",
-    "r27",
-    "r28",
-    "r29",
-    "r30",
-    "r31"
-};
-#endif
-
-static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_R14,  /* call saved registers */
-    TCG_REG_R15,
-    TCG_REG_R16,
-    TCG_REG_R17,
-    TCG_REG_R18,
-    TCG_REG_R19,
-    TCG_REG_R20,
-    TCG_REG_R21,
-    TCG_REG_R22,
-    TCG_REG_R23,
-    TCG_REG_R24,
-    TCG_REG_R25,
-    TCG_REG_R26,
-    TCG_REG_R27,
-    TCG_REG_R28,
-    TCG_REG_R29,
-    TCG_REG_R30,
-    TCG_REG_R31,
-    TCG_REG_R12,  /* call clobbered, non-arguments */
-    TCG_REG_R11,
-    TCG_REG_R10,  /* call clobbered, arguments */
-    TCG_REG_R9,
-    TCG_REG_R8,
-    TCG_REG_R7,
-    TCG_REG_R6,
-    TCG_REG_R5,
-    TCG_REG_R4,
-    TCG_REG_R3,
-};
-
-static const int tcg_target_call_iarg_regs[] = {
-    TCG_REG_R3,
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10
-};
-
-static const int tcg_target_call_oarg_regs[] = {
-    TCG_REG_R3
-};
-
-static const int tcg_target_callee_save_regs[] = {
-#ifdef __APPLE__
-    TCG_REG_R11,
-#endif
-    TCG_REG_R14,
-    TCG_REG_R15,
-    TCG_REG_R16,
-    TCG_REG_R17,
-    TCG_REG_R18,
-    TCG_REG_R19,
-    TCG_REG_R20,
-    TCG_REG_R21,
-    TCG_REG_R22,
-    TCG_REG_R23,
-    TCG_REG_R24,
-    TCG_REG_R25,
-    TCG_REG_R26,
-    TCG_REG_R27, /* currently used for the global env */
-    TCG_REG_R28,
-    TCG_REG_R29,
-    TCG_REG_R30,
-    TCG_REG_R31
-};
-
-static inline bool in_range_b(tcg_target_long target)
-{
-    return target == sextract64(target, 0, 26);
-}
-
-static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
-    ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
-    assert(in_range_b(disp));
-    return disp & 0x3fffffc;
-}
-
-static void reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
-    *pc = (*pc & ~0x3fffffc) | reloc_pc24_val(pc, target);
-}
-
-static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
-    ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
-    assert(disp == (int16_t) disp);
-    return disp & 0xfffc;
-}
-
-static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
-{
-    *pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target);
-}
-
-static inline void tcg_out_b_noaddr(TCGContext *s, int insn)
-{
-    unsigned retrans = *s->code_ptr & 0x3fffffc;
-    tcg_out32(s, insn | retrans);
-}
-
-static inline void tcg_out_bc_noaddr(TCGContext *s, int insn)
-{
-    unsigned retrans = *s->code_ptr & 0xfffc;
-    tcg_out32(s, insn | retrans);
-}
-
-static void patch_reloc(tcg_insn_unit *code_ptr, int type,
-                        intptr_t value, intptr_t addend)
-{
-    tcg_insn_unit *target = (tcg_insn_unit *)value;
-
-    assert(addend == 0);
-    switch (type) {
-    case R_PPC_REL14:
-        reloc_pc14(code_ptr, target);
-        break;
-    case R_PPC_REL24:
-        reloc_pc24(code_ptr, target);
-        break;
-    default:
-        tcg_abort();
-    }
-}
-
-/* parse target specific constraints */
-static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
-{
-    const char *ct_str;
-
-    ct_str = *pct_str;
-    switch (ct_str[0]) {
-    case 'A': case 'B': case 'C': case 'D':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
-        break;
-    case 'r':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
-        break;
-    case 'L':                   /* qemu_ld constraint */
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
-#ifdef CONFIG_SOFTMMU
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
-#endif
-        break;
-    case 'S':                   /* qemu_st constraint */
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
-#ifdef CONFIG_SOFTMMU
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
-#endif
-        break;
-    case 'I':
-        ct->ct |= TCG_CT_CONST_S16;
-        break;
-    case 'J':
-        ct->ct |= TCG_CT_CONST_U16;
-        break;
-    case 'M':
-        ct->ct |= TCG_CT_CONST_MONE;
-        break;
-    case 'T':
-        ct->ct |= TCG_CT_CONST_S32;
-        break;
-    case 'U':
-        ct->ct |= TCG_CT_CONST_U32;
-        break;
-    case 'Z':
-        ct->ct |= TCG_CT_CONST_ZERO;
-        break;
-    default:
-        return -1;
-    }
-    ct_str++;
-    *pct_str = ct_str;
-    return 0;
-}
-
-/* test if a constant matches the constraint */
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
-                                  const TCGArgConstraint *arg_ct)
-{
-    int ct = arg_ct->ct;
-    if (ct & TCG_CT_CONST) {
-        return 1;
-    }
-
-    /* The only 32-bit constraint we use aside from
-       TCG_CT_CONST is TCG_CT_CONST_S16.  */
-    if (type == TCG_TYPE_I32) {
-        val = (int32_t)val;
-    }
-
-    if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
-        return 1;
-    } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
-        return 1;
-    } else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
-        return 1;
-    } else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
-        return 1;
-    } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
-        return 1;
-    } else if ((ct & TCG_CT_CONST_MONE) && val == -1) {
-        return 1;
-    }
-    return 0;
-}
-
-#define OPCD(opc) ((opc)<<26)
-#define XO19(opc) (OPCD(19)|((opc)<<1))
-#define MD30(opc) (OPCD(30)|((opc)<<2))
-#define MDS30(opc) (OPCD(30)|((opc)<<1))
-#define XO31(opc) (OPCD(31)|((opc)<<1))
-#define XO58(opc) (OPCD(58)|(opc))
-#define XO62(opc) (OPCD(62)|(opc))
-
-#define B      OPCD( 18)
-#define BC     OPCD( 16)
-#define LBZ    OPCD( 34)
-#define LHZ    OPCD( 40)
-#define LHA    OPCD( 42)
-#define LWZ    OPCD( 32)
-#define STB    OPCD( 38)
-#define STH    OPCD( 44)
-#define STW    OPCD( 36)
-
-#define STD    XO62(  0)
-#define STDU   XO62(  1)
-#define STDX   XO31(149)
-
-#define LD     XO58(  0)
-#define LDX    XO31( 21)
-#define LDU    XO58(  1)
-#define LWA    XO58(  2)
-#define LWAX   XO31(341)
-
-#define ADDIC  OPCD( 12)
-#define ADDI   OPCD( 14)
-#define ADDIS  OPCD( 15)
-#define ORI    OPCD( 24)
-#define ORIS   OPCD( 25)
-#define XORI   OPCD( 26)
-#define XORIS  OPCD( 27)
-#define ANDI   OPCD( 28)
-#define ANDIS  OPCD( 29)
-#define MULLI  OPCD(  7)
-#define CMPLI  OPCD( 10)
-#define CMPI   OPCD( 11)
-#define SUBFIC OPCD( 8)
-
-#define LWZU   OPCD( 33)
-#define STWU   OPCD( 37)
-
-#define RLWIMI OPCD( 20)
-#define RLWINM OPCD( 21)
-#define RLWNM  OPCD( 23)
-
-#define RLDICL MD30(  0)
-#define RLDICR MD30(  1)
-#define RLDIMI MD30(  3)
-#define RLDCL  MDS30( 8)
-
-#define BCLR   XO19( 16)
-#define BCCTR  XO19(528)
-#define CRAND  XO19(257)
-#define CRANDC XO19(129)
-#define CRNAND XO19(225)
-#define CROR   XO19(449)
-#define CRNOR  XO19( 33)
-
-#define EXTSB  XO31(954)
-#define EXTSH  XO31(922)
-#define EXTSW  XO31(986)
-#define ADD    XO31(266)
-#define ADDE   XO31(138)
-#define ADDME  XO31(234)
-#define ADDZE  XO31(202)
-#define ADDC   XO31( 10)
-#define AND    XO31( 28)
-#define SUBF   XO31( 40)
-#define SUBFC  XO31(  8)
-#define SUBFE  XO31(136)
-#define SUBFME XO31(232)
-#define SUBFZE XO31(200)
-#define OR     XO31(444)
-#define XOR    XO31(316)
-#define MULLW  XO31(235)
-#define MULHWU XO31( 11)
-#define DIVW   XO31(491)
-#define DIVWU  XO31(459)
-#define CMP    XO31(  0)
-#define CMPL   XO31( 32)
-#define LHBRX  XO31(790)
-#define LWBRX  XO31(534)
-#define LDBRX  XO31(532)
-#define STHBRX XO31(918)
-#define STWBRX XO31(662)
-#define STDBRX XO31(660)
-#define MFSPR  XO31(339)
-#define MTSPR  XO31(467)
-#define SRAWI  XO31(824)
-#define NEG    XO31(104)
-#define MFCR   XO31( 19)
-#define MFOCRF (MFCR | (1u << 20))
-#define NOR    XO31(124)
-#define CNTLZW XO31( 26)
-#define CNTLZD XO31( 58)
-#define ANDC   XO31( 60)
-#define ORC    XO31(412)
-#define EQV    XO31(284)
-#define NAND   XO31(476)
-#define ISEL   XO31( 15)
-
-#define MULLD  XO31(233)
-#define MULHD  XO31( 73)
-#define MULHDU XO31(  9)
-#define DIVD   XO31(489)
-#define DIVDU  XO31(457)
-
-#define LBZX   XO31( 87)
-#define LHZX   XO31(279)
-#define LHAX   XO31(343)
-#define LWZX   XO31( 23)
-#define STBX   XO31(215)
-#define STHX   XO31(407)
-#define STWX   XO31(151)
-
-#define SPR(a, b) ((((a)<<5)|(b))<<11)
-#define LR     SPR(8, 0)
-#define CTR    SPR(9, 0)
-
-#define SLW    XO31( 24)
-#define SRW    XO31(536)
-#define SRAW   XO31(792)
-
-#define SLD    XO31( 27)
-#define SRD    XO31(539)
-#define SRAD   XO31(794)
-#define SRADI  XO31(413<<1)
-
-#define TW     XO31( 4)
-#define TRAP   (TW | TO(31))
-
-#define RT(r) ((r)<<21)
-#define RS(r) ((r)<<21)
-#define RA(r) ((r)<<16)
-#define RB(r) ((r)<<11)
-#define TO(t) ((t)<<21)
-#define SH(s) ((s)<<11)
-#define MB(b) ((b)<<6)
-#define ME(e) ((e)<<1)
-#define BO(o) ((o)<<21)
-#define MB64(b) ((b)<<5)
-#define FXM(b) (1 << (19 - (b)))
-
-#define LK    1
-
-#define TAB(t, a, b) (RT(t) | RA(a) | RB(b))
-#define SAB(s, a, b) (RS(s) | RA(a) | RB(b))
-#define TAI(s, a, i) (RT(s) | RA(a) | ((i) & 0xffff))
-#define SAI(s, a, i) (RS(s) | RA(a) | ((i) & 0xffff))
-
-#define BF(n)    ((n)<<23)
-#define BI(n, c) (((c)+((n)*4))<<16)
-#define BT(n, c) (((c)+((n)*4))<<21)
-#define BA(n, c) (((c)+((n)*4))<<16)
-#define BB(n, c) (((c)+((n)*4))<<11)
-#define BC_(n, c) (((c)+((n)*4))<<6)
-
-#define BO_COND_TRUE  BO(12)
-#define BO_COND_FALSE BO( 4)
-#define BO_ALWAYS     BO(20)
-
-enum {
-    CR_LT,
-    CR_GT,
-    CR_EQ,
-    CR_SO
-};
-
-static const uint32_t tcg_to_bc[] = {
-    [TCG_COND_EQ]  = BC | BI(7, CR_EQ) | BO_COND_TRUE,
-    [TCG_COND_NE]  = BC | BI(7, CR_EQ) | BO_COND_FALSE,
-    [TCG_COND_LT]  = BC | BI(7, CR_LT) | BO_COND_TRUE,
-    [TCG_COND_GE]  = BC | BI(7, CR_LT) | BO_COND_FALSE,
-    [TCG_COND_LE]  = BC | BI(7, CR_GT) | BO_COND_FALSE,
-    [TCG_COND_GT]  = BC | BI(7, CR_GT) | BO_COND_TRUE,
-    [TCG_COND_LTU] = BC | BI(7, CR_LT) | BO_COND_TRUE,
-    [TCG_COND_GEU] = BC | BI(7, CR_LT) | BO_COND_FALSE,
-    [TCG_COND_LEU] = BC | BI(7, CR_GT) | BO_COND_FALSE,
-    [TCG_COND_GTU] = BC | BI(7, CR_GT) | BO_COND_TRUE,
-};
-
-/* The low bit here is set if the RA and RB fields must be inverted.  */
-static const uint32_t tcg_to_isel[] = {
-    [TCG_COND_EQ]  = ISEL | BC_(7, CR_EQ),
-    [TCG_COND_NE]  = ISEL | BC_(7, CR_EQ) | 1,
-    [TCG_COND_LT]  = ISEL | BC_(7, CR_LT),
-    [TCG_COND_GE]  = ISEL | BC_(7, CR_LT) | 1,
-    [TCG_COND_LE]  = ISEL | BC_(7, CR_GT) | 1,
-    [TCG_COND_GT]  = ISEL | BC_(7, CR_GT),
-    [TCG_COND_LTU] = ISEL | BC_(7, CR_LT),
-    [TCG_COND_GEU] = ISEL | BC_(7, CR_LT) | 1,
-    [TCG_COND_LEU] = ISEL | BC_(7, CR_GT) | 1,
-    [TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
-};
-
-static inline void tcg_out_mov(TCGContext *s, TCGType type,
-                               TCGReg ret, TCGReg arg)
-{
-    if (ret != arg) {
-        tcg_out32(s, OR | SAB(arg, ret, arg));
-    }
-}
-
-static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
-                               int sh, int mb)
-{
-    sh = SH(sh & 0x1f) | (((sh >> 5) & 1) << 1);
-    mb = MB64((mb >> 5) | ((mb << 1) & 0x3f));
-    tcg_out32(s, op | RA(ra) | RS(rs) | sh | mb);
-}
-
-static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
-                               int sh, int mb, int me)
-{
-    tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
-}
-
-static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
-{
-    tcg_out_rld(s, RLDICL, dst, src, 0, 32);
-}
-
-static inline void tcg_out_shli64(TCGContext *s, TCGReg dst, TCGReg src, int c)
-{
-    tcg_out_rld(s, RLDICR, dst, src, c, 63 - c);
-}
-
-static inline void tcg_out_shri64(TCGContext *s, TCGReg dst, TCGReg src, int c)
-{
-    tcg_out_rld(s, RLDICL, dst, src, 64 - c, c);
-}
-
-static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
-{
-    if (arg == (int16_t) arg) {
-        tcg_out32(s, ADDI | TAI(ret, 0, arg));
-    } else {
-        tcg_out32(s, ADDIS | TAI(ret, 0, arg >> 16));
-        if (arg & 0xffff) {
-            tcg_out32(s, ORI | SAI(ret, ret, arg));
-        }
-    }
-}
-
-static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
-                         tcg_target_long arg)
-{
-    if (type == TCG_TYPE_I32 || arg == (int32_t)arg) {
-        tcg_out_movi32(s, ret, arg);
-    } else if (arg == (uint32_t)arg && !(arg & 0x8000)) {
-        tcg_out32(s, ADDI | TAI(ret, 0, arg));
-        tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
-    } else {
-        int32_t high = arg >> 32;
-        tcg_out_movi32(s, ret, high);
-        if (high) {
-            tcg_out_shli64(s, ret, ret, 32);
-        }
-        if (arg & 0xffff0000) {
-            tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
-        }
-        if (arg & 0xffff) {
-            tcg_out32(s, ORI | SAI(ret, ret, arg));
-        }
-    }
-}
-
-static bool mask_operand(uint32_t c, int *mb, int *me)
-{
-    uint32_t lsb, test;
-
-    /* Accept a bit pattern like:
-           0....01....1
-           1....10....0
-           0..01..10..0
-       Keep track of the transitions.  */
-    if (c == 0 || c == -1) {
-        return false;
-    }
-    test = c;
-    lsb = test & -test;
-    test += lsb;
-    if (test & (test - 1)) {
-        return false;
-    }
-
-    *me = clz32(lsb);
-    *mb = test ? clz32(test & -test) + 1 : 0;
-    return true;
-}
-
-static bool mask64_operand(uint64_t c, int *mb, int *me)
-{
-    uint64_t lsb;
-
-    if (c == 0) {
-        return false;
-    }
-
-    lsb = c & -c;
-    /* Accept 1..10..0.  */
-    if (c == -lsb) {
-        *mb = 0;
-        *me = clz64(lsb);
-        return true;
-    }
-    /* Accept 0..01..1.  */
-    if (lsb == 1 && (c & (c + 1)) == 0) {
-        *mb = clz64(c + 1) + 1;
-        *me = 63;
-        return true;
-    }
-    return false;
-}
-
-static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
-{
-    int mb, me;
-
-    if ((c & 0xffff) == c) {
-        tcg_out32(s, ANDI | SAI(src, dst, c));
-        return;
-    } else if ((c & 0xffff0000) == c) {
-        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
-        return;
-    } else if (mask_operand(c, &mb, &me)) {
-        tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
-    } else {
-        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R0, c);
-        tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
-    }
-}
-
-static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
-{
-    int mb, me;
-
-    if ((c & 0xffff) == c) {
-        tcg_out32(s, ANDI | SAI(src, dst, c));
-        return;
-    } else if ((c & 0xffff0000) == c) {
-        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
-        return;
-    } else if (mask64_operand(c, &mb, &me)) {
-        if (mb == 0) {
-            tcg_out_rld(s, RLDICR, dst, src, 0, me);
-        } else {
-            tcg_out_rld(s, RLDICL, dst, src, 0, mb);
-        }
-    } else {
-        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, c);
-        tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
-    }
-}
-
-static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
-                           int op_lo, int op_hi)
-{
-    if (c >> 16) {
-        tcg_out32(s, op_hi | SAI(src, dst, c >> 16));
-        src = dst;
-    }
-    if (c & 0xffff) {
-        tcg_out32(s, op_lo | SAI(src, dst, c));
-        src = dst;
-    }
-}
-
-static void tcg_out_ori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
-{
-    tcg_out_zori32(s, dst, src, c, ORI, ORIS);
-}
-
-static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
-{
-    tcg_out_zori32(s, dst, src, c, XORI, XORIS);
-}
-
-static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
-{
-    ptrdiff_t disp = tcg_pcrel_diff(s, target);
-    if (in_range_b(disp)) {
-        tcg_out32(s, B | (disp & 0x3fffffc) | mask);
-    } else {
-        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, (uintptr_t)target);
-        tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
-        tcg_out32(s, BCCTR | BO_ALWAYS | mask);
-    }
-}
-
-static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
-{
-#ifdef __APPLE__
-    tcg_out_b(s, LK, target);
-#else
-    /* Look through the descriptor.  If the branch is in range, and we
-       don't have to spend too much effort on building the toc.  */
-    void *tgt = ((void **)target)[0];
-    uintptr_t toc = ((uintptr_t *)target)[1];
-    intptr_t diff = tcg_pcrel_diff(s, tgt);
-
-    if (in_range_b(diff) && toc == (uint32_t)toc) {
-        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, toc);
-        tcg_out_b(s, LK, tgt);
-    } else {
-        /* Fold the low bits of the constant into the addresses below.  */
-        intptr_t arg = (intptr_t)target;
-        int ofs = (int16_t)arg;
-
-        if (ofs + 8 < 0x8000) {
-            arg -= ofs;
-        } else {
-            ofs = 0;
-        }
-        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, arg);
-        tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R2, ofs));
-        tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
-        tcg_out32(s, LD | TAI(TCG_REG_R2, TCG_REG_R2, ofs + 8));
-        tcg_out32(s, BCCTR | BO_ALWAYS | LK);
-    }
-#endif
-}
-
-static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
-                             TCGReg base, tcg_target_long offset)
-{
-    tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
-    TCGReg rs = TCG_REG_R2;
-
-    assert(rt != TCG_REG_R2 && base != TCG_REG_R2);
-
-    switch (opi) {
-    case LD: case LWA:
-        align = 3;
-        /* FALLTHRU */
-    default:
-        if (rt != TCG_REG_R0) {
-            rs = rt;
-        }
-        break;
-    case STD:
-        align = 3;
-        break;
-    case STB: case STH: case STW:
-        break;
-    }
-
-    /* For unaligned, or very large offsets, use the indexed form.  */
-    if (offset & align || offset != (int32_t)offset) {
-        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, orig);
-        tcg_out32(s, opx | TAB(rt, base, TCG_REG_R2));
-        return;
-    }
-
-    l0 = (int16_t)offset;
-    offset = (offset - l0) >> 16;
-    l1 = (int16_t)offset;
-
-    if (l1 < 0 && orig >= 0) {
-        extra = 0x4000;
-        l1 = (int16_t)(offset - 0x4000);
-    }
-    if (l1) {
-        tcg_out32(s, ADDIS | TAI(rs, base, l1));
-        base = rs;
-    }
-    if (extra) {
-        tcg_out32(s, ADDIS | TAI(rs, base, extra));
-        base = rs;
-    }
-    if (opi != ADDI || base != rt || l0 != 0) {
-        tcg_out32(s, opi | TAI(rt, base, l0));
-    }
-}
-
-static const uint32_t qemu_ldx_opc[16] = {
-    [MO_UB] = LBZX,
-    [MO_UW] = LHZX,
-    [MO_UL] = LWZX,
-    [MO_Q]  = LDX,
-    [MO_SW] = LHAX,
-    [MO_SL] = LWAX,
-    [MO_BSWAP | MO_UB] = LBZX,
-    [MO_BSWAP | MO_UW] = LHBRX,
-    [MO_BSWAP | MO_UL] = LWBRX,
-    [MO_BSWAP | MO_Q]  = LDBRX,
-};
-
-static const uint32_t qemu_stx_opc[16] = {
-    [MO_UB] = STBX,
-    [MO_UW] = STHX,
-    [MO_UL] = STWX,
-    [MO_Q]  = STDX,
-    [MO_BSWAP | MO_UB] = STBX,
-    [MO_BSWAP | MO_UW] = STHBRX,
-    [MO_BSWAP | MO_UL] = STWBRX,
-    [MO_BSWAP | MO_Q]  = STDBRX,
-};
-
-static const uint32_t qemu_exts_opc[4] = {
-    EXTSB, EXTSH, EXTSW, 0
-};
-
-#if defined (CONFIG_SOFTMMU)
-/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
- *                                 int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_ld_helpers[16] = {
-    [MO_UB]   = helper_ret_ldub_mmu,
-    [MO_LEUW] = helper_le_lduw_mmu,
-    [MO_LEUL] = helper_le_ldul_mmu,
-    [MO_LEQ]  = helper_le_ldq_mmu,
-    [MO_BEUW] = helper_be_lduw_mmu,
-    [MO_BEUL] = helper_be_ldul_mmu,
-    [MO_BEQ]  = helper_be_ldq_mmu,
-};
-
-/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
- *                                 uintxx_t val, int mmu_idx, uintptr_t ra)
- */
-static void * const qemu_st_helpers[16] = {
-    [MO_UB]   = helper_ret_stb_mmu,
-    [MO_LEUW] = helper_le_stw_mmu,
-    [MO_LEUL] = helper_le_stl_mmu,
-    [MO_LEQ]  = helper_le_stq_mmu,
-    [MO_BEUW] = helper_be_stw_mmu,
-    [MO_BEUL] = helper_be_stl_mmu,
-    [MO_BEQ]  = helper_be_stq_mmu,
-};
-
-/* Perform the TLB load and compare.  Places the result of the comparison
-   in CR7, loads the addend of the TLB into R3, and returns the register
-   containing the guest address (zero-extended into R4).  Clobbers R0 and R2. */
-
-static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
-                               int mem_index, bool is_read)
-{
-    int cmp_off
-        = (is_read
-           ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
-           : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
-    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
-    TCGReg base = TCG_AREG0;
-
-    /* Extract the page index, shifted into place for tlb index.  */
-    if (TARGET_LONG_BITS == 32) {
-        /* Zero-extend the address into a place helpful for further use.  */
-        tcg_out_ext32u(s, TCG_REG_R4, addr_reg);
-        addr_reg = TCG_REG_R4;
-    } else {
-        tcg_out_rld(s, RLDICL, TCG_REG_R3, addr_reg,
-                    64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);
-    }
-
-    /* Compensate for very large offsets.  */
-    if (add_off >= 0x8000) {
-        /* Most target env are smaller than 32k; none are larger than 64k.
-           Simplify the logic here merely to offset by 0x7ff0, giving us a
-           range just shy of 64k.  Check this assumption.  */
-        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
-                                   tlb_table[NB_MMU_MODES - 1][1])
-                          > 0x7ff0 + 0x7fff);
-        tcg_out32(s, ADDI | TAI(TCG_REG_R2, base, 0x7ff0));
-        base = TCG_REG_R2;
-        cmp_off -= 0x7ff0;
-        add_off -= 0x7ff0;
-    }
-
-    /* Extraction and shifting, part 2.  */
-    if (TARGET_LONG_BITS == 32) {
-        tcg_out_rlw(s, RLWINM, TCG_REG_R3, addr_reg,
-                    32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
-                    32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),
-                    31 - CPU_TLB_ENTRY_BITS);
-    } else {
-        tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS);
-    }
-
-    tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));
-
-    /* Load the tlb comparator.  */
-    tcg_out32(s, LD_ADDR | TAI(TCG_REG_R2, TCG_REG_R3, cmp_off));
-
-    /* Load the TLB addend for use on the fast path.  Do this asap
-       to minimize any load use delay.  */
-    tcg_out32(s, LD | TAI(TCG_REG_R3, TCG_REG_R3, add_off));
-
-    /* Clear the non-page, non-alignment bits from the address.  */
-    if (TARGET_LONG_BITS == 32) {
-        tcg_out_rlw(s, RLWINM, TCG_REG_R0, addr_reg, 0,
-                    (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
-    } else if (!s_bits) {
-        tcg_out_rld(s, RLDICR, TCG_REG_R0, addr_reg, 0, 63 - TARGET_PAGE_BITS);
-    } else {
-        tcg_out_rld(s, RLDICL, TCG_REG_R0, addr_reg,
-                    64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
-        tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
-    }
-
-    tcg_out32(s, CMP | BF(7) | RA(TCG_REG_R0) | RB(TCG_REG_R2) | CMP_L);
-
-    return addr_reg;
-}
-
-/* Record the context of a call to the out of line helper code for the slow
-   path for a load or store, so that we can later generate the correct
-   helper code.  */
-static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
-                                int data_reg, int addr_reg, int mem_index,
-                                tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
-{
-    TCGLabelQemuLdst *label = new_ldst_label(s);
-
-    label->is_ld = is_ld;
-    label->opc = opc;
-    label->datalo_reg = data_reg;
-    label->addrlo_reg = addr_reg;
-    label->mem_index = mem_index;
-    label->raddr = raddr;
-    label->label_ptr[0] = label_ptr;
-}
-
-static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
-{
-    TCGMemOp opc = lb->opc;
-
-    reloc_pc14(lb->label_ptr[0], s->code_ptr);
-
-    tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
-
-    /* If the address needed to be zero-extended, we'll have already
-       placed it in R4.  The only remaining case is 64-bit guest.  */
-    tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
-
-    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
-    tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
-
-    tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
-
-    if (opc & MO_SIGN) {
-        uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
-        tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
-    } else {
-        tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
-    }
-
-    tcg_out_b(s, 0, lb->raddr);
-}
-
-static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
-{
-    TCGMemOp opc = lb->opc;
-    TCGMemOp s_bits = opc & MO_SIZE;
-
-    reloc_pc14(lb->label_ptr[0], s->code_ptr);
-
-    tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, TCG_AREG0);
-
-    /* If the address needed to be zero-extended, we'll have already
-       placed it in R4.  The only remaining case is 64-bit guest.  */
-    tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
-
-    tcg_out_rld(s, RLDICL, TCG_REG_R5, lb->datalo_reg,
-                0, 64 - (1 << (3 + s_bits)));
-    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
-    tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
-
-    tcg_out_call(s, qemu_st_helpers[opc]);
-
-    tcg_out_b(s, 0, lb->raddr);
-}
-#endif /* SOFTMMU */
-
-static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
-                            TCGMemOp opc, int mem_index)
-{
-    TCGReg rbase;
-    uint32_t insn;
-    TCGMemOp s_bits = opc & MO_SIZE;
-#ifdef CONFIG_SOFTMMU
-    tcg_insn_unit *label_ptr;
-#endif
-
-#ifdef CONFIG_SOFTMMU
-    addr_reg = tcg_out_tlb_read(s, s_bits, addr_reg, mem_index, true);
-
-    /* Load a pointer into the current opcode w/conditional branch-link. */
-    label_ptr = s->code_ptr;
-    tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
-
-    rbase = TCG_REG_R3;
-#else  /* !CONFIG_SOFTMMU */
-    rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
-    if (TARGET_LONG_BITS == 32) {
-        tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
-        addr_reg = TCG_REG_R2;
-    }
-#endif
-
-    insn = qemu_ldx_opc[opc];
-    if (!HAVE_ISA_2_06 && insn == LDBRX) {
-        tcg_out32(s, ADDI | TAI(TCG_REG_R0, addr_reg, 4));
-        tcg_out32(s, LWBRX | TAB(data_reg, rbase, addr_reg));
-        tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
-        tcg_out_rld(s, RLDIMI, data_reg, TCG_REG_R0, 32, 0);
-    } else if (insn) {
-        tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
-    } else {
-        insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
-        tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
-        insn = qemu_exts_opc[s_bits];
-        tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
-    }
-
-#ifdef CONFIG_SOFTMMU
-    add_qemu_ldst_label(s, true, opc, data_reg, addr_reg, mem_index,
-                        s->code_ptr, label_ptr);
-#endif
-}
-
-static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
-                            TCGMemOp opc, int mem_index)
-{
-    TCGReg rbase;
-    uint32_t insn;
-#ifdef CONFIG_SOFTMMU
-    tcg_insn_unit *label_ptr;
-#endif
-
-#ifdef CONFIG_SOFTMMU
-    addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
-
-    /* Load a pointer into the current opcode w/conditional branch-link. */
-    label_ptr = s->code_ptr;
-    tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
-
-    rbase = TCG_REG_R3;
-#else  /* !CONFIG_SOFTMMU */
-    rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
-    if (TARGET_LONG_BITS == 32) {
-        tcg_out_ext32u(s, TCG_REG_R2, addr_reg);
-        addr_reg = TCG_REG_R2;
-    }
-#endif
-
-    insn = qemu_stx_opc[opc];
-    if (!HAVE_ISA_2_06 && insn == STDBRX) {
-        tcg_out32(s, STWBRX | SAB(data_reg, rbase, addr_reg));
-        tcg_out32(s, ADDI | TAI(TCG_REG_R2, addr_reg, 4));
-        tcg_out_shri64(s, TCG_REG_R0, data_reg, 32);
-        tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_R2));
-    } else {
-        tcg_out32(s, insn | SAB(data_reg, rbase, addr_reg));
-    }
-
-#ifdef CONFIG_SOFTMMU
-    add_qemu_ldst_label(s, false, opc, data_reg, addr_reg, mem_index,
-                        s->code_ptr, label_ptr);
-#endif
-}
-
-#define FRAME_SIZE ((int) \
-    ((8                     /* back chain */              \
-      + 8                   /* CR */                      \
-      + 8                   /* LR */                      \
-      + 8                   /* compiler doubleword */     \
-      + 8                   /* link editor doubleword */  \
-      + 8                   /* TOC save area */           \
-      + TCG_STATIC_CALL_ARGS_SIZE                         \
-      + CPU_TEMP_BUF_NLONGS * sizeof(long)                \
-      + ARRAY_SIZE(tcg_target_callee_save_regs) * 8       \
-      + 15) & ~15))
-
-#define REG_SAVE_BOT (FRAME_SIZE - ARRAY_SIZE(tcg_target_callee_save_regs) * 8)
-
-static void tcg_target_qemu_prologue(TCGContext *s)
-{
-    int i;
-
-    tcg_set_frame(s, TCG_REG_CALL_STACK,
-                  REG_SAVE_BOT - CPU_TEMP_BUF_NLONGS * sizeof(long),
-                  CPU_TEMP_BUF_NLONGS * sizeof(long));
-
-#ifndef __APPLE__
-    /* First emit adhoc function descriptor */
-    tcg_out64(s, (uint64_t)s->code_ptr + 24); /* entry point */
-    tcg_out64(s, 0);                          /* toc */
-    tcg_out64(s, 0);                          /* environment pointer */
-#endif
-
-    /* Prologue */
-    tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
-    tcg_out32(s, STDU | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
-    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
-        tcg_out32(s, STD | SAI(tcg_target_callee_save_regs[i], 1, 
-                               REG_SAVE_BOT + i * 8));
-    }
-    tcg_out32(s, STD | SAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
-
-#ifdef CONFIG_USE_GUEST_BASE
-    if (GUEST_BASE) {
-        tcg_out_movi(s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE);
-        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
-    }
-#endif
-
-    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
-    tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
-    tcg_out32(s, BCCTR | BO_ALWAYS);
-
-    /* Epilogue */
-    tb_ret_addr = s->code_ptr;
-
-    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
-        tcg_out32(s, LD | TAI(tcg_target_callee_save_regs[i], TCG_REG_R1,
-                              REG_SAVE_BOT + i * 8));
-    }
-    tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R1, FRAME_SIZE + 16));
-    tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
-    tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
-    tcg_out32(s, BCLR | BO_ALWAYS);
-}
-
-static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
-                              TCGReg arg1, intptr_t arg2)
-{
-    int opi, opx;
-
-    if (type == TCG_TYPE_I32) {
-        opi = LWZ, opx = LWZX;
-    } else {
-        opi = LD, opx = LDX;
-    }
-    tcg_out_mem_long(s, opi, opx, ret, arg1, arg2);
-}
-
-static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
-                              TCGReg arg1, intptr_t arg2)
-{
-    int opi, opx;
-
-    if (type == TCG_TYPE_I32) {
-        opi = STW, opx = STWX;
-    } else {
-        opi = STD, opx = STDX;
-    }
-    tcg_out_mem_long(s, opi, opx, arg, arg1, arg2);
-}
-
-static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
-                        int const_arg2, int cr, TCGType type)
-{
-    int imm;
-    uint32_t op;
-
-    /* Simplify the comparisons below wrt CMPI.  */
-    if (type == TCG_TYPE_I32) {
-        arg2 = (int32_t)arg2;
-    }
-
-    switch (cond) {
-    case TCG_COND_EQ:
-    case TCG_COND_NE:
-        if (const_arg2) {
-            if ((int16_t) arg2 == arg2) {
-                op = CMPI;
-                imm = 1;
-                break;
-            } else if ((uint16_t) arg2 == arg2) {
-                op = CMPLI;
-                imm = 1;
-                break;
-            }
-        }
-        op = CMPL;
-        imm = 0;
-        break;
-
-    case TCG_COND_LT:
-    case TCG_COND_GE:
-    case TCG_COND_LE:
-    case TCG_COND_GT:
-        if (const_arg2) {
-            if ((int16_t) arg2 == arg2) {
-                op = CMPI;
-                imm = 1;
-                break;
-            }
-        }
-        op = CMP;
-        imm = 0;
-        break;
-
-    case TCG_COND_LTU:
-    case TCG_COND_GEU:
-    case TCG_COND_LEU:
-    case TCG_COND_GTU:
-        if (const_arg2) {
-            if ((uint16_t) arg2 == arg2) {
-                op = CMPLI;
-                imm = 1;
-                break;
-            }
-        }
-        op = CMPL;
-        imm = 0;
-        break;
-
-    default:
-        tcg_abort();
-    }
-    op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
-
-    if (imm) {
-        tcg_out32(s, op | RA(arg1) | (arg2 & 0xffff));
-    } else {
-        if (const_arg2) {
-            tcg_out_movi(s, type, TCG_REG_R0, arg2);
-            arg2 = TCG_REG_R0;
-        }
-        tcg_out32(s, op | RA(arg1) | RB(arg2));
-    }
-}
-
-static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
-                                TCGReg dst, TCGReg src)
-{
-    tcg_out32(s, (type == TCG_TYPE_I64 ? CNTLZD : CNTLZW) | RS(src) | RA(dst));
-    tcg_out_shri64(s, dst, dst, type == TCG_TYPE_I64 ? 6 : 5);
-}
-
-static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
-{
-    /* X != 0 implies X + -1 generates a carry.  Extra addition
-       trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C.  */
-    if (dst != src) {
-        tcg_out32(s, ADDIC | TAI(dst, src, -1));
-        tcg_out32(s, SUBFE | TAB(dst, dst, src));
-    } else {
-        tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
-        tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
-    }
-}
-
-static TCGReg tcg_gen_setcond_xor(TCGContext *s, TCGReg arg1, TCGArg arg2,
-                                  bool const_arg2)
-{
-    if (const_arg2) {
-        if ((uint32_t)arg2 == arg2) {
-            tcg_out_xori32(s, TCG_REG_R0, arg1, arg2);
-        } else {
-            tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, arg2);
-            tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, TCG_REG_R0));
-        }
-    } else {
-        tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, arg2));
-    }
-    return TCG_REG_R0;
-}
-
-static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
-                            TCGArg arg0, TCGArg arg1, TCGArg arg2,
-                            int const_arg2)
-{
-    int crop, sh;
-
-    /* Ignore high bits of a potential constant arg2.  */
-    if (type == TCG_TYPE_I32) {
-        arg2 = (uint32_t)arg2;
-    }
-
-    /* Handle common and trivial cases before handling anything else.  */
-    if (arg2 == 0) {
-        switch (cond) {
-        case TCG_COND_EQ:
-            tcg_out_setcond_eq0(s, type, arg0, arg1);
-            return;
-        case TCG_COND_NE:
-            if (type == TCG_TYPE_I32) {
-                tcg_out_ext32u(s, TCG_REG_R0, arg1);
-                arg1 = TCG_REG_R0;
-            }
-            tcg_out_setcond_ne0(s, arg0, arg1);
-            return;
-        case TCG_COND_GE:
-            tcg_out32(s, NOR | SAB(arg1, arg0, arg1));
-            arg1 = arg0;
-            /* FALLTHRU */
-        case TCG_COND_LT:
-            /* Extract the sign bit.  */
-            tcg_out_rld(s, RLDICL, arg0, arg1,
-                        type == TCG_TYPE_I64 ? 1 : 33, 63);
-            return;
-        default:
-            break;
-        }
-    }
-
-    /* If we have ISEL, we can implement everything with 3 or 4 insns.
-       All other cases below are also at least 3 insns, so speed up the
-       code generator by not considering them and always using ISEL.  */
-    if (HAVE_ISEL) {
-        int isel, tab;
-
-        tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
-
-        isel = tcg_to_isel[cond];
-
-        tcg_out_movi(s, type, arg0, 1);
-        if (isel & 1) {
-            /* arg0 = (bc ? 0 : 1) */
-            tab = TAB(arg0, 0, arg0);
-            isel &= ~1;
-        } else {
-            /* arg0 = (bc ? 1 : 0) */
-            tcg_out_movi(s, type, TCG_REG_R0, 0);
-            tab = TAB(arg0, arg0, TCG_REG_R0);
-        }
-        tcg_out32(s, isel | tab);
-        return;
-    }
-
-    switch (cond) {
-    case TCG_COND_EQ:
-        arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
-        tcg_out_setcond_eq0(s, type, arg0, arg1);
-        return;
-
-    case TCG_COND_NE:
-        arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
-        /* Discard the high bits only once, rather than both inputs.  */
-        if (type == TCG_TYPE_I32) {
-            tcg_out_ext32u(s, TCG_REG_R0, arg1);
-            arg1 = TCG_REG_R0;
-        }
-        tcg_out_setcond_ne0(s, arg0, arg1);
-        return;
-
-    case TCG_COND_GT:
-    case TCG_COND_GTU:
-        sh = 30;
-        crop = 0;
-        goto crtest;
-
-    case TCG_COND_LT:
-    case TCG_COND_LTU:
-        sh = 29;
-        crop = 0;
-        goto crtest;
-
-    case TCG_COND_GE:
-    case TCG_COND_GEU:
-        sh = 31;
-        crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT);
-        goto crtest;
-
-    case TCG_COND_LE:
-    case TCG_COND_LEU:
-        sh = 31;
-        crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
-    crtest:
-        tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
-        if (crop) {
-            tcg_out32(s, crop);
-        }
-        tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
-        tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31);
-        break;
-
-    default:
-        tcg_abort();
-    }
-}
-
-static void tcg_out_bc(TCGContext *s, int bc, int label_index)
-{
-    TCGLabel *l = &s->labels[label_index];
-
-    if (l->has_value) {
-        tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
-    } else {
-        tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
-        tcg_out_bc_noaddr(s, bc);
-    }
-}
-
-static void tcg_out_brcond(TCGContext *s, TCGCond cond,
-                           TCGArg arg1, TCGArg arg2, int const_arg2,
-                           int label_index, TCGType type)
-{
-    tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
-    tcg_out_bc(s, tcg_to_bc[cond], label_index);
-}
-
-static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
-                            TCGArg dest, TCGArg c1, TCGArg c2, TCGArg v1,
-                            TCGArg v2, bool const_c2)
-{
-    /* If for some reason both inputs are zero, don't produce bad code.  */
-    if (v1 == 0 && v2 == 0) {
-        tcg_out_movi(s, type, dest, 0);
-        return;
-    }
-
-    tcg_out_cmp(s, cond, c1, c2, const_c2, 7, type);
-
-    if (HAVE_ISEL) {
-        int isel = tcg_to_isel[cond];
-
-        /* Swap the V operands if the operation indicates inversion.  */
-        if (isel & 1) {
-            int t = v1;
-            v1 = v2;
-            v2 = t;
-            isel &= ~1;
-        }
-        /* V1 == 0 is handled by isel; V2 == 0 must be handled by hand.  */
-        if (v2 == 0) {
-            tcg_out_movi(s, type, TCG_REG_R0, 0);
-        }
-        tcg_out32(s, isel | TAB(dest, v1, v2));
-    } else {
-        if (dest == v2) {
-            cond = tcg_invert_cond(cond);
-            v2 = v1;
-        } else if (dest != v1) {
-            if (v1 == 0) {
-                tcg_out_movi(s, type, dest, 0);
-            } else {
-                tcg_out_mov(s, type, dest, v1);
-            }
-        }
-        /* Branch forward over one insn */
-        tcg_out32(s, tcg_to_bc[cond] | 8);
-        if (v2 == 0) {
-            tcg_out_movi(s, type, dest, 0);
-        } else {
-            tcg_out_mov(s, type, dest, v2);
-        }
-    }
-}
-
-void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
-{
-    TCGContext s;
-
-    s.code_buf = s.code_ptr = (tcg_insn_unit *)jmp_addr;
-    tcg_out_b(&s, 0, (tcg_insn_unit *)addr);
-    flush_icache_range(jmp_addr, jmp_addr + tcg_current_code_size(&s));
-}
-
-static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
-                       const int *const_args)
-{
-    TCGArg a0, a1, a2;
-    int c;
-
-    switch (opc) {
-    case INDEX_op_exit_tb:
-        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
-        tcg_out_b(s, 0, tb_ret_addr);
-        break;
-    case INDEX_op_goto_tb:
-        if (s->tb_jmp_offset) {
-            /* Direct jump method.  */
-            s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
-            s->code_ptr += 7;
-        } else {
-            /* Indirect jump method.  */
-            tcg_abort();
-        }
-        s->tb_next_offset[args[0]] = tcg_current_code_size(s);
-        break;
-    case INDEX_op_br:
-        {
-            TCGLabel *l = &s->labels[args[0]];
-
-            if (l->has_value) {
-                tcg_out_b(s, 0, l->u.value_ptr);
-            } else {
-                tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, args[0], 0);
-                tcg_out_b_noaddr(s, B);
-            }
-        }
-        break;
-    case INDEX_op_ld8u_i32:
-    case INDEX_op_ld8u_i64:
-        tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld8s_i32:
-    case INDEX_op_ld8s_i64:
-        tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
-        tcg_out32(s, EXTSB | RS(args[0]) | RA(args[0]));
-        break;
-    case INDEX_op_ld16u_i32:
-    case INDEX_op_ld16u_i64:
-        tcg_out_mem_long(s, LHZ, LHZX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld16s_i32:
-    case INDEX_op_ld16s_i64:
-        tcg_out_mem_long(s, LHA, LHAX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld_i32:
-    case INDEX_op_ld32u_i64:
-        tcg_out_mem_long(s, LWZ, LWZX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld32s_i64:
-        tcg_out_mem_long(s, LWA, LWAX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld_i64:
-        tcg_out_mem_long(s, LD, LDX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_st8_i32:
-    case INDEX_op_st8_i64:
-        tcg_out_mem_long(s, STB, STBX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_st16_i32:
-    case INDEX_op_st16_i64:
-        tcg_out_mem_long(s, STH, STHX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_st_i32:
-    case INDEX_op_st32_i64:
-        tcg_out_mem_long(s, STW, STWX, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_st_i64:
-        tcg_out_mem_long(s, STD, STDX, args[0], args[1], args[2]);
-        break;
-
-    case INDEX_op_add_i32:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-        do_addi_32:
-            tcg_out_mem_long(s, ADDI, ADD, a0, a1, (int32_t)a2);
-        } else {
-            tcg_out32(s, ADD | TAB(a0, a1, a2));
-        }
-        break;
-    case INDEX_op_sub_i32:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[1]) {
-            if (const_args[2]) {
-                tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2);
-            } else {
-                tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
-            }
-        } else if (const_args[2]) {
-            a2 = -a2;
-            goto do_addi_32;
-        } else {
-            tcg_out32(s, SUBF | TAB(a0, a2, a1));
-        }
-        break;
-
-    case INDEX_op_and_i32:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out_andi32(s, a0, a1, a2);
-        } else {
-            tcg_out32(s, AND | SAB(a1, a0, a2));
-        }
-        break;
-    case INDEX_op_and_i64:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out_andi64(s, a0, a1, a2);
-        } else {
-            tcg_out32(s, AND | SAB(a1, a0, a2));
-        }
-        break;
-    case INDEX_op_or_i64:
-    case INDEX_op_or_i32:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out_ori32(s, a0, a1, a2);
-        } else {
-            tcg_out32(s, OR | SAB(a1, a0, a2));
-        }
-        break;
-    case INDEX_op_xor_i64:
-    case INDEX_op_xor_i32:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out_xori32(s, a0, a1, a2);
-        } else {
-            tcg_out32(s, XOR | SAB(a1, a0, a2));
-        }
-        break;
-    case INDEX_op_andc_i32:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out_andi32(s, a0, a1, ~a2);
-        } else {
-            tcg_out32(s, ANDC | SAB(a1, a0, a2));
-        }
-        break;
-    case INDEX_op_andc_i64:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out_andi64(s, a0, a1, ~a2);
-        } else {
-            tcg_out32(s, ANDC | SAB(a1, a0, a2));
-        }
-        break;
-    case INDEX_op_orc_i32:
-        if (const_args[2]) {
-            tcg_out_ori32(s, args[0], args[1], ~args[2]);
-            break;
-        }
-        /* FALLTHRU */
-    case INDEX_op_orc_i64:
-        tcg_out32(s, ORC | SAB(args[1], args[0], args[2]));
-        break;
-    case INDEX_op_eqv_i32:
-        if (const_args[2]) {
-            tcg_out_xori32(s, args[0], args[1], ~args[2]);
-            break;
-        }
-        /* FALLTHRU */
-    case INDEX_op_eqv_i64:
-        tcg_out32(s, EQV | SAB(args[1], args[0], args[2]));
-        break;
-    case INDEX_op_nand_i32:
-    case INDEX_op_nand_i64:
-        tcg_out32(s, NAND | SAB(args[1], args[0], args[2]));
-        break;
-    case INDEX_op_nor_i32:
-    case INDEX_op_nor_i64:
-        tcg_out32(s, NOR | SAB(args[1], args[0], args[2]));
-        break;
-
-    case INDEX_op_mul_i32:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out32(s, MULLI | TAI(a0, a1, a2));
-        } else {
-            tcg_out32(s, MULLW | TAB(a0, a1, a2));
-        }
-        break;
-
-    case INDEX_op_div_i32:
-        tcg_out32(s, DIVW | TAB(args[0], args[1], args[2]));
-        break;
-
-    case INDEX_op_divu_i32:
-        tcg_out32(s, DIVWU | TAB(args[0], args[1], args[2]));
-        break;
-
-    case INDEX_op_shl_i32:
-        if (const_args[2]) {
-            tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
-        } else {
-            tcg_out32(s, SLW | SAB(args[1], args[0], args[2]));
-        }
-        break;
-    case INDEX_op_shr_i32:
-        if (const_args[2]) {
-            tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], args[2], 31);
-        } else {
-            tcg_out32(s, SRW | SAB(args[1], args[0], args[2]));
-        }
-        break;
-    case INDEX_op_sar_i32:
-        if (const_args[2]) {
-            tcg_out32(s, SRAWI | RS(args[1]) | RA(args[0]) | SH(args[2]));
-        } else {
-            tcg_out32(s, SRAW | SAB(args[1], args[0], args[2]));
-        }
-        break;
-    case INDEX_op_rotl_i32:
-        if (const_args[2]) {
-            tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31);
-        } else {
-            tcg_out32(s, RLWNM | SAB(args[1], args[0], args[2])
-                         | MB(0) | ME(31));
-        }
-        break;
-    case INDEX_op_rotr_i32:
-        if (const_args[2]) {
-            tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], 0, 31);
-        } else {
-            tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 32));
-            tcg_out32(s, RLWNM | SAB(args[1], args[0], TCG_REG_R0)
-                         | MB(0) | ME(31));
-        }
-        break;
-
-    case INDEX_op_brcond_i32:
-        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
-                       args[3], TCG_TYPE_I32);
-        break;
-
-    case INDEX_op_brcond_i64:
-        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
-                       args[3], TCG_TYPE_I64);
-        break;
-
-    case INDEX_op_neg_i32:
-    case INDEX_op_neg_i64:
-        tcg_out32(s, NEG | RT(args[0]) | RA(args[1]));
-        break;
-
-    case INDEX_op_not_i32:
-    case INDEX_op_not_i64:
-        tcg_out32(s, NOR | SAB(args[1], args[0], args[1]));
-        break;
-
-    case INDEX_op_add_i64:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-        do_addi_64:
-            tcg_out_mem_long(s, ADDI, ADD, a0, a1, a2);
-        } else {
-            tcg_out32(s, ADD | TAB(a0, a1, a2));
-        }
-        break;
-    case INDEX_op_sub_i64:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[1]) {
-            if (const_args[2]) {
-                tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2);
-            } else {
-                tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
-            }
-        } else if (const_args[2]) {
-            a2 = -a2;
-            goto do_addi_64;
-        } else {
-            tcg_out32(s, SUBF | TAB(a0, a2, a1));
-        }
-        break;
-
-    case INDEX_op_shl_i64:
-        if (const_args[2]) {
-            tcg_out_shli64(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out32(s, SLD | SAB(args[1], args[0], args[2]));
-        }
-        break;
-    case INDEX_op_shr_i64:
-        if (const_args[2]) {
-            tcg_out_shri64(s, args[0], args[1], args[2]);
-        } else {
-            tcg_out32(s, SRD | SAB(args[1], args[0], args[2]));
-        }
-        break;
-    case INDEX_op_sar_i64:
-        if (const_args[2]) {
-            int sh = SH(args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1);
-            tcg_out32(s, SRADI | RA(args[0]) | RS(args[1]) | sh);
-        } else {
-            tcg_out32(s, SRAD | SAB(args[1], args[0], args[2]));
-        }
-        break;
-    case INDEX_op_rotl_i64:
-        if (const_args[2]) {
-            tcg_out_rld(s, RLDICL, args[0], args[1], args[2], 0);
-        } else {
-            tcg_out32(s, RLDCL | SAB(args[1], args[0], args[2]) | MB64(0));
-        }
-        break;
-    case INDEX_op_rotr_i64:
-        if (const_args[2]) {
-            tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 0);
-        } else {
-            tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 64));
-            tcg_out32(s, RLDCL | SAB(args[1], args[0], TCG_REG_R0) | MB64(0));
-        }
-        break;
-
-    case INDEX_op_mul_i64:
-        a0 = args[0], a1 = args[1], a2 = args[2];
-        if (const_args[2]) {
-            tcg_out32(s, MULLI | TAI(a0, a1, a2));
-        } else {
-            tcg_out32(s, MULLD | TAB(a0, a1, a2));
-        }
-        break;
-    case INDEX_op_div_i64:
-        tcg_out32(s, DIVD | TAB(args[0], args[1], args[2]));
-        break;
-    case INDEX_op_divu_i64:
-        tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
-        break;
-
-    case INDEX_op_qemu_ld_i32:
-    case INDEX_op_qemu_ld_i64:
-        tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3]);
-        break;
-    case INDEX_op_qemu_st_i32:
-    case INDEX_op_qemu_st_i64:
-        tcg_out_qemu_st(s, args[0], args[1], args[2], args[3]);
-        break;
-
-    case INDEX_op_ext8s_i32:
-    case INDEX_op_ext8s_i64:
-        c = EXTSB;
-        goto gen_ext;
-    case INDEX_op_ext16s_i32:
-    case INDEX_op_ext16s_i64:
-        c = EXTSH;
-        goto gen_ext;
-    case INDEX_op_ext32s_i64:
-        c = EXTSW;
-        goto gen_ext;
-    gen_ext:
-        tcg_out32(s, c | RS(args[1]) | RA(args[0]));
-        break;
-
-    case INDEX_op_setcond_i32:
-        tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
-                        const_args[2]);
-        break;
-    case INDEX_op_setcond_i64:
-        tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
-                        const_args[2]);
-        break;
-
-    case INDEX_op_bswap16_i32:
-    case INDEX_op_bswap16_i64:
-        a0 = args[0], a1 = args[1];
-        /* a1 = abcd */
-        if (a0 != a1) {
-            /* a0 = (a1 r<< 24) & 0xff # 000c */
-            tcg_out_rlw(s, RLWINM, a0, a1, 24, 24, 31);
-            /* a0 = (a0 & ~0xff00) | (a1 r<< 8) & 0xff00 # 00dc */
-            tcg_out_rlw(s, RLWIMI, a0, a1, 8, 16, 23);
-        } else {
-            /* r0 = (a1 r<< 8) & 0xff00 # 00d0 */
-            tcg_out_rlw(s, RLWINM, TCG_REG_R0, a1, 8, 16, 23);
-            /* a0 = (a1 r<< 24) & 0xff # 000c */
-            tcg_out_rlw(s, RLWINM, a0, a1, 24, 24, 31);
-            /* a0 = a0 | r0 # 00dc */
-            tcg_out32(s, OR | SAB(TCG_REG_R0, a0, a0));
-        }
-        break;
-
-    case INDEX_op_bswap32_i32:
-    case INDEX_op_bswap32_i64:
-        /* Stolen from gcc's builtin_bswap32 */
-        a1 = args[1];
-        a0 = args[0] == a1 ? TCG_REG_R0 : args[0];
-
-        /* a1 = args[1] # abcd */
-        /* a0 = rotate_left (a1, 8) # bcda */
-        tcg_out_rlw(s, RLWINM, a0, a1, 8, 0, 31);
-        /* a0 = (a0 & ~0xff000000) | ((a1 r<< 24) & 0xff000000) # dcda */
-        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 0, 7);
-        /* a0 = (a0 & ~0x0000ff00) | ((a1 r<< 24) & 0x0000ff00) # dcba */
-        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 16, 23);
-
-        if (a0 == TCG_REG_R0) {
-            tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
-        }
-        break;
-
-    case INDEX_op_bswap64_i64:
-        a0 = args[0], a1 = args[1], a2 = TCG_REG_R0;
-        if (a0 == a1) {
-            a0 = TCG_REG_R0;
-            a2 = a1;
-        }
-
-        /* a1 = # abcd efgh */
-        /* a0 = rl32(a1, 8) # 0000 fghe */
-        tcg_out_rlw(s, RLWINM, a0, a1, 8, 0, 31);
-        /* a0 = dep(a0, rl32(a1, 24), 0xff000000) # 0000 hghe */
-        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 0, 7);
-        /* a0 = dep(a0, rl32(a1, 24), 0x0000ff00) # 0000 hgfe */
-        tcg_out_rlw(s, RLWIMI, a0, a1, 24, 16, 23);
-
-        /* a0 = rl64(a0, 32) # hgfe 0000 */
-        /* a2 = rl64(a1, 32) # efgh abcd */
-        tcg_out_rld(s, RLDICL, a0, a0, 32, 0);
-        tcg_out_rld(s, RLDICL, a2, a1, 32, 0);
-
-        /* a0 = dep(a0, rl32(a2, 8), 0xffffffff)  # hgfe bcda */
-        tcg_out_rlw(s, RLWIMI, a0, a2, 8, 0, 31);
-        /* a0 = dep(a0, rl32(a2, 24), 0xff000000) # hgfe dcda */
-        tcg_out_rlw(s, RLWIMI, a0, a2, 24, 0, 7);
-        /* a0 = dep(a0, rl32(a2, 24), 0x0000ff00) # hgfe dcba */
-        tcg_out_rlw(s, RLWIMI, a0, a2, 24, 16, 23);
-
-        if (a0 == 0) {
-            tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
-        }
-        break;
-
-    case INDEX_op_deposit_i32:
-        if (const_args[2]) {
-            uint32_t mask = ((2u << (args[4] - 1)) - 1) << args[3];
-            tcg_out_andi32(s, args[0], args[0], ~mask);
-        } else {
-            tcg_out_rlw(s, RLWIMI, args[0], args[2], args[3],
-                        32 - args[3] - args[4], 31 - args[3]);
-        }
-        break;
-    case INDEX_op_deposit_i64:
-        if (const_args[2]) {
-            uint64_t mask = ((2ull << (args[4] - 1)) - 1) << args[3];
-            tcg_out_andi64(s, args[0], args[0], ~mask);
-        } else {
-            tcg_out_rld(s, RLDIMI, args[0], args[2], args[3],
-                        64 - args[3] - args[4]);
-        }
-        break;
-
-    case INDEX_op_movcond_i32:
-        tcg_out_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], args[2],
-                        args[3], args[4], const_args[2]);
-        break;
-    case INDEX_op_movcond_i64:
-        tcg_out_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1], args[2],
-                        args[3], args[4], const_args[2]);
-        break;
-
-    case INDEX_op_add2_i64:
-        /* Note that the CA bit is defined based on the word size of the
-           environment.  So in 64-bit mode it's always carry-out of bit 63.
-           The fallback code using deposit works just as well for 32-bit.  */
-        a0 = args[0], a1 = args[1];
-        if (a0 == args[3] || (!const_args[5] && a0 == args[5])) {
-            a0 = TCG_REG_R0;
-        }
-        if (const_args[4]) {
-            tcg_out32(s, ADDIC | TAI(a0, args[2], args[4]));
-        } else {
-            tcg_out32(s, ADDC | TAB(a0, args[2], args[4]));
-        }
-        if (const_args[5]) {
-            tcg_out32(s, (args[5] ? ADDME : ADDZE) | RT(a1) | RA(args[3]));
-        } else {
-            tcg_out32(s, ADDE | TAB(a1, args[3], args[5]));
-        }
-        if (a0 != args[0]) {
-            tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
-        }
-        break;
-
-    case INDEX_op_sub2_i64:
-        a0 = args[0], a1 = args[1];
-        if (a0 == args[5] || (!const_args[4] && a0 == args[4])) {
-            a0 = TCG_REG_R0;
-        }
-        if (const_args[2]) {
-            tcg_out32(s, SUBFIC | TAI(a0, args[3], args[2]));
-        } else {
-            tcg_out32(s, SUBFC | TAB(a0, args[3], args[2]));
-        }
-        if (const_args[4]) {
-            tcg_out32(s, (args[4] ? SUBFME : SUBFZE) | RT(a1) | RA(args[5]));
-        } else {
-            tcg_out32(s, SUBFE | TAB(a1, args[5], args[4]));
-        }
-        if (a0 != args[0]) {
-            tcg_out_mov(s, TCG_TYPE_I64, args[0], a0);
-        }
-        break;
-
-    case INDEX_op_muluh_i64:
-        tcg_out32(s, MULHDU | TAB(args[0], args[1], args[2]));
-        break;
-    case INDEX_op_mulsh_i64:
-        tcg_out32(s, MULHD | TAB(args[0], args[1], args[2]));
-        break;
-
-    case INDEX_op_mov_i32:   /* Always emitted via tcg_out_mov.  */
-    case INDEX_op_mov_i64:
-    case INDEX_op_movi_i32:  /* Always emitted via tcg_out_movi.  */
-    case INDEX_op_movi_i64:
-    case INDEX_op_call:      /* Always emitted via tcg_out_call.  */
-    default:
-        tcg_abort();
-    }
-}
-
-static const TCGTargetOpDef ppc_op_defs[] = {
-    { INDEX_op_exit_tb, { } },
-    { INDEX_op_goto_tb, { } },
-    { INDEX_op_br, { } },
-
-    { INDEX_op_ld8u_i32, { "r", "r" } },
-    { INDEX_op_ld8s_i32, { "r", "r" } },
-    { INDEX_op_ld16u_i32, { "r", "r" } },
-    { INDEX_op_ld16s_i32, { "r", "r" } },
-    { INDEX_op_ld_i32, { "r", "r" } },
-    { INDEX_op_ld_i64, { "r", "r" } },
-    { INDEX_op_st8_i32, { "r", "r" } },
-    { INDEX_op_st8_i64, { "r", "r" } },
-    { INDEX_op_st16_i32, { "r", "r" } },
-    { INDEX_op_st16_i64, { "r", "r" } },
-    { INDEX_op_st_i32, { "r", "r" } },
-    { INDEX_op_st_i64, { "r", "r" } },
-    { INDEX_op_st32_i64, { "r", "r" } },
-
-    { INDEX_op_ld8u_i64, { "r", "r" } },
-    { INDEX_op_ld8s_i64, { "r", "r" } },
-    { INDEX_op_ld16u_i64, { "r", "r" } },
-    { INDEX_op_ld16s_i64, { "r", "r" } },
-    { INDEX_op_ld32u_i64, { "r", "r" } },
-    { INDEX_op_ld32s_i64, { "r", "r" } },
-
-    { INDEX_op_add_i32, { "r", "r", "ri" } },
-    { INDEX_op_mul_i32, { "r", "r", "rI" } },
-    { INDEX_op_div_i32, { "r", "r", "r" } },
-    { INDEX_op_divu_i32, { "r", "r", "r" } },
-    { INDEX_op_sub_i32, { "r", "rI", "ri" } },
-    { INDEX_op_and_i32, { "r", "r", "ri" } },
-    { INDEX_op_or_i32, { "r", "r", "ri" } },
-    { INDEX_op_xor_i32, { "r", "r", "ri" } },
-    { INDEX_op_andc_i32, { "r", "r", "ri" } },
-    { INDEX_op_orc_i32, { "r", "r", "ri" } },
-    { INDEX_op_eqv_i32, { "r", "r", "ri" } },
-    { INDEX_op_nand_i32, { "r", "r", "r" } },
-    { INDEX_op_nor_i32, { "r", "r", "r" } },
-
-    { INDEX_op_shl_i32, { "r", "r", "ri" } },
-    { INDEX_op_shr_i32, { "r", "r", "ri" } },
-    { INDEX_op_sar_i32, { "r", "r", "ri" } },
-    { INDEX_op_rotl_i32, { "r", "r", "ri" } },
-    { INDEX_op_rotr_i32, { "r", "r", "ri" } },
-
-    { INDEX_op_brcond_i32, { "r", "ri" } },
-    { INDEX_op_brcond_i64, { "r", "ri" } },
-
-    { INDEX_op_neg_i32, { "r", "r" } },
-    { INDEX_op_not_i32, { "r", "r" } },
-
-    { INDEX_op_add_i64, { "r", "r", "rT" } },
-    { INDEX_op_sub_i64, { "r", "rI", "rT" } },
-    { INDEX_op_and_i64, { "r", "r", "ri" } },
-    { INDEX_op_or_i64, { "r", "r", "rU" } },
-    { INDEX_op_xor_i64, { "r", "r", "rU" } },
-    { INDEX_op_andc_i64, { "r", "r", "ri" } },
-    { INDEX_op_orc_i64, { "r", "r", "r" } },
-    { INDEX_op_eqv_i64, { "r", "r", "r" } },
-    { INDEX_op_nand_i64, { "r", "r", "r" } },
-    { INDEX_op_nor_i64, { "r", "r", "r" } },
-
-    { INDEX_op_shl_i64, { "r", "r", "ri" } },
-    { INDEX_op_shr_i64, { "r", "r", "ri" } },
-    { INDEX_op_sar_i64, { "r", "r", "ri" } },
-    { INDEX_op_rotl_i64, { "r", "r", "ri" } },
-    { INDEX_op_rotr_i64, { "r", "r", "ri" } },
-
-    { INDEX_op_mul_i64, { "r", "r", "rI" } },
-    { INDEX_op_div_i64, { "r", "r", "r" } },
-    { INDEX_op_divu_i64, { "r", "r", "r" } },
-
-    { INDEX_op_neg_i64, { "r", "r" } },
-    { INDEX_op_not_i64, { "r", "r" } },
-
-    { INDEX_op_qemu_ld_i32, { "r", "L" } },
-    { INDEX_op_qemu_ld_i64, { "r", "L" } },
-    { INDEX_op_qemu_st_i32, { "S", "S" } },
-    { INDEX_op_qemu_st_i64, { "S", "S" } },
-
-    { INDEX_op_ext8s_i32, { "r", "r" } },
-    { INDEX_op_ext16s_i32, { "r", "r" } },
-    { INDEX_op_ext8s_i64, { "r", "r" } },
-    { INDEX_op_ext16s_i64, { "r", "r" } },
-    { INDEX_op_ext32s_i64, { "r", "r" } },
-
-    { INDEX_op_setcond_i32, { "r", "r", "ri" } },
-    { INDEX_op_setcond_i64, { "r", "r", "ri" } },
-    { INDEX_op_movcond_i32, { "r", "r", "ri", "rZ", "rZ" } },
-    { INDEX_op_movcond_i64, { "r", "r", "ri", "rZ", "rZ" } },
-
-    { INDEX_op_bswap16_i32, { "r", "r" } },
-    { INDEX_op_bswap16_i64, { "r", "r" } },
-    { INDEX_op_bswap32_i32, { "r", "r" } },
-    { INDEX_op_bswap32_i64, { "r", "r" } },
-    { INDEX_op_bswap64_i64, { "r", "r" } },
-
-    { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
-    { INDEX_op_deposit_i64, { "r", "0", "rZ" } },
-
-    { INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } },
-    { INDEX_op_sub2_i64, { "r", "r", "rI", "r", "rZM", "r" } },
-    { INDEX_op_mulsh_i64, { "r", "r", "r" } },
-    { INDEX_op_muluh_i64, { "r", "r", "r" } },
-
-    { -1 },
-};
-
-static void tcg_target_init(TCGContext *s)
-{
-    unsigned long hwcap = qemu_getauxval(AT_HWCAP);
-    if (hwcap & PPC_FEATURE_ARCH_2_06) {
-        have_isa_2_06 = true;
-    }
-
-    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
-    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
-    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
-                     (1 << TCG_REG_R0) |
-                     (1 << TCG_REG_R2) |
-                     (1 << TCG_REG_R3) |
-                     (1 << TCG_REG_R4) |
-                     (1 << TCG_REG_R5) |
-                     (1 << TCG_REG_R6) |
-                     (1 << TCG_REG_R7) |
-                     (1 << TCG_REG_R8) |
-                     (1 << TCG_REG_R9) |
-                     (1 << TCG_REG_R10) |
-                     (1 << TCG_REG_R11) |
-                     (1 << TCG_REG_R12));
-
-    tcg_regset_clear(s->reserved_regs);
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* tcg temp */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* stack pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* mem temp */
-#ifdef __APPLE__
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R11); /* ??? */
-#endif
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
-
-    tcg_add_target_add_op_defs(ppc_op_defs);
-}
-
-typedef struct {
-    DebugFrameCIE cie;
-    DebugFrameFDEHeader fde;
-    uint8_t fde_def_cfa[4];
-    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2 + 3];
-} DebugFrame;
-
-/* We're expecting a 2 byte uleb128 encoded value.  */
-QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
-
-#define ELF_HOST_MACHINE EM_PPC64
-
-static DebugFrame debug_frame = {
-    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
-    .cie.id = -1,
-    .cie.version = 1,
-    .cie.code_align = 1,
-    .cie.data_align = 0x78,             /* sleb128 -8 */
-    .cie.return_column = 65,
-
-    /* Total FDE size does not include the "len" member.  */
-    .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
-
-    .fde_def_cfa = {
-        12, 1,                          /* DW_CFA_def_cfa r1, ... */
-        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
-        (FRAME_SIZE >> 7)
-    },
-    .fde_reg_ofs = {
-        0x11, 65, 0x7e,                 /* DW_CFA_offset_extended_sf, lr, 16 */
-    }
-};
-
-void tcg_register_jit(void *buf, size_t buf_size)
-{
-    uint8_t *p = &debug_frame.fde_reg_ofs[3];
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i, p += 2) {
-        p[0] = 0x80 + tcg_target_callee_save_regs[i];
-        p[1] = (FRAME_SIZE - (REG_SAVE_BOT + i * 8)) / 8;
-    }
-
-    debug_frame.fde.func_start = (tcg_target_long) buf;
-    debug_frame.fde.func_len = buf_size;
-
-    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
-}
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
deleted file mode 100644
index f2360c869a..0000000000
--- a/tcg/ppc64/tcg-target.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef TCG_TARGET_PPC64 
-#define TCG_TARGET_PPC64 1
-
-#define TCG_TARGET_NB_REGS 32
-#define TCG_TARGET_INSN_UNIT_SIZE 4
-
-typedef enum {
-    TCG_REG_R0 = 0,
-    TCG_REG_R1,
-    TCG_REG_R2,
-    TCG_REG_R3,
-    TCG_REG_R4,
-    TCG_REG_R5,
-    TCG_REG_R6,
-    TCG_REG_R7,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-    TCG_REG_R11,
-    TCG_REG_R12,
-    TCG_REG_R13,
-    TCG_REG_R14,
-    TCG_REG_R15,
-    TCG_REG_R16,
-    TCG_REG_R17,
-    TCG_REG_R18,
-    TCG_REG_R19,
-    TCG_REG_R20,
-    TCG_REG_R21,
-    TCG_REG_R22,
-    TCG_REG_R23,
-    TCG_REG_R24,
-    TCG_REG_R25,
-    TCG_REG_R26,
-    TCG_REG_R27,
-    TCG_REG_R28,
-    TCG_REG_R29,
-    TCG_REG_R30,
-    TCG_REG_R31
-} TCGReg;
-
-/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_R1
-#define TCG_TARGET_STACK_ALIGN 16
-#define TCG_TARGET_CALL_STACK_OFFSET 48
-
-/* optional instructions automatically implemented */
-#define TCG_TARGET_HAS_ext8u_i32        0 /* andi */
-#define TCG_TARGET_HAS_ext16u_i32       0
-#define TCG_TARGET_HAS_ext8u_i64        0
-#define TCG_TARGET_HAS_ext16u_i64       0
-#define TCG_TARGET_HAS_ext32u_i64       0
-
-/* optional instructions */
-#define TCG_TARGET_HAS_div_i32          1
-#define TCG_TARGET_HAS_rem_i32          0
-#define TCG_TARGET_HAS_rot_i32          1
-#define TCG_TARGET_HAS_ext8s_i32        1
-#define TCG_TARGET_HAS_ext16s_i32       1
-#define TCG_TARGET_HAS_bswap16_i32      1
-#define TCG_TARGET_HAS_bswap32_i32      1
-#define TCG_TARGET_HAS_not_i32          1
-#define TCG_TARGET_HAS_neg_i32          1
-#define TCG_TARGET_HAS_andc_i32         1
-#define TCG_TARGET_HAS_orc_i32          1
-#define TCG_TARGET_HAS_eqv_i32          1
-#define TCG_TARGET_HAS_nand_i32         1
-#define TCG_TARGET_HAS_nor_i32          1
-#define TCG_TARGET_HAS_deposit_i32      1
-#define TCG_TARGET_HAS_movcond_i32      1
-#define TCG_TARGET_HAS_add2_i32         0
-#define TCG_TARGET_HAS_sub2_i32         0
-#define TCG_TARGET_HAS_mulu2_i32        0
-#define TCG_TARGET_HAS_muls2_i32        0
-#define TCG_TARGET_HAS_muluh_i32        0
-#define TCG_TARGET_HAS_mulsh_i32        0
-#define TCG_TARGET_HAS_trunc_shr_i32    0
-
-#define TCG_TARGET_HAS_div_i64          1
-#define TCG_TARGET_HAS_rem_i64          0
-#define TCG_TARGET_HAS_rot_i64          1
-#define TCG_TARGET_HAS_ext8s_i64        1
-#define TCG_TARGET_HAS_ext16s_i64       1
-#define TCG_TARGET_HAS_ext32s_i64       1
-#define TCG_TARGET_HAS_bswap16_i64      1
-#define TCG_TARGET_HAS_bswap32_i64      1
-#define TCG_TARGET_HAS_bswap64_i64      1
-#define TCG_TARGET_HAS_not_i64          1
-#define TCG_TARGET_HAS_neg_i64          1
-#define TCG_TARGET_HAS_andc_i64         1
-#define TCG_TARGET_HAS_orc_i64          1
-#define TCG_TARGET_HAS_eqv_i64          1
-#define TCG_TARGET_HAS_nand_i64         1
-#define TCG_TARGET_HAS_nor_i64          1
-#define TCG_TARGET_HAS_deposit_i64      1
-#define TCG_TARGET_HAS_movcond_i64      1
-#define TCG_TARGET_HAS_add2_i64         1
-#define TCG_TARGET_HAS_sub2_i64         1
-#define TCG_TARGET_HAS_mulu2_i64        0
-#define TCG_TARGET_HAS_muls2_i64        0
-#define TCG_TARGET_HAS_muluh_i64        1
-#define TCG_TARGET_HAS_mulsh_i64        1
-
-#define TCG_AREG0 TCG_REG_R27
-
-#define TCG_TARGET_EXTEND_ARGS 1
-
-#endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index dae4b7cb00..815eec1a78 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -37,7 +37,6 @@
 #endif
 
 #include "qemu-common.h"
-#include "qemu/cache-utils.h"
 #include "qemu/host-utils.h"
 #include "qemu/timer.h"
 
diff --git a/tests/Makefile b/tests/Makefile
index 4caf7deb89..7e53d0d618 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -27,6 +27,8 @@ check-unit-y += tests/test-string-input-visitor$(EXESUF)
 gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
 check-unit-y += tests/test-string-output-visitor$(EXESUF)
 gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c
+check-unit-y += tests/test-qmp-event$(EXESUF)
+gcov-files-test-qmp-event-y += qapi/qmp-event.c
 check-unit-y += tests/test-opts-visitor$(EXESUF)
 gcov-files-test-opts-visitor-y = qapi/opts-visitor.c
 check-unit-y += tests/test-coroutine$(EXESUF)
@@ -199,9 +201,10 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
         include-simple.json include-relpath.json include-format-err.json \
         include-non-file.json include-no-file.json include-before-err.json \
         include-nested-err.json include-self-cycle.json include-cycle.json \
-        include-repetition.json)
+        include-repetition.json event-nest-struct.json)
 
-GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
+GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h \
+                     tests/test-qmp-commands.h tests/test-qapi-event.h
 
 test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
 	tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
@@ -210,9 +213,10 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
 	tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
 	tests/test-qmp-commands.o tests/test-visitor-serialization.o \
 	tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
-	tests/test-opts-visitor.o
+	tests/test-opts-visitor.o tests/test-qmp-event.o
 
-test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o
+test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
+                  tests/test-qapi-event.o
 
 $(test-obj-y): QEMU_INCLUDES += -Itests
 QEMU_CFLAGS += -I$(SRC_PATH)/tests
@@ -264,9 +268,15 @@ $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-com
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
 		$(gen-out-type) -o tests -p "test-" -i $<, \
 		"  GEN   $@")
+tests/test-qapi-event.c tests/test-qapi-event.h :\
+$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
+		$(gen-out-type) -o tests -p "test-" -i $<, \
+		"  GEN   $@")
 
 tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
 tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
+tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
 tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
 tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
 tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 4e74548109..95497a037e 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -45,6 +45,13 @@ static void escaped_string(void)
         { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
         { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
         { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
+        { "'\\b'", "\b", .skip = 1 },
+        { "'\\f'", "\f", .skip = 1 },
+        { "'\\n'", "\n", .skip = 1 },
+        { "'\\r'", "\r", .skip = 1 },
+        { "'\\t'", "\t", .skip = 1 },
+        { "'\\/'", "/", .skip = 1 },
+        { "'\\\\'", "\\", .skip = 1 },
         {}
     };
 
diff --git a/tests/qapi-schema/event-nest-struct.err b/tests/qapi-schema/event-nest-struct.err
new file mode 100644
index 0000000000..e4a0faac9c
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.err
@@ -0,0 +1 @@
+tests/qapi-schema/event-nest-struct.json:1: Nested structure define in event is not supported now, event 'EVENT_A', argname 'a'
diff --git a/tests/qapi-schema/event-nest-struct.exit b/tests/qapi-schema/event-nest-struct.exit
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/event-nest-struct.json b/tests/qapi-schema/event-nest-struct.json
new file mode 100644
index 0000000000..ee6f3ecb6f
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.json
@@ -0,0 +1,2 @@
+{ 'event': 'EVENT_A',
+  'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/event-nest-struct.out b/tests/qapi-schema/event-nest-struct.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.out
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 818c06dc75..ab4d3d96b6 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -89,3 +89,15 @@
     '*u16' : [ 'uint16' ],
     '*i64x':   'int'     ,
     '*u64x':   'uint64'  } }
+
+# testing event
+{ 'type': 'EventStructOne',
+  'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
+
+{ 'event': 'EVENT_A' }
+{ 'event': 'EVENT_B',
+  'data': { } }
+{ 'event': 'EVENT_C',
+  'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
+{ 'event': 'EVENT_D',
+  'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 6cd03f31c3..95e989925b 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -15,7 +15,12 @@
  OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 'UserDefOne')]))]),
  OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 'UserDefOne'), ('*ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]),
  OrderedDict([('command', 'user_def_cmd3'), ('data', OrderedDict([('a', 'int'), ('*b', 'int')])), ('returns', 'int')]),
- OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
+ OrderedDict([('type', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))]),
+ OrderedDict([('event', 'EVENT_A')]),
+ OrderedDict([('event', 'EVENT_B'), ('data', OrderedDict())]),
+ OrderedDict([('event', 'EVENT_C'), ('data', OrderedDict([('*a', 'int'), ('*b', 'UserDefOne'), ('c', 'str')]))]),
+ OrderedDict([('event', 'EVENT_D'), ('data', OrderedDict([('a', 'EventStructOne'), ('b', 'str'), ('*c', 'str'), ('*enum3', 'EnumOne')]))])]
 [{'enum_name': 'EnumOne', 'enum_values': ['value1', 'value2', 'value3']},
  {'enum_name': 'UserDefUnionKind', 'enum_values': None},
  {'enum_name': 'UserDefAnonUnionKind', 'enum_values': None},
@@ -28,4 +33,5 @@
  OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
  OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
  OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
- OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
+ OrderedDict([('type', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))])]
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
new file mode 100644
index 0000000000..cb1e4418ec
--- /dev/null
+++ b/tests/test-qmp-event.c
@@ -0,0 +1,265 @@
+/*
+ * qapi event unit-tests.
+ *
+ * Copyright (c) 2014 Wenchao Xia
+ *
+ * Authors:
+ *  Wenchao Xia   <wenchaoqemu@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qemu-common.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "test-qapi-event.h"
+#include "qapi/qmp/types.h"
+#include "qapi/qmp/qint.h"
+#include "qapi/qmp/qobject.h"
+#include "qapi/qmp-event.h"
+
+typedef struct TestEventData {
+    QDict *expect;
+} TestEventData;
+
+typedef struct QDictCmpData {
+    QDict *expect;
+    bool result;
+} QDictCmpData;
+
+TestEventData *test_event_data;
+static CompatGMutex test_event_lock;
+
+/* Only compares bool, int, string */
+static
+void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
+
+{
+    QObject *obj2;
+    QDictCmpData d_new, *d = opaque;
+
+    if (!d->result) {
+        return;
+    }
+
+    obj2 = qdict_get(d->expect, key);
+    if (!obj2) {
+        d->result = false;
+        return;
+    }
+
+    if (qobject_type(obj1) != qobject_type(obj2)) {
+        d->result = false;
+        return;
+    }
+
+    switch (qobject_type(obj1)) {
+    case QTYPE_QBOOL:
+        d->result = (qbool_get_int(qobject_to_qbool(obj1)) ==
+                     qbool_get_int(qobject_to_qbool(obj2)));
+        return;
+    case QTYPE_QINT:
+        d->result = (qint_get_int(qobject_to_qint(obj1)) ==
+                     qint_get_int(qobject_to_qint(obj2)));
+        return;
+    case QTYPE_QSTRING:
+        d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
+                              qstring_get_str(qobject_to_qstring(obj2))) == 0;
+        return;
+    case QTYPE_QDICT:
+        d_new.expect = qobject_to_qdict(obj2);
+        d_new.result = true;
+        qdict_iter(qobject_to_qdict(obj1), qdict_cmp_do_simple, &d_new);
+        d->result = d_new.result;
+        return;
+    default:
+        abort();
+    }
+}
+
+static bool qdict_cmp_simple(QDict *a, QDict *b)
+{
+    QDictCmpData d;
+
+    d.expect = b;
+    d.result = true;
+    qdict_iter(a, qdict_cmp_do_simple, &d);
+    return d.result;
+}
+
+/* This function is hooked as final emit function, which can verify the
+   correctness. */
+static void event_test_emit(TEST_QAPIEvent event, QDict *d, Error **errp)
+{
+    QObject *obj;
+    QDict *t;
+    int64_t s, ms;
+
+    /* Verify that we have timestamp, then remove it to compare other fields */
+    obj = qdict_get(d, "timestamp");
+    g_assert(obj);
+    t = qobject_to_qdict(obj);
+    g_assert(t);
+    obj = qdict_get(t, "seconds");
+    g_assert(obj && qobject_type(obj) == QTYPE_QINT);
+    s = qint_get_int(qobject_to_qint(obj));
+    obj = qdict_get(t, "microseconds");
+    g_assert(obj && qobject_type(obj) == QTYPE_QINT);
+    ms = qint_get_int(qobject_to_qint(obj));
+    if (s == -1) {
+        g_assert(ms == -1);
+    } else {
+        g_assert(ms >= 0 && ms <= 999999);
+    }
+    g_assert(qdict_size(t) == 2);
+
+    qdict_del(d, "timestamp");
+
+    g_assert(qdict_cmp_simple(d, test_event_data->expect));
+
+}
+
+static void event_prepare(TestEventData *data,
+                          const void *unused)
+{
+    /* Global variable test_event_data was used to pass the expectation, so
+       test cases can't be executed at same time. */
+    g_mutex_lock(&test_event_lock);
+
+    data->expect = qdict_new();
+    test_event_data = data;
+}
+
+static void event_teardown(TestEventData *data,
+                           const void *unused)
+{
+    QDECREF(data->expect);
+    test_event_data = NULL;
+
+    g_mutex_unlock(&test_event_lock);
+}
+
+static void event_test_add(const char *testpath,
+                           void (*test_func)(TestEventData *data,
+                                             const void *user_data))
+{
+    g_test_add(testpath, TestEventData, NULL, event_prepare, test_func,
+               event_teardown);
+}
+
+
+/* Test cases */
+
+static void test_event_a(TestEventData *data,
+                         const void *unused)
+{
+    QDict *d;
+    d = data->expect;
+    qdict_put(d, "event", qstring_from_str("EVENT_A"));
+    qapi_event_send_event_a(&error_abort);
+}
+
+static void test_event_b(TestEventData *data,
+                         const void *unused)
+{
+    QDict *d;
+    d = data->expect;
+    qdict_put(d, "event", qstring_from_str("EVENT_B"));
+    qapi_event_send_event_b(&error_abort);
+}
+
+static void test_event_c(TestEventData *data,
+                         const void *unused)
+{
+    QDict *d, *d_data, *d_b;
+
+    UserDefOne b;
+    UserDefZero z;
+    z.integer = 2;
+    b.base = &z;
+    b.string = g_strdup("test1");
+    b.has_enum1 = false;
+
+    d_b = qdict_new();
+    qdict_put(d_b, "integer", qint_from_int(2));
+    qdict_put(d_b, "string", qstring_from_str("test1"));
+
+    d_data = qdict_new();
+    qdict_put(d_data, "a", qint_from_int(1));
+    qdict_put(d_data, "b", d_b);
+    qdict_put(d_data, "c", qstring_from_str("test2"));
+
+    d = data->expect;
+    qdict_put(d, "event", qstring_from_str("EVENT_C"));
+    qdict_put(d, "data", d_data);
+
+    qapi_event_send_event_c(true, 1, true, &b, "test2", &error_abort);
+
+    g_free(b.string);
+}
+
+/* Complex type */
+static void test_event_d(TestEventData *data,
+                         const void *unused)
+{
+    UserDefOne struct1;
+    EventStructOne a;
+    UserDefZero z;
+    QDict *d, *d_data, *d_a, *d_struct1;
+
+    z.integer = 2;
+    struct1.base = &z;
+    struct1.string = g_strdup("test1");
+    struct1.has_enum1 = true;
+    struct1.enum1 = ENUM_ONE_VALUE1;
+
+    a.struct1 = &struct1;
+    a.string = g_strdup("test2");
+    a.has_enum2 = true;
+    a.enum2 = ENUM_ONE_VALUE2;
+
+    d_struct1 = qdict_new();
+    qdict_put(d_struct1, "integer", qint_from_int(2));
+    qdict_put(d_struct1, "string", qstring_from_str("test1"));
+    qdict_put(d_struct1, "enum1", qstring_from_str("value1"));
+
+    d_a = qdict_new();
+    qdict_put(d_a, "struct1", d_struct1);
+    qdict_put(d_a, "string", qstring_from_str("test2"));
+    qdict_put(d_a, "enum2", qstring_from_str("value2"));
+
+    d_data = qdict_new();
+    qdict_put(d_data, "a", d_a);
+    qdict_put(d_data, "b", qstring_from_str("test3"));
+    qdict_put(d_data, "enum3", qstring_from_str("value3"));
+
+    d = data->expect;
+    qdict_put(d, "event", qstring_from_str("EVENT_D"));
+    qdict_put(d, "data", d_data);
+
+    qapi_event_send_event_d(&a, "test3", false, NULL, true, ENUM_ONE_VALUE3,
+                           &error_abort);
+
+    g_free(struct1.string);
+    g_free(a.string);
+}
+
+int main(int argc, char **argv)
+{
+    qmp_event_set_func_emit(event_test_emit);
+
+    g_test_init(&argc, &argv, NULL);
+
+    event_test_add("/event/event_a", test_event_a);
+    event_test_add("/event/event_b", test_event_b);
+    event_test_add("/event/event_c", test_event_c);
+    event_test_add("/event/event_d", test_event_d);
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 7c826b49e5..2af2381a1d 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -8,17 +8,30 @@
  *
  */
 
+#define QEMU_GLIB_COMPAT_H
+#include <glib.h>
+
 #include "libqtest.h"
 #include "qemu/option.h"
 #include "sysemu/char.h"
 #include "sysemu/sysemu.h"
 
-#include <glib.h>
 #include <linux/vhost.h>
 #include <sys/mman.h>
 #include <sys/vfs.h>
 #include <qemu/sockets.h>
 
+/* GLIB version compatibility flags */
+#if GLIB_CHECK_VERSION(2, 28, 0)
+#define HAVE_MONOTONIC_TIME
+#endif
+
+#if GLIB_CHECK_VERSION(2, 32, 0)
+#define HAVE_MUTEX_INIT
+#define HAVE_COND_INIT
+#define HAVE_THREAD_NEW
+#endif
+
 #define QEMU_CMD_ACCEL  " -machine accel=tcg"
 #define QEMU_CMD_MEM    " -m 512 -object memory-backend-file,id=mem,size=512M,"\
                         "mem-path=%s,share=on -numa node,memdev=mem"
@@ -95,8 +108,93 @@ static VhostUserMsg m __attribute__ ((unused));
 
 int fds_num = 0, fds[VHOST_MEMORY_MAX_NREGIONS];
 static VhostUserMemory memory;
-static GMutex data_mutex;
-static GCond data_cond;
+static GMutex *data_mutex;
+static GCond *data_cond;
+
+static gint64 _get_time(void)
+{
+#ifdef HAVE_MONOTONIC_TIME
+    return g_get_monotonic_time();
+#else
+    GTimeVal time;
+    g_get_current_time(&time);
+
+    return time.tv_sec * G_TIME_SPAN_SECOND + time.tv_usec;
+#endif
+}
+
+static GMutex *_mutex_new(void)
+{
+    GMutex *mutex;
+
+#ifdef HAVE_MUTEX_INIT
+    mutex = g_new(GMutex, 1);
+    g_mutex_init(mutex);
+#else
+    mutex = g_mutex_new();
+#endif
+
+    return mutex;
+}
+
+static void _mutex_free(GMutex *mutex)
+{
+#ifdef HAVE_MUTEX_INIT
+    g_mutex_clear(mutex);
+    g_free(mutex);
+#else
+    g_mutex_free(mutex);
+#endif
+}
+
+static GCond *_cond_new(void)
+{
+    GCond *cond;
+
+#ifdef HAVE_COND_INIT
+    cond = g_new(GCond, 1);
+    g_cond_init(cond);
+#else
+    cond = g_cond_new();
+#endif
+
+    return cond;
+}
+
+static gboolean _cond_wait_until(GCond *cond, GMutex *mutex, gint64 end_time)
+{
+    gboolean ret = FALSE;
+#ifdef HAVE_COND_INIT
+    ret = g_cond_wait_until(cond, mutex, end_time);
+#else
+    GTimeVal time = { end_time / G_TIME_SPAN_SECOND,
+                      end_time % G_TIME_SPAN_SECOND };
+    ret = g_cond_timed_wait(cond, mutex, &time);
+#endif
+    return ret;
+}
+
+static void _cond_free(GCond *cond)
+{
+#ifdef HAVE_COND_INIT
+    g_cond_clear(cond);
+    g_free(cond);
+#else
+    g_cond_free(cond);
+#endif
+}
+
+static GThread *_thread_new(const gchar *name, GThreadFunc func, gpointer data)
+{
+    GThread *thread = NULL;
+    GError *error = NULL;
+#ifdef HAVE_THREAD_NEW
+    thread = g_thread_try_new(name, func, data, &error);
+#else
+    thread = g_thread_create(func, data, TRUE, &error);
+#endif
+    return thread;
+}
 
 static void read_guest_mem(void)
 {
@@ -104,11 +202,11 @@ static void read_guest_mem(void)
     gint64 end_time;
     int i, j;
 
-    g_mutex_lock(&data_mutex);
+    g_mutex_lock(data_mutex);
 
-    end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+    end_time = _get_time() + 5 * G_TIME_SPAN_SECOND;
     while (!fds_num) {
-        if (!g_cond_wait_until(&data_cond, &data_mutex, end_time)) {
+        if (!_cond_wait_until(data_cond, data_mutex, end_time)) {
             /* timeout has passed */
             g_assert(fds_num);
             break;
@@ -143,7 +241,7 @@ static void read_guest_mem(void)
     }
 
     g_assert_cmpint(1, ==, 1);
-    g_mutex_unlock(&data_mutex);
+    g_mutex_unlock(data_mutex);
 }
 
 static void *thread_function(void *data)
@@ -171,6 +269,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         return;
     }
 
+    g_mutex_lock(data_mutex);
     memcpy(p, buf, VHOST_USER_HDR_SIZE);
 
     if (msg.size) {
@@ -203,8 +302,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         fds_num = qemu_chr_fe_get_msgfds(chr, fds, sizeof(fds) / sizeof(int));
 
         /* signal the test that it can continue */
-        g_cond_signal(&data_cond);
-        g_mutex_unlock(&data_mutex);
+        g_cond_signal(data_cond);
         break;
 
     case VHOST_USER_SET_VRING_KICK:
@@ -221,6 +319,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
     default:
         break;
     }
+    g_mutex_unlock(data_mutex);
 }
 
 static const char *init_hugepagefs(void)
@@ -285,10 +384,9 @@ int main(int argc, char **argv)
     qemu_chr_add_handlers(chr, chr_can_read, chr_read, NULL, chr);
 
     /* run the main loop thread so the chardev may operate */
-    g_mutex_init(&data_mutex);
-    g_cond_init(&data_cond);
-    g_mutex_lock(&data_mutex);
-    g_thread_new(NULL, thread_function, NULL);
+    data_mutex = _mutex_new();
+    data_cond = _cond_new();
+    _thread_new(NULL, thread_function, NULL);
 
     qemu_cmd = g_strdup_printf(QEMU_CMD, hugefs, socket_path);
     s = qtest_start(qemu_cmd);
@@ -305,8 +403,8 @@ int main(int argc, char **argv)
     /* cleanup */
     unlink(socket_path);
     g_free(socket_path);
-    g_cond_clear(&data_cond);
-    g_mutex_clear(&data_mutex);
+    _cond_free(data_cond);
+    _mutex_free(data_mutex);
 
     return ret;
 }
diff --git a/ui/console.c b/ui/console.c
index 7dc4c1414c..ab8454903c 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1821,7 +1821,7 @@ static CharDriverState *text_console_init(ChardevVC *vc)
     unsigned width = 0;
     unsigned height = 0;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = qemu_chr_alloc();
 
     if (vc->has_width) {
         width = vc->width;
diff --git a/ui/spice-core.c b/ui/spice-core.c
index d10818a925..70df4460e4 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -35,9 +35,9 @@
 #include "qapi/qmp/qjson.h"
 #include "qemu/notify.h"
 #include "migration/migration.h"
-#include "monitor/monitor.h"
 #include "hw/hw.h"
 #include "ui/spice-display.h"
+#include "qapi-event.h"
 
 /* core bits */
 
@@ -174,39 +174,34 @@ static void channel_list_del(SpiceChannelEventInfo *info)
     }
 }
 
-static void add_addr_info(QDict *dict, struct sockaddr *addr, int len)
+static void add_addr_info(SpiceBasicInfo *info, struct sockaddr *addr, int len)
 {
     char host[NI_MAXHOST], port[NI_MAXSERV];
-    const char *family;
 
     getnameinfo(addr, len, host, sizeof(host), port, sizeof(port),
                 NI_NUMERICHOST | NI_NUMERICSERV);
-    family = inet_strfamily(addr->sa_family);
 
-    qdict_put(dict, "host", qstring_from_str(host));
-    qdict_put(dict, "port", qstring_from_str(port));
-    qdict_put(dict, "family", qstring_from_str(family));
+    info->host = g_strdup(host);
+    info->port = g_strdup(port);
+    info->family = inet_netfamily(addr->sa_family);
 }
 
-static void add_channel_info(QDict *dict, SpiceChannelEventInfo *info)
+static void add_channel_info(SpiceChannel *sc, SpiceChannelEventInfo *info)
 {
     int tls = info->flags & SPICE_CHANNEL_EVENT_FLAG_TLS;
 
-    qdict_put(dict, "connection-id", qint_from_int(info->connection_id));
-    qdict_put(dict, "channel-type", qint_from_int(info->type));
-    qdict_put(dict, "channel-id", qint_from_int(info->id));
-    qdict_put(dict, "tls", qbool_from_int(tls));
+    sc->connection_id = info->connection_id;
+    sc->channel_type = info->type;
+    sc->channel_id = info->id;
+    sc->tls = !!tls;
 }
 
 static void channel_event(int event, SpiceChannelEventInfo *info)
 {
-    static const int qevent[] = {
-        [ SPICE_CHANNEL_EVENT_CONNECTED    ] = QEVENT_SPICE_CONNECTED,
-        [ SPICE_CHANNEL_EVENT_INITIALIZED  ] = QEVENT_SPICE_INITIALIZED,
-        [ SPICE_CHANNEL_EVENT_DISCONNECTED ] = QEVENT_SPICE_DISCONNECTED,
-    };
-    QDict *server, *client;
-    QObject *data;
+    SpiceServerInfo *server = g_malloc0(sizeof(*server));
+    SpiceChannel *client = g_malloc0(sizeof(*client));
+    server->base = g_malloc0(sizeof(*server->base));
+    client->base = g_malloc0(sizeof(*client->base));
 
     /*
      * Spice server might have called us from spice worker thread
@@ -222,36 +217,43 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
         qemu_mutex_lock_iothread();
     }
 
-    client = qdict_new();
-    server = qdict_new();
-
     if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
-        add_addr_info(client, (struct sockaddr *)&info->paddr_ext,
+        add_addr_info(client->base, (struct sockaddr *)&info->paddr_ext,
                       info->plen_ext);
-        add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
+        add_addr_info(server->base, (struct sockaddr *)&info->laddr_ext,
                       info->llen_ext);
     } else {
         error_report("spice: %s, extended address is expected",
                      __func__);
     }
 
-    if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
-        qdict_put(server, "auth", qstring_from_str(auth));
+    switch (event) {
+    case SPICE_CHANNEL_EVENT_CONNECTED:
+        qapi_event_send_spice_connected(server->base, client->base, &error_abort);
+        break;
+    case SPICE_CHANNEL_EVENT_INITIALIZED:
+        if (auth) {
+            server->has_auth = true;
+            server->auth = g_strdup(auth);
+        }
         add_channel_info(client, info);
         channel_list_add(info);
-    }
-    if (event == SPICE_CHANNEL_EVENT_DISCONNECTED) {
+        qapi_event_send_spice_initialized(server, client, &error_abort);
+        break;
+    case SPICE_CHANNEL_EVENT_DISCONNECTED:
         channel_list_del(info);
+        qapi_event_send_spice_disconnected(server->base, client->base, &error_abort);
+        break;
+    default:
+        break;
     }
 
-    data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
-                              QOBJECT(client), QOBJECT(server));
-    monitor_protocol_event(qevent[event], data);
-    qobject_decref(data);
-
     if (need_lock) {
         qemu_mutex_unlock_iothread();
     }
+
+    qapi_free_SpiceServerInfo(server);
+    qapi_free_SpiceChannel(client);
 }
 
 static SpiceCoreInterface core_interface = {
@@ -305,7 +307,7 @@ static void migrate_connect_complete_cb(SpiceMigrateInstance *sin)
 
 static void migrate_end_complete_cb(SpiceMigrateInstance *sin)
 {
-    monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL);
+    qapi_event_send_spice_migrate_completed(&error_abort);
     spice_migration_completed = true;
 }
 
@@ -391,15 +393,16 @@ static SpiceChannelList *qmp_query_spice_channels(void)
 
         chan = g_malloc0(sizeof(*chan));
         chan->value = g_malloc0(sizeof(*chan->value));
+        chan->value->base = g_malloc0(sizeof(*chan->value->base));
 
         paddr = (struct sockaddr *)&item->info->paddr_ext;
         plen = item->info->plen_ext;
         getnameinfo(paddr, plen,
                     host, sizeof(host), port, sizeof(port),
                     NI_NUMERICHOST | NI_NUMERICSERV);
-        chan->value->host = g_strdup(host);
-        chan->value->port = g_strdup(port);
-        chan->value->family = g_strdup(inet_strfamily(paddr->sa_family));
+        chan->value->base->host = g_strdup(host);
+        chan->value->base->port = g_strdup(port);
+        chan->value->base->family = inet_netfamily(paddr->sa_family);
 
         chan->value->connection_id = item->info->connection_id;
         chan->value->channel_type = item->info->type;
diff --git a/ui/vnc.c b/ui/vnc.c
index aac93f0e17..14a86c36ce 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -35,6 +35,7 @@
 #include "qmp-commands.h"
 #include "qemu/osdep.h"
 #include "ui/input.h"
+#include "qapi-event.h"
 
 #define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT
 #define VNC_REFRESH_INTERVAL_INC  50
@@ -124,9 +125,10 @@ char *vnc_socket_remote_addr(const char *format, int fd) {
     return addr_to_string(format, &sa, salen);
 }
 
-static int put_addr_qdict(QDict *qdict, struct sockaddr_storage *sa,
-                          socklen_t salen)
+static VncBasicInfo *vnc_basic_info_get(struct sockaddr_storage *sa,
+                                        socklen_t salen)
 {
+    VncBasicInfo *info;
     char host[NI_MAXHOST];
     char serv[NI_MAXSERV];
     int err;
@@ -137,40 +139,40 @@ static int put_addr_qdict(QDict *qdict, struct sockaddr_storage *sa,
                            NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
         VNC_DEBUG("Cannot resolve address %d: %s\n",
                   err, gai_strerror(err));
-        return -1;
+        return NULL;
     }
 
-    qdict_put(qdict, "host", qstring_from_str(host));
-    qdict_put(qdict, "service", qstring_from_str(serv));
-    qdict_put(qdict, "family",qstring_from_str(inet_strfamily(sa->ss_family)));
-
-    return 0;
+    info = g_malloc0(sizeof(VncBasicInfo));
+    info->host = g_strdup(host);
+    info->service = g_strdup(serv);
+    info->family = inet_netfamily(sa->ss_family);
+    return info;
 }
 
-static int vnc_server_addr_put(QDict *qdict, int fd)
+static VncBasicInfo *vnc_basic_info_get_from_server_addr(int fd)
 {
     struct sockaddr_storage sa;
     socklen_t salen;
 
     salen = sizeof(sa);
     if (getsockname(fd, (struct sockaddr*)&sa, &salen) < 0) {
-        return -1;
+        return NULL;
     }
 
-    return put_addr_qdict(qdict, &sa, salen);
+    return vnc_basic_info_get(&sa, salen);
 }
 
-static int vnc_qdict_remote_addr(QDict *qdict, int fd)
+static VncBasicInfo *vnc_basic_info_get_from_remote_addr(int fd)
 {
     struct sockaddr_storage sa;
     socklen_t salen;
 
     salen = sizeof(sa);
     if (getpeername(fd, (struct sockaddr*)&sa, &salen) < 0) {
-        return -1;
+        return NULL;
     }
 
-    return put_addr_qdict(qdict, &sa, salen);
+    return vnc_basic_info_get(&sa, salen);
 }
 
 static const char *vnc_auth_name(VncDisplay *vd) {
@@ -224,81 +226,82 @@ static const char *vnc_auth_name(VncDisplay *vd) {
     return "unknown";
 }
 
-static int vnc_server_info_put(QDict *qdict)
+static VncServerInfo *vnc_server_info_get(void)
 {
-    if (vnc_server_addr_put(qdict, vnc_display->lsock) < 0) {
-        return -1;
+    VncServerInfo *info;
+    VncBasicInfo *bi = vnc_basic_info_get_from_server_addr(vnc_display->lsock);
+    if (!bi) {
+        return NULL;
     }
 
-    qdict_put(qdict, "auth", qstring_from_str(vnc_auth_name(vnc_display)));
-    return 0;
+    info = g_malloc(sizeof(*info));
+    info->base = bi;
+    info->has_auth = true;
+    info->auth = g_strdup(vnc_auth_name(vnc_display));
+    return info;
 }
 
 static void vnc_client_cache_auth(VncState *client)
 {
-#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
-    QDict *qdict;
-#endif
-
     if (!client->info) {
         return;
     }
 
-#if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
-    qdict = qobject_to_qdict(client->info);
-#endif
-
 #ifdef CONFIG_VNC_TLS
     if (client->tls.session &&
         client->tls.dname) {
-        qdict_put(qdict, "x509_dname", qstring_from_str(client->tls.dname));
+        client->info->has_x509_dname = true;
+        client->info->x509_dname = g_strdup(client->tls.dname);
     }
 #endif
 #ifdef CONFIG_VNC_SASL
     if (client->sasl.conn &&
         client->sasl.username) {
-        qdict_put(qdict, "sasl_username",
-                  qstring_from_str(client->sasl.username));
+        client->info->has_sasl_username = true;
+        client->info->sasl_username = g_strdup(client->sasl.username);
     }
 #endif
 }
 
 static void vnc_client_cache_addr(VncState *client)
 {
-    QDict *qdict;
+    VncBasicInfo *bi = vnc_basic_info_get_from_remote_addr(client->csock);
 
-    qdict = qdict_new();
-    if (vnc_qdict_remote_addr(qdict, client->csock) < 0) {
-        QDECREF(qdict);
-        /* XXX: how to report the error? */
-        return;
+    if (bi) {
+        client->info = g_malloc0(sizeof(*client->info));
+        client->info->base = bi;
     }
-
-    client->info = QOBJECT(qdict);
 }
 
-static void vnc_qmp_event(VncState *vs, MonitorEvent event)
+static void vnc_qmp_event(VncState *vs, QAPIEvent event)
 {
-    QDict *server;
-    QObject *data;
+    VncServerInfo *si;
 
     if (!vs->info) {
         return;
     }
+    g_assert(vs->info->base);
 
-    server = qdict_new();
-    if (vnc_server_info_put(server) < 0) {
-        QDECREF(server);
+    si = vnc_server_info_get();
+    if (!si) {
         return;
     }
 
-    data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
-                              vs->info, QOBJECT(server));
-
-    monitor_protocol_event(event, data);
+    switch (event) {
+    case QAPI_EVENT_VNC_CONNECTED:
+        qapi_event_send_vnc_connected(si, vs->info->base, &error_abort);
+        break;
+    case QAPI_EVENT_VNC_INITIALIZED:
+        qapi_event_send_vnc_initialized(si, vs->info, &error_abort);
+        break;
+    case QAPI_EVENT_VNC_DISCONNECTED:
+        qapi_event_send_vnc_disconnected(si, vs->info, &error_abort);
+        break;
+    default:
+        break;
+    }
 
-    qobject_incref(vs->info);
-    qobject_decref(data);
+    qapi_free_VncServerInfo(si);
 }
 
 static VncClientInfo *qmp_query_vnc_client(const VncState *client)
@@ -321,9 +324,10 @@ static VncClientInfo *qmp_query_vnc_client(const VncState *client)
     }
 
     info = g_malloc0(sizeof(*info));
-    info->host = g_strdup(host);
-    info->service = g_strdup(serv);
-    info->family = g_strdup(inet_strfamily(sa.ss_family));
+    info->base = g_malloc0(sizeof(*info->base));
+    info->base->host = g_strdup(host);
+    info->base->service = g_strdup(serv);
+    info->base->family = inet_netfamily(sa.ss_family);
 
 #ifdef CONFIG_VNC_TLS
     if (client->tls.session && client->tls.dname) {
@@ -398,7 +402,7 @@ VncInfo *qmp_query_vnc(Error **errp)
         info->service = g_strdup(serv);
 
         info->has_family = true;
-        info->family = g_strdup(inet_strfamily(sa.ss_family));
+        info->family = inet_netfamily(sa.ss_family);
 
         info->has_auth = true;
         info->auth = g_strdup(vnc_auth_name(vnc_display));
@@ -1039,7 +1043,7 @@ void vnc_disconnect_finish(VncState *vs)
     vnc_jobs_join(vs); /* Wait encoding jobs */
 
     vnc_lock_output(vs);
-    vnc_qmp_event(vs, QEVENT_VNC_DISCONNECTED);
+    vnc_qmp_event(vs, QAPI_EVENT_VNC_DISCONNECTED);
 
     buffer_free(&vs->input);
     buffer_free(&vs->output);
@@ -1048,7 +1052,7 @@ void vnc_disconnect_finish(VncState *vs)
     buffer_free(&vs->ws_output);
 #endif /* CONFIG_VNC_WS */
 
-    qobject_decref(vs->info);
+    qapi_free_VncClientInfo(vs->info);
 
     vnc_zlib_clear(vs);
     vnc_tight_clear(vs);
@@ -2323,7 +2327,7 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
     vnc_flush(vs);
 
     vnc_client_cache_auth(vs);
-    vnc_qmp_event(vs, QEVENT_VNC_INITIALIZED);
+    vnc_qmp_event(vs, QAPI_EVENT_VNC_INITIALIZED);
 
     vnc_read_when(vs, protocol_client_msg, 1);
 
@@ -2846,7 +2850,7 @@ static void vnc_connect(VncDisplay *vd, int csock,
     }
 
     vnc_client_cache_addr(vs);
-    vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
+    vnc_qmp_event(vs, QAPI_EVENT_VNC_CONNECTED);
     vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING);
 
     vs->vd = vd;
diff --git a/ui/vnc.h b/ui/vnc.h
index 8da81b8d6e..07af9f73de 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -31,7 +31,6 @@
 #include "qemu/queue.h"
 #include "qemu/thread.h"
 #include "ui/console.h"
-#include "monitor/monitor.h"
 #include "audio/audio.h"
 #include "qemu/bitmap.h"
 #include <zlib.h>
@@ -40,6 +39,7 @@
 #include "keymaps.h"
 #include "vnc-palette.h"
 #include "vnc-enc-zrle.h"
+#include "qapi-types.h"
 
 // #define _VNC_DEBUG 1
 
@@ -292,7 +292,7 @@ struct VncState
     bool websocket;
 #endif /* CONFIG_VNC_WS */
 
-    QObject *info;
+    VncClientInfo *info;
 
     Buffer output;
     Buffer input;
diff --git a/util/Makefile.objs b/util/Makefile.objs
index df83b629a0..6b3c83b0eb 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -1,7 +1,7 @@
 util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
 util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win32.o
 util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o qemu-openpty.o
-util-obj-y += envlist.o path.o host-utils.o cache-utils.o module.o
+util-obj-y += envlist.o path.o host-utils.o module.o
 util-obj-y += bitmap.o bitops.o hbitmap.o
 util-obj-y += fifo8.o
 util-obj-y += acl.o
diff --git a/util/cache-utils.c b/util/cache-utils.c
deleted file mode 100644
index 047003008b..0000000000
--- a/util/cache-utils.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "qemu-common.h"
-#include "qemu/cache-utils.h"
-
-#if defined(_ARCH_PPC)
-struct qemu_cache_conf qemu_cache_conf = {
-    .dcache_bsize = 16,
-    .icache_bsize = 16
-};
-
-#if defined _AIX
-#include <sys/systemcfg.h>
-
-void qemu_cache_utils_init(void)
-{
-    qemu_cache_conf.icache_bsize = _system_configuration.icache_line;
-    qemu_cache_conf.dcache_bsize = _system_configuration.dcache_line;
-}
-
-#elif defined __linux__
-#include "qemu/osdep.h"
-#include "elf.h"
-
-void qemu_cache_utils_init(void)
-{
-    unsigned long dsize = qemu_getauxval(AT_DCACHEBSIZE);
-    unsigned long isize = qemu_getauxval(AT_ICACHEBSIZE);
-
-    if (dsize == 0 || isize == 0) {
-        if (dsize == 0) {
-            fprintf(stderr, "getauxval AT_DCACHEBSIZE failed\n");
-        }
-        if (isize == 0) {
-            fprintf(stderr, "getauxval AT_ICACHEBSIZE failed\n");
-        }
-        exit(1);
-
-    }
-    qemu_cache_conf.dcache_bsize = dsize;
-    qemu_cache_conf.icache_bsize = isize;
-}
-
-#elif defined __APPLE__
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-void qemu_cache_utils_init(void)
-{
-    size_t len;
-    unsigned cacheline;
-    int name[2] = { CTL_HW, HW_CACHELINE };
-
-    len = sizeof(cacheline);
-    if (sysctl(name, 2, &cacheline, &len, NULL, 0)) {
-        perror("sysctl CTL_HW HW_CACHELINE failed");
-    } else {
-        qemu_cache_conf.dcache_bsize = cacheline;
-        qemu_cache_conf.icache_bsize = cacheline;
-    }
-}
-
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-void qemu_cache_utils_init(void)
-{
-    size_t len = 4;
-    unsigned cacheline;
-
-    if (sysctlbyname ("machdep.cacheline_size", &cacheline, &len, NULL, 0)) {
-        fprintf(stderr, "sysctlbyname machdep.cacheline_size failed: %s\n",
-                strerror(errno));
-        exit(1);
-    }
-
-    qemu_cache_conf.dcache_bsize = cacheline;
-    qemu_cache_conf.icache_bsize = cacheline;
-}
-#endif
-
-#endif /* _ARCH_PPC */
diff --git a/util/getauxval.c b/util/getauxval.c
index 476c883b32..25f48e5456 100644
--- a/util/getauxval.c
+++ b/util/getauxval.c
@@ -48,24 +48,51 @@ typedef struct {
 
 static const ElfW_auxv_t *auxv;
 
-void qemu_init_auxval(char **envp)
+static const ElfW_auxv_t *qemu_init_auxval(void)
 {
-    /* The auxiliary vector is located just beyond the initial environment.  */
-    while (*envp++ != NULL) {
-        continue;
+    ElfW_auxv_t *a;
+    ssize_t size = 512, r, ofs;
+    int fd;
+
+    /* Allocate some initial storage.  Make sure the first entry is set
+       to end-of-list, so that we've got a valid list in case of error.  */
+    auxv = a = g_malloc(size);
+    a[0].a_type = 0;
+    a[0].a_val = 0;
+
+    fd = open("/proc/self/auxv", O_RDONLY);
+    if (fd < 0) {
+        return a;
+    }
+
+    /* Read the first SIZE bytes.  Hopefully, this covers everything.  */
+    r = read(fd, a, size);
+
+    if (r == size) {
+        /* Continue to expand until we do get a partial read.  */
+        do {
+            ofs = size;
+            size *= 2;
+            auxv = a = g_realloc(a, size);
+            r = read(fd, (char *)a + ofs, ofs);
+        } while (r == ofs);
     }
-    auxv = (const ElfW_auxv_t *)envp;
+
+    close(fd);
+    return a;
 }
 
 unsigned long qemu_getauxval(unsigned long type)
 {
-    /* If we were able to find the auxiliary vector, use it.  */
-    if (auxv) {
-        const ElfW_auxv_t *a;
-        for (a = auxv; a->a_type != 0; a++) {
-            if (a->a_type == type) {
-                return a->a_val;
-            }
+    const ElfW_auxv_t *a = auxv;
+
+    if (unlikely(a == NULL)) {
+        a = qemu_init_auxval();
+    }
+
+    for (; a->a_type != 0; a++) {
+        if (a->a_type == type) {
+            return a->a_val;
         }
     }
 
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index a4a1e9d300..74cf0786e5 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -92,14 +92,14 @@ static void inet_setport(struct addrinfo *e, int port)
     }
 }
 
-const char *inet_strfamily(int family)
+NetworkAddressFamily inet_netfamily(int family)
 {
     switch (family) {
-    case PF_INET6: return "ipv6";
-    case PF_INET:  return "ipv4";
-    case PF_UNIX:  return "unix";
+    case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6;
+    case PF_INET:  return NETWORK_ADDRESS_FAMILY_IPV4;
+    case PF_UNIX:  return NETWORK_ADDRESS_FAMILY_UNIX;
     }
-    return "unknown";
+    return NETWORK_ADDRESS_FAMILY_UNKNOWN;
 }
 
 int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
diff --git a/vl.c b/vl.c
index 32887559be..a1686ef6c4 100644
--- a/vl.c
+++ b/vl.c
@@ -82,7 +82,6 @@ int main(int argc, char **argv)
 #include "qemu/timer.h"
 #include "sysemu/char.h"
 #include "qemu/bitmap.h"
-#include "qemu/cache-utils.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
 #include "migration/block.h"
@@ -117,6 +116,8 @@ int main(int argc, char **argv)
 #include "ui/qemu-spice.h"
 #include "qapi/string-input-visitor.h"
 #include "qapi/opts-visitor.h"
+#include "qom/object_interfaces.h"
+#include "qapi-event.h"
 
 #define DEFAULT_RAM_SIZE 128
 
@@ -381,6 +382,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "kvm-type",
             .type = QEMU_OPT_STRING,
             .help = "Specifies the KVM virtualization mode (HV, PR)",
+        },{
+            .name = PC_MACHINE_MAX_RAM_BELOW_4G,
+            .type = QEMU_OPT_SIZE,
+            .help = "maximum ram below the 4G boundary (32bit boundary)",
         },
         { /* End of list */ }
     },
@@ -734,7 +739,7 @@ void vm_start(void)
      * the STOP event.
      */
     if (runstate_is_running()) {
-        monitor_protocol_event(QEVENT_STOP, NULL);
+        qapi_event_send_stop(&error_abort);
     } else {
         cpu_enable_ticks();
         runstate_set(RUN_STATE_RUNNING);
@@ -742,7 +747,7 @@ void vm_start(void)
         resume_all_vcpus();
     }
 
-    monitor_protocol_event(QEVENT_RESUME, NULL);
+    qapi_event_send_resume(&error_abort);
 }
 
 
@@ -786,15 +791,6 @@ int qemu_timedate_diff(struct tm *tm)
     return seconds - time(NULL);
 }
 
-void rtc_change_mon_event(struct tm *tm)
-{
-    QObject *data;
-
-    data = qobject_from_jsonf("{ 'offset': %d }", qemu_timedate_diff(tm));
-    monitor_protocol_event(QEVENT_RTC_CHANGE, data);
-    qobject_decref(data);
-}
-
 static void configure_rtc_date_offset(const char *startdate, int legacy)
 {
     time_t rtc_start_date;
@@ -1846,7 +1842,7 @@ void qemu_system_reset(bool report)
         qemu_devices_reset();
     }
     if (report) {
-        monitor_protocol_event(QEVENT_RESET, NULL);
+        qapi_event_send_reset(&error_abort);
     }
     cpu_synchronize_all_post_reset();
 }
@@ -1867,7 +1863,7 @@ static void qemu_system_suspend(void)
     pause_all_vcpus();
     notifier_list_notify(&suspend_notifiers, NULL);
     runstate_set(RUN_STATE_SUSPENDED);
-    monitor_protocol_event(QEVENT_SUSPEND, NULL);
+    qapi_event_send_suspend(&error_abort);
 }
 
 void qemu_system_suspend_request(void)
@@ -1930,7 +1926,7 @@ void qemu_system_shutdown_request(void)
 
 static void qemu_system_powerdown(void)
 {
-    monitor_protocol_event(QEVENT_POWERDOWN, NULL);
+    qapi_event_send_powerdown(&error_abort);
     notifier_list_notify(&powerdown_notifiers, NULL);
 }
 
@@ -1962,7 +1958,7 @@ static bool main_loop_should_exit(void)
     }
     if (qemu_shutdown_requested()) {
         qemu_kill_report();
-        monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
+        qapi_event_send_shutdown(&error_abort);
         if (no_shutdown) {
             vm_stop(RUN_STATE_SHUTDOWN);
         } else {
@@ -1985,7 +1981,7 @@ static bool main_loop_should_exit(void)
         notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
         wakeup_reason = QEMU_WAKEUP_REASON_NONE;
         resume_all_vcpus();
-        monitor_protocol_event(QEVENT_WAKEUP, NULL);
+        qapi_event_send_wakeup(&error_abort);
     }
     if (qemu_powerdown_requested()) {
         qemu_system_powerdown();
@@ -2975,9 +2971,6 @@ int main(int argc, char **argv, char **envp)
 
     rtc_clock = QEMU_CLOCK_HOST;
 
-    qemu_init_auxval(envp);
-    qemu_cache_utils_init();
-
     QLIST_INIT (&vm_change_state_head);
     os_setup_early_signal_handling();
 
diff --git a/xen-hvm-stub.c b/xen-hvm-stub.c
index 4eb27b5f2b..2d98696e72 100644
--- a/xen-hvm-stub.c
+++ b/xen-hvm-stub.c
@@ -51,7 +51,8 @@ void xen_modified_memory(ram_addr_t start, ram_addr_t length)
 {
 }
 
-int xen_hvm_init(MemoryRegion **ram_memory)
+int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
+                 MemoryRegion **ram_memory)
 {
     return 0;
 }
diff --git a/xen-hvm.c b/xen-hvm.c
index aac38efb09..bafdf1283f 100644
--- a/xen-hvm.c
+++ b/xen-hvm.c
@@ -155,30 +155,43 @@ qemu_irq *xen_interrupt_controller_init(void)
 
 /* Memory Ops */
 
-static void xen_ram_init(ram_addr_t ram_size, MemoryRegion **ram_memory_p)
+static void xen_ram_init(ram_addr_t *below_4g_mem_size,
+                         ram_addr_t *above_4g_mem_size,
+                         ram_addr_t ram_size, MemoryRegion **ram_memory_p)
 {
     MemoryRegion *sysmem = get_system_memory();
-    ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
     ram_addr_t block_len;
+    uint64_t user_lowmem = object_property_get_int(qdev_get_machine(),
+                                                   PC_MACHINE_MAX_RAM_BELOW_4G,
+                                                   &error_abort);
 
-    block_len = ram_size;
-    if (ram_size >= HVM_BELOW_4G_RAM_END) {
-        /* Xen does not allocate the memory continuously, and keep a hole at
-         * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
+    /* Handle the machine opt max-ram-below-4g.  It is basicly doing
+     * min(xen limit, user limit).
+     */
+    if (HVM_BELOW_4G_RAM_END <= user_lowmem) {
+        user_lowmem = HVM_BELOW_4G_RAM_END;
+    }
+
+    if (ram_size >= user_lowmem) {
+        *above_4g_mem_size = ram_size - user_lowmem;
+        *below_4g_mem_size = user_lowmem;
+    } else {
+        *above_4g_mem_size = 0;
+        *below_4g_mem_size = ram_size;
+    }
+    if (!*above_4g_mem_size) {
+        block_len = ram_size;
+    } else {
+        /*
+         * Xen does not allocate the memory continuously, it keeps a
+         * hole of the size computed above or passed in.
          */
-        block_len += HVM_BELOW_4G_MMIO_LENGTH;
+        block_len = (1ULL << 32) + *above_4g_mem_size;
     }
     memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
     *ram_memory_p = &ram_memory;
     vmstate_register_ram_global(&ram_memory);
 
-    if (ram_size >= HVM_BELOW_4G_RAM_END) {
-        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
-        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
-    } else {
-        below_4g_mem_size = ram_size;
-    }
-
     memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k",
                              &ram_memory, 0, 0xa0000);
     memory_region_add_subregion(sysmem, 0, &ram_640k);
@@ -189,12 +202,13 @@ static void xen_ram_init(ram_addr_t ram_size, MemoryRegion **ram_memory_p)
      * the Options ROM, so it is registered here as RAM.
      */
     memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
-                             &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
+                             &ram_memory, 0xc0000,
+                             *below_4g_mem_size - 0xc0000);
     memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
-    if (above_4g_mem_size > 0) {
+    if (*above_4g_mem_size > 0) {
         memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
                                  &ram_memory, 0x100000000ULL,
-                                 above_4g_mem_size);
+                                 *above_4g_mem_size);
         memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
     }
 }
@@ -958,7 +972,8 @@ static void xen_wakeup_notifier(Notifier *notifier, void *data)
     xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
 }
 
-int xen_hvm_init(MemoryRegion **ram_memory)
+int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size,
+                 MemoryRegion **ram_memory)
 {
     int i, rc;
     unsigned long ioreq_pfn;
@@ -1036,7 +1051,7 @@ int xen_hvm_init(MemoryRegion **ram_memory)
 
     /* Init RAM management */
     xen_map_cache_init(xen_phys_offset_to_gaddr, state);
-    xen_ram_init(ram_size, ram_memory);
+    xen_ram_init(below_4g_mem_size, above_4g_mem_size, ram_size, ram_memory);
 
     qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);